From 8d2dab109352f254fb36251232a42c60f3a1b05e Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 5 Jul 2009 13:56:31 +0400 Subject: [PATCH 01/33] [8119] Speedup code and prevent crash at pet stats reset in time owner not in world. --- src/game/Pet.cpp | 13 ++++++++----- src/shared/revision_nr.h | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 2f9cbfdba..32964c818 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -1459,13 +1459,16 @@ bool Pet::unlearnSpell(uint32 spell_id, bool learn_prev, bool clear_ab) { if(removeSpell(spell_id,learn_prev,clear_ab)) { - if(GetOwner()->GetTypeId() == TYPEID_PLAYER) + if(!m_loading) { - if(!m_loading) + if (Unit* owner = GetOwner()) { - WorldPacket data(SMSG_PET_REMOVED_SPELL, 4); - data << uint32(spell_id); - ((Player*)GetOwner())->GetSession()->SendPacket(&data); + if(owner->GetTypeId() == TYPEID_PLAYER) + { + WorldPacket data(SMSG_PET_REMOVED_SPELL, 4); + data << uint32(spell_id); + ((Player*)owner)->GetSession()->SendPacket(&data); + } } } return true; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 4312804a9..97cd30eb6 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8118" + #define REVISION_NR "8119" #endif // __REVISION_NR_H__ From c853c2e26141e5b89f6eae9c621f39a98449ba71 Mon Sep 17 00:00:00 2001 From: Thyros Date: Sun, 5 Jul 2009 00:14:32 +0200 Subject: [PATCH 02/33] [8120] - Typo for Linux, thanks to win32. (cherry picked from commit 389894bcee8a60f7dd59baf06f4a75e5098e9a69) Signed-off-by: VladimirMangos --- Makefile.am | 22 +++++++++++----------- src/shared/revision_nr.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Makefile.am b/Makefile.am index b63cd3472..f26fa667f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,17 +20,6 @@ SUBDIRS = dep doc sql src ## Additional files to include when running 'make dist' -# Win32 project workspace for Visual Studio .NET 2003 -EXTRA_DIST = \ - win/mangosdVC71.sln \ - win/VC71/framework.vcproj \ - win/VC71/game.vcproj \ - win/VC71/mangosd.vcproj \ - win/VC71/realmd.vcproj \ - win/VC71/shared.vcproj \ - win/VC71/zlib.vcproj \ - win/VC71/g3dlite.vcproj - # Win32 project workspace for Visual Studio .NET 2005 EXTRA_DIST += \ win/mangosdVC80.sln \ @@ -53,3 +42,14 @@ EXTRA_DIST += \ win/VC90/zlib.vcproj \ win/VC90/g3dlite.vcproj +# Win32 project workspace for Visual Studio .NET 2010 +EXTRA_DIST = \ + win/mangosdVC100.sln \ + win/VC100/framework.vcxproj \ + win/VC100/game.vcxproj \ + win/VC100/mangosd.vcxproj \ + win/VC100/realmd.vcxproj \ + win/VC100/shared.vcxproj \ + win/VC100/zlib.vcxproj \ + win/VC100/g3dlite.vcxproj + diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 97cd30eb6..e985a0bcd 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8119" + #define REVISION_NR "8120" #endif // __REVISION_NR_H__ From b4302d61e5a89b8f0cb6945ff96103a32d86845e Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 5 Jul 2009 17:43:39 +0400 Subject: [PATCH 03/33] [8121] Cleanup and more safe code in Player::BuyItemFromVendor use. * Move bag search by bag guid code to WorldSession::HandleBuyItemInSlotOpcode * Really reject unexisted bag cases. --- src/game/ItemHandler.cpp | 26 ++++++++++++- src/game/Player.cpp | 80 ++++++++++++++-------------------------- src/game/Player.h | 2 +- src/shared/revision_nr.h | 2 +- 4 files changed, 55 insertions(+), 55 deletions(-) diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 5a9ff8172..671fba434 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -672,7 +672,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/Player.cpp b/src/game/Player.cpp index a8d4a1674..5dc4939fb 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -17144,16 +17144,16 @@ 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; - 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; @@ -17175,7 +17175,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; @@ -17184,39 +17184,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; @@ -17246,62 +17246,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 (int 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() ) - { - 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); @@ -17315,9 +17291,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; @@ -17325,19 +17301,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) { @@ -17346,7 +17322,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); @@ -17368,7 +17344,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint return false; } - return crItem->maxcount!=0; + return crItem->maxcount != 0; } uint32 Player::GetMaxPersonalArenaRatingRequirement() diff --git a/src/game/Player.h b/src/game/Player.h index ca9f3a234..05b662ea3 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1186,7 +1186,7 @@ class MANGOS_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; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index e985a0bcd..e9069b9a8 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8120" + #define REVISION_NR "8121" #endif // __REVISION_NR_H__ From 91e4d7324a424512c56c1c165fa9795ada0a8dd8 Mon Sep 17 00:00:00 2001 From: ApoC Date: Sun, 5 Jul 2009 13:35:54 +0200 Subject: [PATCH 04/33] [8122] Permit read-only acces to player's cooldowns via GetSpellCooldownMap() Signed-off-by: ApoC --- src/game/Player.h | 2 ++ src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/game/Player.h b/src/game/Player.h index 05b662ea3..44d93408f 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1492,6 +1492,8 @@ class MANGOS_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 const* spell = NULL); template T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index e9069b9a8..c904f3ac4 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8121" + #define REVISION_NR "8122" #endif // __REVISION_NR_H__ From 2273f7abe0d50a3d7151f8fa330934b2d2a3ca8b Mon Sep 17 00:00:00 2001 From: ApoC Date: Sun, 5 Jul 2009 14:28:03 +0200 Subject: [PATCH 05/33] [8123] Introduced new method Player::RemoveSpellCategoryCooldown(uint32,bool) This method removes cooldown from all spells from given category and optionaly sends update to player. By default update is not send. Signed-off-by: ApoC --- src/game/Player.cpp | 16 ++++++++++++++++ src/game/Player.h | 1 + src/shared/revision_nr.h | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 5dc4939fb..65a879d5d 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -3352,6 +3352,22 @@ void Player::RemoveSpellCooldown( uint32 spell_id, bool update /* = false */ ) SendClearCooldown(spell_id, this); } +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 diff --git a/src/game/Player.h b/src/game/Player.h index 44d93408f..a30471d0a 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1517,6 +1517,7 @@ class MANGOS_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 RemoveArenaSpellCooldowns(); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c904f3ac4..29a61a3dd 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8122" + #define REVISION_NR "8123" #endif // __REVISION_NR_H__ From f064ef9c4932eff7132664b337bb176fe55518c3 Mon Sep 17 00:00:00 2001 From: ApoC Date: Sun, 5 Jul 2009 14:30:00 +0200 Subject: [PATCH 06/33] [8124] Fixed removing cooldown of 23922 and ranks by 50227 Signed-off-by: ApoC --- src/game/Unit.cpp | 8 ++++++++ src/shared/revision_nr.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 234fdbdb0..0deffac6a 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -6767,6 +6767,14 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB return false; break; } + // Sword and Board + case 50227: + { + // Remove cooldown on Shield Slam + if (GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->RemoveSpellCategoryCooldown(1209, true); + break; + } // Brain Freeze case 57761: { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 29a61a3dd..b7f1768d3 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8123" + #define REVISION_NR "8124" #endif // __REVISION_NR_H__ From 60fe7928669cb3d829f62c595c074bb76ccbfdc9 Mon Sep 17 00:00:00 2001 From: ApoC Date: Sun, 5 Jul 2009 17:31:26 +0200 Subject: [PATCH 07/33] [8125] Optimized spell cooldowns remove. Traverse only active cooldowns instead of whole player spell map. Signed-off-by: ApoC --- src/game/SpellEffects.cpp | 36 ++++++++++++++++++------------------ src/shared/revision_nr.h | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 6cbb6cbd6..140201d11 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1191,21 +1191,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; } @@ -1440,14 +1438,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 & UI64LIT(0x0000024000000860))) - ((Player*)m_caster)->RemoveSpellCooldown(classspell,true); + ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true); + else + ++itr; } return; } @@ -1491,14 +1490,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/shared/revision_nr.h b/src/shared/revision_nr.h index b7f1768d3..e82d7c065 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8124" + #define REVISION_NR "8125" #endif // __REVISION_NR_H__ From 715470a89876a64e62ede0bf1e1a42c6e33a65d1 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 5 Jul 2009 19:58:26 +0400 Subject: [PATCH 08/33] [8126] Improvemets in player/pet/charter name checks. * Implement new config options for minimal player/pet/charter name length (2 by default) * Better error reporting at problems in names. * Add check from max pet/charter name length (same as for player names at client side) --- src/game/CharacterHandler.cpp | 37 +++++++++++++++-------------- src/game/Level3.cpp | 12 +++++----- src/game/ObjectMgr.cpp | 40 ++++++++++++++++++++++---------- src/game/ObjectMgr.h | 8 ++++--- src/game/Pet.h | 3 +++ src/game/PetHandler.cpp | 5 ++-- src/game/Player.cpp | 3 ++- src/game/PlayerDump.cpp | 13 ++++++----- src/game/World.cpp | 21 +++++++++++++++++ src/game/World.h | 3 +++ src/mangosd/mangosd.conf.dist.in | 15 ++++++++++++ src/shared/revision_nr.h | 2 +- 12 files changed, 114 insertions(+), 48 deletions(-) diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index a0799d0bc..f8bd12d02 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -244,30 +244,31 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) } // prevent character creating with invalid name - if(!normalizePlayerName(name)) + if (!normalizePlayerName(name)) { - data << (uint8)CHAR_NAME_INVALID_CHARACTER; + data << (uint8)CHAR_NAME_NO_NAME; SendPacket( &data ); sLog.outError("Account:[%d] but tried to Create character with empty [name] ",GetAccountId()); return; } // check name limitations - if(!ObjectMgr::IsValidName(name,true)) + uint8 res = ObjectMgr::CheckPlayerName(name,true); + if (res != CHAR_NAME_SUCCESS) { - data << (uint8)CHAR_NAME_INVALID_CHARACTER; + data << uint8(res); SendPacket( &data ); return; } - if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(name)) + if (GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(name)) { data << (uint8)CHAR_NAME_RESERVED; SendPacket( &data ); return; } - if(objmgr.GetPlayerGUIDByName(name)) + if (objmgr.GetPlayerGUIDByName(name)) { data << (uint8)CHAR_CREATE_NAME_IN_USE; SendPacket( &data ); @@ -275,7 +276,7 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) } QueryResult *resultacct = loginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId()); - if ( resultacct ) + if (resultacct) { Field *fields=resultacct->Fetch(); uint32 acctcharcount = fields[0].GetUInt32(); @@ -967,7 +968,7 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recv_data) recv_data >> newname; // prevent character rename to invalid name - if(!normalizePlayerName(newname)) + if (!normalizePlayerName(newname)) { WorldPacket data(SMSG_CHAR_RENAME, 1); data << uint8(CHAR_NAME_NO_NAME); @@ -975,16 +976,17 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recv_data) return; } - if(!ObjectMgr::IsValidName(newname, true)) + uint8 res = ObjectMgr::CheckPlayerName(newname,true); + if (res != CHAR_NAME_SUCCESS) { WorldPacket data(SMSG_CHAR_RENAME, 1); - data << uint8(CHAR_NAME_INVALID_CHARACTER); + data << uint8(res); SendPacket( &data ); return; } // check name limitations - if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname)) + if (GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname)) { WorldPacket data(SMSG_CHAR_RENAME, 1); data << uint8(CHAR_NAME_RESERVED); @@ -1240,7 +1242,7 @@ void WorldSession::HandleCharCustomize(WorldPacket& recv_data) } // prevent character rename to invalid name - if(!normalizePlayerName(newname)) + if (!normalizePlayerName(newname)) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); data << uint8(CHAR_NAME_NO_NAME); @@ -1248,16 +1250,17 @@ void WorldSession::HandleCharCustomize(WorldPacket& recv_data) return; } - if(!ObjectMgr::IsValidName(newname,true)) + uint8 res = ObjectMgr::CheckPlayerName(newname,true); + if (res != CHAR_NAME_SUCCESS) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); - data << uint8(CHAR_NAME_INVALID_CHARACTER); + data << uint8(res); SendPacket( &data ); return; } // check name limitations - if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname)) + if (GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname)) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); data << uint8(CHAR_NAME_RESERVED); @@ -1266,9 +1269,9 @@ void WorldSession::HandleCharCustomize(WorldPacket& recv_data) } // character with this name already exist - if(uint64 newguid = objmgr.GetPlayerGUIDByName(newname)) + if (uint64 newguid = objmgr.GetPlayerGUIDByName(newname)) { - if(newguid != guid) + if (newguid != guid) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); data << uint8(CHAR_CREATE_NAME_IN_USE); diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index fe2eaaad2..ceb1d6e19 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -5623,18 +5623,18 @@ bool ChatHandler::HandlePDumpLoadCommand(const char *args) char* name_str = strtok(NULL, " "); std::string name; - if(name_str) + if (name_str) { name = name_str; // normalize the name if specified and check if it exists - if(!normalizePlayerName(name)) + if (!normalizePlayerName(name)) { PSendSysMessage(LANG_INVALID_CHARACTER_NAME); SetSentErrorMessage(true); return false; } - if(!ObjectMgr::IsValidName(name,true)) + if (ObjectMgr::CheckPlayerName(name,true) != CHAR_NAME_SUCCESS) { PSendSysMessage(LANG_INVALID_CHARACTER_NAME); SetSentErrorMessage(true); @@ -5646,17 +5646,17 @@ bool ChatHandler::HandlePDumpLoadCommand(const char *args) uint32 guid = 0; - if(guid_str) + if (guid_str) { guid = atoi(guid_str); - if(!guid) + if (!guid) { PSendSysMessage(LANG_INVALID_CHARACTER_GUID); SetSentErrorMessage(true); return false; } - if(objmgr.GetPlayerAccountIdByGUID(guid)) + if (objmgr.GetPlayerAccountIdByGUID(guid)) { PSendSysMessage(LANG_CHARACTER_GUID_IN_USE,guid); SetSentErrorMessage(true); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index a56a2fa6d..7671ae859 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -6645,18 +6645,24 @@ bool isValidString(std::wstring wstr, uint32 strictMask, bool numericOrSpace, bo return false; } -bool ObjectMgr::IsValidName( const std::string& name, bool create ) +uint8 ObjectMgr::CheckPlayerName( const std::string& name, bool create ) { std::wstring wname; if(!Utf8toWStr(name,wname)) - return false; + return CHAR_NAME_INVALID_CHARACTER; - if(wname.size() < 1 || wname.size() > MAX_PLAYER_NAME) - return false; + if(wname.size() > MAX_PLAYER_NAME) + return CHAR_NAME_TOO_LONG; + + uint32 minName = sWorld.getConfig(CONFIG_MIN_PLAYER_NAME); + if(wname.size() < minName) + return CHAR_NAME_TOO_SHORT; uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_PLAYER_NAMES); - - return isValidString(wname,strictMask,false,create); + if(!isValidString(wname,strictMask,false,create)) + return CHAR_NAME_MIXED_LANGUAGES; + + return CHAR_NAME_SUCCESS; } bool ObjectMgr::IsValidCharterName( const std::string& name ) @@ -6665,7 +6671,11 @@ bool ObjectMgr::IsValidCharterName( const std::string& name ) if(!Utf8toWStr(name,wname)) return false; - if(wname.size() < 1) + if(wname.size() > MAX_CHARTER_NAME) + return false; + + uint32 minName = sWorld.getConfig(CONFIG_MIN_CHARTER_NAME); + if(wname.size() < minName) return false; uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_CHARTER_NAMES); @@ -6673,18 +6683,24 @@ bool ObjectMgr::IsValidCharterName( const std::string& name ) return isValidString(wname,strictMask,true); } -bool ObjectMgr::IsValidPetName( const std::string& name ) +PetNameInvalidReason ObjectMgr::CheckPetName( const std::string& name ) { std::wstring wname; if(!Utf8toWStr(name,wname)) - return false; + return PET_NAME_INVALID; - if(wname.size() < 1) - return false; + if(wname.size() > MAX_PET_NAME) + return PET_NAME_TOO_LONG; + + uint32 minName = sWorld.getConfig(CONFIG_MIN_PET_NAME); + if(wname.size() < minName) + return PET_NAME_TOO_SHORT; uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_PET_NAMES); + if(!isValidString(wname,strictMask,false)) + return PET_NAME_MIXED_LANGUAGES; - return isValidString(wname,strictMask,false); + return PET_NAME_SUCCESS; } int ObjectMgr::GetIndexForLocale( LocaleConstant loc ) diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index c869a191f..7aeac8405 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -279,8 +279,10 @@ enum SkillRangeType SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial); -#define MAX_PLAYER_NAME 12 // max allowed by client name length +#define MAX_PLAYER_NAME 12 // max allowed by client name length #define MAX_INTERNAL_PLAYER_NAME 15 // max server internal player name length ( > MAX_PLAYER_NAME for support declined names ) +#define MAX_PET_NAME 12 // max allowed by client name length +#define MAX_CHARTER_NAME 24 // max allowed by client name length bool normalizePlayerName(std::string& name); @@ -693,9 +695,9 @@ class ObjectMgr bool IsReservedName(const std::string& name) const; // name with valid structure and symbols - static bool IsValidName( const std::string& name, bool create = false ); + static uint8 CheckPlayerName( const std::string& name, bool create = false ); + static PetNameInvalidReason CheckPetName( const std::string& name ); static bool IsValidCharterName( const std::string& name ); - static bool IsValidPetName( const std::string& name ); static bool CheckDeclinedNames(std::wstring mainpart, DeclinedName const& names); diff --git a/src/game/Pet.h b/src/game/Pet.h index bbe878d1d..303d3ba50 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -91,6 +91,9 @@ enum PetTalk enum PetNameInvalidReason { + // custom, not send + PET_NAME_SUCCESS = 0, + PET_NAME_INVALID = 1, PET_NAME_NO_NAME = 2, PET_NAME_TOO_SHORT = 3, diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index a9f464b40..b665a0584 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -401,9 +401,10 @@ void WorldSession::HandlePetRename( WorldPacket & recv_data ) pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo() ) return; - if(!ObjectMgr::IsValidPetName(name)) + PetNameInvalidReason res = ObjectMgr::CheckPetName(name); + if(res != PET_NAME_SUCCESS) { - SendPetNameInvalid(PET_NAME_INVALID, name, NULL); + SendPetNameInvalid(res, name, NULL); return; } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 65a879d5d..9fc2d93b4 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -14043,7 +14043,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) m_name = fields[3].GetCppString(); // check name limitations - if(!ObjectMgr::IsValidName(m_name) || (GetSession()->GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(m_name))) + if (ObjectMgr::CheckPlayerName(m_name) != CHAR_NAME_SUCCESS || + GetSession()->GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(m_name)) { delete result; CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid ='%u'", uint32(AT_LOGIN_RENAME),guid); diff --git a/src/game/PlayerDump.cpp b/src/game/PlayerDump.cpp index 42a512689..5319ac8d7 100644 --- a/src/game/PlayerDump.cpp +++ b/src/game/PlayerDump.cpp @@ -393,7 +393,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s { QueryResult *result = CharacterDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%d'", account); uint8 charcount = 0; - if ( result ) + if (result) { Field *fields=result->Fetch(); charcount = fields[0].GetUInt8(); @@ -405,7 +405,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s } FILE *fin = fopen(file.c_str(), "r"); - if(!fin) + if (!fin) return DUMP_FILE_OPEN_ERROR; QueryResult * result = NULL; @@ -413,7 +413,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s // make sure the same guid doesn't already exist and is safe to use bool incHighest = true; - if(guid != 0 && guid < objmgr.m_hiCharGuid) + if (guid != 0 && guid < objmgr.m_hiCharGuid) { result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE guid = '%d'", guid); if (result) @@ -427,10 +427,10 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s guid = objmgr.m_hiCharGuid; // normalize the name if specified and check if it exists - if(!normalizePlayerName(name)) + if (!normalizePlayerName(name)) name = ""; - if(ObjectMgr::IsValidName(name,true)) + if (ObjectMgr::CheckPlayerName(name,true) == CHAR_NAME_SUCCESS) { CharacterDatabase.escape_string(name); // for safe, we use name only for sql quearies anyway result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE name = '%s'", name.c_str()); @@ -440,7 +440,8 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s delete result; } } - else name = ""; + else + name = ""; // name encoded or empty diff --git a/src/game/World.cpp b/src/game/World.cpp index 87b06e7b8..bf20ccf08 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -624,6 +624,27 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_STRICT_CHARTER_NAMES] = sConfig.GetIntDefault ("StrictCharterNames", 0); m_configs[CONFIG_STRICT_PET_NAMES] = sConfig.GetIntDefault ("StrictPetNames", 0); + m_configs[CONFIG_MIN_PLAYER_NAME] = sConfig.GetIntDefault ("MinPlayerName", 2); + if(m_configs[CONFIG_MIN_PLAYER_NAME] < 1 || m_configs[CONFIG_MIN_PLAYER_NAME] > MAX_PLAYER_NAME) + { + sLog.outError("MinPlayerName (%i) must be in range 1..%u. Set to 2.",m_configs[CONFIG_MIN_PLAYER_NAME],MAX_PLAYER_NAME); + m_configs[CONFIG_MIN_PLAYER_NAME] = 2; + } + + m_configs[CONFIG_MIN_CHARTER_NAME] = sConfig.GetIntDefault ("MinCharterName", 2); + if(m_configs[CONFIG_MIN_CHARTER_NAME] < 1 || m_configs[CONFIG_MIN_CHARTER_NAME] > MAX_CHARTER_NAME) + { + sLog.outError("MinCharterName (%i) must be in range 1..%u. Set to 2.",m_configs[CONFIG_MIN_CHARTER_NAME],MAX_CHARTER_NAME); + m_configs[CONFIG_MIN_CHARTER_NAME] = 2; + } + + m_configs[CONFIG_MIN_PET_NAME] = sConfig.GetIntDefault ("MinPetName", 2); + if(m_configs[CONFIG_MIN_PET_NAME] < 1 || m_configs[CONFIG_MIN_PET_NAME] > MAX_PET_NAME) + { + sLog.outError("MinPetName (%i) must be in range 1..%u. Set to 2.",m_configs[CONFIG_MIN_PET_NAME],MAX_PET_NAME); + m_configs[CONFIG_MIN_PET_NAME] = 2; + } + m_configs[CONFIG_CHARACTERS_CREATING_DISABLED] = sConfig.GetIntDefault ("CharactersCreatingDisabled", 0); m_configs[CONFIG_CHARACTERS_PER_REALM] = sConfig.GetIntDefault("CharactersPerRealm", 10); diff --git a/src/game/World.h b/src/game/World.h index 5fdfb00ad..8c2f2df14 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -107,6 +107,9 @@ enum WorldConfigs CONFIG_STRICT_PLAYER_NAMES, CONFIG_STRICT_CHARTER_NAMES, CONFIG_STRICT_PET_NAMES, + CONFIG_MIN_PLAYER_NAME, + CONFIG_MIN_CHARTER_NAME, + CONFIG_MIN_PET_NAME, CONFIG_CHARACTERS_CREATING_DISABLED, CONFIG_CHARACTERS_PER_ACCOUNT, CONFIG_CHARACTERS_PER_REALM, diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index 69643c7cf..de5dbe22d 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -396,6 +396,18 @@ LogColors = "" # (included in client by default, with active official localization or custom localization fonts in clientdir/Fonts). # 3 basic latin characters + server timezone specific # +# MinPlayerName +# Minimal name length (1..12) +# Default: 2 +# +# MinCharterName +# Minimal name length (1..24) +# Default: 2 +# +# MinPetName +# Minimal name length (1..12) +# Default: 2 +# # CharactersCreatingDisabled # Disable characters creating for specific team or any (non-player accounts not affected) # Default: 0 - enabled @@ -579,6 +591,9 @@ DeclinedNames = 0 StrictPlayerNames = 0 StrictCharterNames = 0 StrictPetNames = 0 +MinPlayerName = 2 +MinCharterName = 2 +MinPetName = 2 CharactersCreatingDisabled = 0 CharactersPerAccount = 50 CharactersPerRealm = 10 diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index e82d7c065..c6f213801 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8125" + #define REVISION_NR "8126" #endif // __REVISION_NR_H__ From 572c6d99a74b13fd028d0c3cd14c5113b66f99e8 Mon Sep 17 00:00:00 2001 From: ApoC Date: Sun, 5 Jul 2009 19:06:43 +0200 Subject: [PATCH 09/33] [8127] Fixed detection of spell 20243 Signed-off-by: ApoC --- src/game/SpellEffects.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 140201d11..0ed28d587 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -4331,7 +4331,7 @@ void Spell::EffectWeaponDmg(uint32 i) spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized); } // Devastate bonus and sunder armor refresh - else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508) + else if(m_spellInfo->SpellVisual[0] == 12295 && m_spellInfo->SpellIconID == 1508) { uint32 stack = 0; // Need refresh all Sunder Armor auras from this caster diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c6f213801..ac3c12355 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8126" + #define REVISION_NR "8127" #endif // __REVISION_NR_H__ From de974e5537d764f9b4084816f3a983c70e239ab4 Mon Sep 17 00:00:00 2001 From: Thyros Date: Sun, 5 Jul 2009 21:08:10 +0400 Subject: [PATCH 10/33] [8128] Typos in typos fix [8120]. Signed-off-by: VladimirMangos --- Makefile.am | 4 ++-- src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index f26fa667f..767eda776 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,7 +21,7 @@ SUBDIRS = dep doc sql src ## Additional files to include when running 'make dist' # Win32 project workspace for Visual Studio .NET 2005 -EXTRA_DIST += \ +EXTRA_DIST = \ win/mangosdVC80.sln \ win/VC80/framework.vcproj \ win/VC80/game.vcproj \ @@ -43,7 +43,7 @@ EXTRA_DIST += \ win/VC90/g3dlite.vcproj # Win32 project workspace for Visual Studio .NET 2010 -EXTRA_DIST = \ +EXTRA_DIST += \ win/mangosdVC100.sln \ win/VC100/framework.vcxproj \ win/VC100/game.vcxproj \ diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index ac3c12355..12c079eea 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8127" + #define REVISION_NR "8128" #endif // __REVISION_NR_H__ From a2d9467428a68c4e9a7cc83abba88b4fff08fc64 Mon Sep 17 00:00:00 2001 From: ApoC Date: Sun, 5 Jul 2009 20:06:26 +0200 Subject: [PATCH 11/33] [8129] More work on spell 20243 * No need to loop over rest of auras if correct one found * Fixed spell not applied 58567 Signed-off-by: ApoC --- src/game/SpellEffects.cpp | 8 +++++++- src/shared/revision_nr.h | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 0ed28d587..c808c1fd9 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -4336,19 +4336,25 @@ void Spell::EffectWeaponDmg(uint32 i) uint32 stack = 0; // Need refresh all Sunder Armor auras from this caster Unit::AuraMap& suAuras = unitTarget->GetAuras(); + SpellEntry const *spellInfo; for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr) { - SpellEntry const *spellInfo = (*itr).second->GetSpellProto(); + spellInfo = (*itr).second->GetSpellProto(); if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000)) && (*itr).second->GetCasterGUID() == m_caster->GetGUID()) { (*itr).second->RefreshAura(); stack = (*itr).second->GetStackAmount(); + break; } } if (stack) spell_bonus += stack * CalculateDamage(2, unitTarget); + if (!stack || stack < spellInfo->StackAmount) + // Devastate causing Sunder Armor Effect + // and no need to cast over max stack amount + m_caster->CastSpell(unitTarget, 58567, true); } break; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 12c079eea..277d379df 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8128" + #define REVISION_NR "8129" #endif // __REVISION_NR_H__ From 61443d758320e747bbdb46d63d04da7638852f18 Mon Sep 17 00:00:00 2001 From: ApoC Date: Sun, 5 Jul 2009 20:52:17 +0200 Subject: [PATCH 12/33] [8130] Allow stacking spell 18820 with 1459 and ranks Signed-off-by: ApoC --- src/game/SpellMgr.cpp | 15 ++++++++++++--- src/shared/revision_nr.h | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 6f68c336d..1dd4544d6 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -334,7 +334,7 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex) case 11196: // Recently Bandaged return false; // some spells have unclear target modes for selection, so just make effect positive - case 27184: + case 27184: case 27190: case 27191: case 27201: @@ -1126,7 +1126,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons if(!spellInfo_1 || !spellInfo_2) return false; - if(spellInfo_1->Id == spellId_2) + if(spellId_1 == spellId_2) return false; //I think we don't check this correctly because i need a exception for spell: @@ -1193,6 +1193,11 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons break; } + case SPELLFAMILY_MAGE: + // Arcane Intellect and Insight + if( spellInfo_2->SpellIconID == 125 && spellInfo_1->Id == 18820 ) + return false; + break; case SPELLFAMILY_WARRIOR: { // Scroll of Protection and Defensive Stance (multi-family check) @@ -1274,6 +1279,10 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons if( spellInfo_1->Id == 11129 && spellInfo_2->SpellIconID == 33 && spellInfo_2->SpellVisual[0] == 321 ) return false; + // Arcane Intellect and Insight + if( spellInfo_1->SpellIconID == 125 && spellInfo_2->Id == 18820 ) + return false; + break; case SPELLFAMILY_WARLOCK: if( spellInfo_2->SpellFamilyName == SPELLFAMILY_WARLOCK ) @@ -2610,7 +2619,7 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell // Try search in next group groupEntry = sAreaGroupStore.LookupEntry(groupEntry->nextGroup); } - + if(!found) return SPELL_FAILED_INCORRECT_AREA; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 277d379df..64f9ce72a 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8129" + #define REVISION_NR "8130" #endif // __REVISION_NR_H__ From 6a574896f51bfe29276005710261367784569690 Mon Sep 17 00:00:00 2001 From: Lightguard Date: Sun, 5 Jul 2009 23:04:35 +0400 Subject: [PATCH 13/33] [8131] Some anti-cheating server side checks. * Loot in ghost state * Apply duplicate glyphs. Signed-off-by: VladimirMangos --- src/game/LootHandler.cpp | 4 ++++ src/game/Spell.cpp | 8 ++++++++ src/shared/revision_nr.h | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/game/LootHandler.cpp b/src/game/LootHandler.cpp index cfba29ad3..06c84aeff 100644 --- a/src/game/LootHandler.cpp +++ b/src/game/LootHandler.cpp @@ -247,6 +247,10 @@ void WorldSession::HandleLootOpcode( WorldPacket & recv_data ) uint64 guid; recv_data >> guid; + // Check possible cheat + if(!_player->isAlive()) + return; + GetPlayer()->SendLoot(guid, LOOT_CORPSE); } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 44fe64ac2..ae88927c8 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -4093,6 +4093,14 @@ SpellCastResult Spell::CheckCast(bool strict) break; } + case SPELL_EFFECT_APPLY_GLYPH: + { + uint32 glyphId = m_spellInfo->EffectMiscValue[i]; + if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyphId)) + if(m_caster->HasAura(gp->SpellId)) + return SPELL_FAILED_UNIQUE_GLYPH; + break; + } case SPELL_EFFECT_FEED_PET: { if (m_caster->GetTypeId() != TYPEID_PLAYER) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 64f9ce72a..9db875648 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8130" + #define REVISION_NR "8131" #endif // __REVISION_NR_H__ From ac051d10e9296e4bc4c45778409293f5bfda0696 Mon Sep 17 00:00:00 2001 From: Lightguard Date: Sun, 5 Jul 2009 23:39:15 +0400 Subject: [PATCH 14/33] [8132] Use real caster in some cases in Spell::DoSpellHitOnUnit. Signed-off-by: VladimirMangos --- src/game/Spell.cpp | 65 ++++++++++++++++++++-------------------- src/shared/revision_nr.h | 2 +- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index ae88927c8..b85946086 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1146,15 +1146,17 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) { - if(!unit || !effectMask) + if (!unit || !effectMask) return; + Unit* realCaster = m_originalCaster ? m_originalCaster : m_caster; + // Recheck immune (only for delayed spells) - if( m_spellInfo->speed && ( + if (m_spellInfo->speed && ( unit->IsImmunedToDamage(GetSpellSchoolMask(m_spellInfo)) || unit->IsImmunedToSpell(m_spellInfo))) { - m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_IMMUNE); + realCaster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_IMMUNE); return; } @@ -1164,67 +1166,65 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) ((Player*)unit)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, m_spellInfo->Id); } - if(m_caster->GetTypeId() == TYPEID_PLAYER) - { - ((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, unit); - } + if (realCaster->GetTypeId() == TYPEID_PLAYER) + ((Player*)realCaster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, unit); - if( m_caster != unit ) + if (realCaster != unit) { // Recheck UNIT_FLAG_NON_ATTACKABLE for delayed spells if (m_spellInfo->speed > 0.0f && unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) && unit->GetCharmerOrOwnerGUID() != m_caster->GetGUID()) { - m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE); + realCaster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE); return; } - if( !m_caster->IsFriendlyTo(unit) ) + if (!realCaster->IsFriendlyTo(unit)) { // for delayed spells ignore not visible explicit target - if(m_spellInfo->speed > 0.0f && unit == m_targets.getUnitTarget() && !unit->isVisibleForOrDetect(m_caster,false)) + if (m_spellInfo->speed > 0.0f && unit == m_targets.getUnitTarget() && + !unit->isVisibleForOrDetect(m_caster,false)) { - m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE); + realCaster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE); return; } unit->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - if( !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO) ) + if (!(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO)) { - if(!unit->IsStandState() && !unit->hasUnitState(UNIT_STAT_STUNNED)) + if (!unit->IsStandState() && !unit->hasUnitState(UNIT_STAT_STUNNED)) unit->SetStandState(UNIT_STAND_STATE_STAND); - if(!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI()) - ((Creature*)unit)->AI()->AttackedBy(m_caster); + if (!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI()) + ((Creature*)unit)->AI()->AttackedBy(realCaster); - unit->AddThreat(m_caster, 0.0f); - unit->SetInCombatWith(m_caster); - m_caster->SetInCombatWith(unit); + unit->AddThreat(realCaster, 0.0f); + unit->SetInCombatWith(realCaster); + realCaster->SetInCombatWith(unit); - if(Player *attackedPlayer = unit->GetCharmerOrOwnerPlayerOrPlayerItself()) - { - m_caster->SetContestedPvP(attackedPlayer); - } + if (Player *attackedPlayer = unit->GetCharmerOrOwnerPlayerOrPlayerItself()) + realCaster->SetContestedPvP(attackedPlayer); } } else { // for delayed spells ignore negative spells (after duel end) for friendly targets - if(m_spellInfo->speed > 0.0f && !IsPositiveSpell(m_spellInfo->Id)) + if (m_spellInfo->speed > 0.0f && !IsPositiveSpell(m_spellInfo->Id)) { - m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE); + realCaster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE); return; } // assisting case, healing and resurrection - if(unit->hasUnitState(UNIT_STAT_ATTACK_PLAYER)) - m_caster->SetContestedPvP(); - if( unit->isInCombat() && !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO) ) + if (unit->hasUnitState(UNIT_STAT_ATTACK_PLAYER)) + realCaster->SetContestedPvP(); + + if (unit->isInCombat() && !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO)) { - m_caster->SetInCombatState(unit->GetCombatTimer() > 0); - unit->getHostilRefManager().threatAssist(m_caster, 0.0f); + realCaster->SetInCombatState(unit->GetCombatTimer() > 0); + unit->getHostilRefManager().threatAssist(realCaster, 0.0f); } } } @@ -1233,7 +1233,8 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) m_diminishGroup = GetDiminishingReturnsGroupForSpell(m_spellInfo,m_triggeredByAuraSpell); m_diminishLevel = unit->GetDiminishing(m_diminishGroup); // Increase Diminishing on unit, current informations for actually casts will use values above - if((GetDiminishingReturnsGroupType(m_diminishGroup) == DRTYPE_PLAYER && unit->GetTypeId() == TYPEID_PLAYER) || GetDiminishingReturnsGroupType(m_diminishGroup) == DRTYPE_ALL) + if ((GetDiminishingReturnsGroupType(m_diminishGroup) == DRTYPE_PLAYER && unit->GetTypeId() == TYPEID_PLAYER) || + GetDiminishingReturnsGroupType(m_diminishGroup) == DRTYPE_ALL) unit->IncrDiminishing(m_diminishGroup); // Apply additional spell effects to target @@ -1250,7 +1251,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) // Get multiplier float multiplier = m_spellInfo->DmgMultiplier[effectNumber]; // Apply multiplier mods - if(Player* modOwner = m_originalCaster->GetSpellModOwner()) + if(Player* modOwner = realCaster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_EFFECT_PAST_FIRST, multiplier, this); m_damageMultipliers[effectNumber] *= multiplier; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 9db875648..33fea0275 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8131" + #define REVISION_NR "8132" #endif // __REVISION_NR_H__ From 08f1c9587493cd8e1a32ce5bbbbb847030272ede Mon Sep 17 00:00:00 2001 From: ApoC Date: Mon, 6 Jul 2009 03:26:13 +0200 Subject: [PATCH 15/33] [8133] Do not scale with level damage for SPELL_AURA_MOD_DECREASE_SPEED. May be other auras will need to be excluded also (auras modify AP, Armor ...) but this one is the most annoying :) This commit should fix non-movable behavior after being hitted by some NPC spell with slowing effect. Signed-off-by: ApoC --- src/game/Unit.cpp | 3 ++- src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 0deffac6a..7ca85987f 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -9796,7 +9796,8 @@ int32 Unit::CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_inde if(spellProto->Attributes & SPELL_ATTR_LEVEL_DAMAGE_CALCULATION && spellProto->spellLevel && spellProto->Effect[effect_index] != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE && - spellProto->Effect[effect_index] != SPELL_EFFECT_KNOCK_BACK) + spellProto->Effect[effect_index] != SPELL_EFFECT_KNOCK_BACK && + (spellProto->Effect[effect_index] != SPELL_EFFECT_APPLY_AURA || spellProto->EffectApplyAuraName[effect_index] != SPELL_AURA_MOD_DECREASE_SPEED)) value = int32(value*0.25f*exp(getLevel()*(70-spellProto->spellLevel)/1000.0f)); return value; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 33fea0275..5f7397c33 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8132" + #define REVISION_NR "8133" #endif // __REVISION_NR_H__ From ef6b3f978d266830a3e88c06ec09c60b14eb8040 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 6 Jul 2009 11:24:30 +0400 Subject: [PATCH 16/33] [8134] Fixed typo in ACTION_T_MORPH_TO_ENTRY_OR_MODEL check. --- src/game/CreatureEventAIMgr.cpp | 3 +-- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/game/CreatureEventAIMgr.cpp b/src/game/CreatureEventAIMgr.cpp index 79f059961..b90f944ce 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/shared/revision_nr.h b/src/shared/revision_nr.h index 5f7397c33..965d2ad09 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8133" + #define REVISION_NR "8134" #endif // __REVISION_NR_H__ From 5d8bd14d38848eeba7ab795ad9903bbbfd76ef6b Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 6 Jul 2009 15:48:26 +0400 Subject: [PATCH 17/33] [8135] Cast quest rewarded spells after mark spell as completed. Some spell have spell_area requirement for cast (for later re-apply) --- src/game/Player.cpp | 56 +++++++++++++++++++++------------------- src/shared/revision_nr.h | 2 +- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 9fc2d93b4..64d2c3b6d 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -12539,7 +12539,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i ) { - if ( pQuest->ReqItemId[i] ) + if (pQuest->ReqItemId[i]) DestroyItemCount( pQuest->ReqItemId[i], pQuest->ReqItemCount[i], true); } @@ -12547,12 +12547,12 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver // SetTimedQuest( 0 ); m_timedquests.erase(pQuest->GetQuestId()); - if ( pQuest->GetRewChoiceItemsCount() > 0 ) + if (pQuest->GetRewChoiceItemsCount() > 0) { - if( pQuest->RewChoiceItemId[reward] ) + if (pQuest->RewChoiceItemId[reward]) { ItemPosCountVec dest; - if( CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewChoiceItemId[reward], pQuest->RewChoiceItemCount[reward] ) == EQUIP_ERR_OK ) + if (CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewChoiceItemId[reward], pQuest->RewChoiceItemCount[reward] ) == EQUIP_ERR_OK) { Item* item = StoreNewItem( dest, pQuest->RewChoiceItemId[reward], true); SendNewItem(item, pQuest->RewChoiceItemCount[reward], true, false); @@ -12560,14 +12560,14 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver } } - if ( pQuest->GetRewItemsCount() > 0 ) + if (pQuest->GetRewItemsCount() > 0) { for (uint32 i=0; i < pQuest->GetRewItemsCount(); ++i) { - if( pQuest->RewItemId[i] ) + if (pQuest->RewItemId[i]) { ItemPosCountVec dest; - if( CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewItemId[i], pQuest->RewItemCount[i] ) == EQUIP_ERR_OK ) + if (CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewItemId[i], pQuest->RewItemCount[i] ) == EQUIP_ERR_OK) { Item* item = StoreNewItem( dest, pQuest->RewItemId[i], true); SendNewItem(item, pQuest->RewItemCount[i], true, false); @@ -12578,13 +12578,8 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver RewardReputation( pQuest ); - if( pQuest->GetRewSpellCast() > 0 ) - CastSpell( this, pQuest->GetRewSpellCast(), true); - else if( pQuest->GetRewSpell() > 0) - CastSpell( this, pQuest->GetRewSpell(), true); - uint16 log_slot = FindQuestSlot( quest_id ); - if( log_slot < MAX_QUEST_LOG_SIZE) + if (log_slot < MAX_QUEST_LOG_SIZE) SetQuestSlot(log_slot,0); QuestStatusData& q_status = mQuestStatus[quest_id]; @@ -12592,7 +12587,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver // Not give XP in case already completed once repeatable quest uint32 XP = q_status.m_rewarded ? 0 : uint32(pQuest->XPValue( this )*sWorld.getRate(RATE_XP_QUEST)); - if ( getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) ) + if (getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) GiveXP( XP , NULL ); else { @@ -12602,33 +12597,33 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver } // Give player extra money if GetRewOrReqMoney > 0 and get ReqMoney if negative - if(pQuest->GetRewOrReqMoney()) + if (pQuest->GetRewOrReqMoney()) { ModifyMoney( pQuest->GetRewOrReqMoney() ); - if(pQuest->GetRewOrReqMoney() > 0) + if (pQuest->GetRewOrReqMoney() > 0) GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, pQuest->GetRewOrReqMoney()); } // honor reward - if(pQuest->GetRewHonorableKills()) + if (pQuest->GetRewHonorableKills()) RewardHonor(NULL, 0, MaNGOS::Honor::hk_honor_at_level(getLevel(), pQuest->GetRewHonorableKills())); // title reward - if(pQuest->GetCharTitleId()) + if (pQuest->GetCharTitleId()) { - if(CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(pQuest->GetCharTitleId())) + if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(pQuest->GetCharTitleId())) SetTitle(titleEntry); } - if(pQuest->GetBonusTalents()) + if (pQuest->GetBonusTalents()) { m_questRewardTalentCount+=pQuest->GetBonusTalents(); InitTalentForLevel(); } // Send reward mail - if(pQuest->GetRewMailTemplateId()) + if (pQuest->GetRewMailTemplateId()) { MailMessageType mailType; uint32 senderGuidOrEntry; @@ -12666,9 +12661,9 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver uint32 max_slot = questMailLoot.GetMaxSlotInLootFor(this); for(uint32 i = 0; mi.size() < MAX_MAIL_ITEMS && i < max_slot; ++i) { - if(LootItem* lootitem = questMailLoot.LootItemInSlot(i,this)) + if (LootItem* lootitem = questMailLoot.LootItemInSlot(i,this)) { - if(Item* item = Item::CreateItem(lootitem->itemid,lootitem->count,this)) + if (Item* item = Item::CreateItem(lootitem->itemid,lootitem->count,this)) { item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted mi.AddItem(item->GetGUIDLow(), item->GetEntry(), item); @@ -12679,23 +12674,30 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver WorldSession::SendMailTo(this, mailType, MAIL_STATIONERY_NORMAL, senderGuidOrEntry, GetGUIDLow(), "", 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE,pQuest->GetRewMailDelaySecs(),pQuest->GetRewMailTemplateId()); } - if(pQuest->IsDaily()) + if (pQuest->IsDaily()) { SetDailyQuestStatus(quest_id); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST, 1); } - if ( !pQuest->IsRepeatable() ) + if (!pQuest->IsRepeatable()) SetQuestStatus(quest_id, QUEST_STATUS_COMPLETE); else SetQuestStatus(quest_id, QUEST_STATUS_NONE); q_status.m_rewarded = true; + if (q_status.uState != QUEST_NEW) + q_status.uState = QUEST_CHANGED; - if(announce) + if (announce) SendQuestReward( pQuest, XP, questGiver ); - if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; + // cast spells after mark quest complete (some spells have quest completed state reqyurements in spell_area data) + if (pQuest->GetRewSpellCast() > 0) + CastSpell( this, pQuest->GetRewSpellCast(), true); + else if ( pQuest->GetRewSpell() > 0) + CastSpell( this, pQuest->GetRewSpell(), true); + if (pQuest->GetZoneOrSort() > 0) GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, pQuest->GetZoneOrSort()); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 965d2ad09..23a9a6ad7 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8134" + #define REVISION_NR "8135" #endif // __REVISION_NR_H__ From 84e46d76e3cd344c370433f8375a6dd73abd33d3 Mon Sep 17 00:00:00 2001 From: ApoC Date: Mon, 6 Jul 2009 00:03:51 +0200 Subject: [PATCH 18/33] [8136] Fixed aura refresh on modify stack by negative amount. When decreasing stack amount of aura, aura should not be refreshed to full time. This should only happen on increasing stack. Signed-off-by: ApoC --- src/game/SpellAuras.cpp | 39 ++++++++++++++++++++++++--------------- src/shared/revision_nr.h | 2 +- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 67ece8a60..a1cb7643d 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -1178,23 +1178,32 @@ void Aura::SendAuraUpdate(bool remove) void Aura::SetStackAmount(uint8 stackAmount) { - if (stackAmount != m_stackAmount) + if (stackAmount == m_stackAmount) + // Nothing changed + return; + + Unit *target = GetTarget(); + Unit *caster = GetCaster(); + if (!target || !caster) + return; + + bool refresh = stackAmount > m_stackAmount; + m_stackAmount = stackAmount; + int32 amount = m_stackAmount * caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, target); + // Reapply if amount change + if (amount!=m_modifier.m_amount) { - Unit *target = GetTarget(); - Unit *caster = GetCaster(); - if (!target || !caster) - return; - m_stackAmount = stackAmount; - int32 amount = m_stackAmount * caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, target); - // Reapply if amount change - if (amount!=m_modifier.m_amount) - { - ApplyModifier(false, true); - m_modifier.m_amount = amount; - ApplyModifier(true, true); - } + ApplyModifier(false, true); + m_modifier.m_amount = amount; + ApplyModifier(true, true); } - RefreshAura(); + + if (refresh) + // Stack increased refresh duration + RefreshAura(); + else + // Stack decreased only send update + SendAuraUpdate(false); } bool Aura::modStackAmount(int32 num) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 23a9a6ad7..182d6e4c6 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8135" + #define REVISION_NR "8136" #endif // __REVISION_NR_H__ From a2959794847a06300452f1c4018c020a6da82305 Mon Sep 17 00:00:00 2001 From: hunuza Date: Mon, 6 Jul 2009 16:31:58 +0200 Subject: [PATCH 19/33] Minor optimizations to MSG_QUERY_NEXT_MAIL_TIME handler. * Do not search for more unread mails when already found 2. * Do not call time(NULL) every iteration. Signed-off-by: hunuza --- src/game/Mail.cpp | 52 ++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp index 2453f193f..2f2dfe85c 100644 --- a/src/game/Mail.cpp +++ b/src/game/Mail.cpp @@ -762,38 +762,40 @@ void WorldSession::HandleQueryNextMailTime(WorldPacket & /*recv_data*/ ) { data << (uint32) 0; // float data << (uint32) 0; // count + uint32 count = 0; + time_t now = time(NULL); for(PlayerMails::iterator itr = _player->GetmailBegin(); itr != _player->GetmailEnd(); ++itr) { Mail *m = (*itr); - // not checked yet, already must be delivered - if((m->checked & MAIL_CHECK_MASK_READ)==0 && (m->deliver_time <= time(NULL))) + // must be not checked yet + if(m->checked & MAIL_CHECK_MASK_RED) + continue; + + // and already delivered + if(now < m->deliver_time) + continue; + + data << (uint64) m->sender; // sender guid + + switch(m->messageType) { - ++count; - - if(count > 2) - { - count = 2; + case MAIL_AUCTION: + data << (uint32) 2; + data << (uint32) 2; + data << (uint32) m->stationery; + break; + default: + data << (uint32) 0; + data << (uint32) 0; + data << (uint32) m->stationery; break; - } - - data << (uint64) m->sender; // sender guid - - switch(m->messageType) - { - case MAIL_AUCTION: - data << (uint32) 2; - data << (uint32) 2; - data << (uint32) m->stationery; - break; - default: - data << (uint32) 0; - data << (uint32) 0; - data << (uint32) m->stationery; - break; - } - data << (uint32) 0xC6000000; // float unk, time or something } + data << (uint32) 0xC6000000; // float unk, time or something + + ++count; + if(count == 2) // do not display more than 2 mails + break; } data.put(4, count); } From 38197b539f5910ce276a8fbd06e51473ddf79633 Mon Sep 17 00:00:00 2001 From: hunuza Date: Mon, 6 Jul 2009 18:16:07 +0200 Subject: [PATCH 20/33] [8137] Init player display id + native display id on login. * Temporary reset of display id on save no longer needed. * Players always have the right model for their gender. Signed-off-by: hunuza --- src/game/Level3.cpp | 22 ++---------- src/game/Mail.cpp | 2 +- src/game/Player.cpp | 70 +++++++++++++++++++-------------------- src/game/Player.h | 2 ++ src/game/SpellEffects.cpp | 4 +-- src/shared/revision_nr.h | 2 +- 6 files changed, 43 insertions(+), 59 deletions(-) diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index ceb1d6e19..65fb77aba 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -4504,9 +4504,6 @@ bool ChatHandler::HandleResetHonorCommand (const char * args) static bool HandleResetStatsOrLevelHelper(Player* player) { - PlayerInfo const *info = objmgr.GetPlayerInfo(player->getRace(), player->getClass()); - if(!info) return false; - ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(player->getClass()); if(!cEntry) { @@ -4529,21 +4526,7 @@ static bool HandleResetStatsOrLevelHelper(Player* player) // reset only if player not in some form; if(player->m_form==FORM_NONE) - { - switch(player->getGender()) - { - case GENDER_FEMALE: - player->SetDisplayId(info->displayId_f); - player->SetNativeDisplayId(info->displayId_f); - break; - case GENDER_MALE: - player->SetDisplayId(info->displayId_m); - player->SetNativeDisplayId(info->displayId_m); - break; - default: - break; - } - } + player->InitDisplayIds(); player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP ); player->SetByteValue(UNIT_FIELD_BYTES_2, 3, player->m_form); @@ -6562,8 +6545,7 @@ bool ChatHandler::HandleModifyGenderCommand(const char *args) player->SetByteValue(PLAYER_BYTES_3, 0, gender); // Change display ID - player->SetDisplayId(gender ? info->displayId_f : info->displayId_m); - player->SetNativeDisplayId(gender ? info->displayId_f : info->displayId_m); + player->InitDisplayIds(); char const* gender_full = gender ? "female" : "male"; diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp index 2f2dfe85c..72c42825e 100644 --- a/src/game/Mail.cpp +++ b/src/game/Mail.cpp @@ -769,7 +769,7 @@ void WorldSession::HandleQueryNextMailTime(WorldPacket & /*recv_data*/ ) { Mail *m = (*itr); // must be not checked yet - if(m->checked & MAIL_CHECK_MASK_RED) + if(m->checked & MAIL_CHECK_MASK_READ) continue; // and already delivered diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 64d2c3b6d..77bf6c22f 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -555,27 +555,12 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f); - switch(gender) - { - case GENDER_FEMALE: - SetDisplayId(info->displayId_f ); - SetNativeDisplayId(info->displayId_f ); - break; - case GENDER_MALE: - SetDisplayId(info->displayId_m ); - SetNativeDisplayId(info->displayId_m ); - break; - default: - sLog.outError("Invalid gender %u for player",gender); - return false; - break; - } - setFactionForRace(race); uint32 RaceClassGender = ( race ) | ( class_ << 8 ) | ( gender << 16 ); SetUInt32Value(UNIT_FIELD_BYTES_0, ( RaceClassGender | ( powertype << 24 ) ) ); + InitDisplayIds(); SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP ); SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE ); SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER); @@ -1411,7 +1396,7 @@ bool Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) PlayerInfo const *info = objmgr.GetPlayerInfo(pRace, pClass); if(!info) { - sLog.outError("Player %u have incorrect race/class pair. Don't build enum.", guid); + sLog.outError("Player %u has incorrect race/class pair. Don't build enum.", guid); return false; } @@ -3420,7 +3405,7 @@ void Player::_LoadSpellCooldowns(QueryResult *result) if(!sSpellStore.LookupEntry(spell_id)) { - sLog.outError("Player %u have unknown spell %u in `character_spell_cooldown`, skipping.",GetGUIDLow(),spell_id); + sLog.outError("Player %u has unknown spell %u in `character_spell_cooldown`, skipping.",GetGUIDLow(),spell_id); continue; } @@ -14078,6 +14063,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) SetUInt32Value(PLAYER_BYTES_3, (GetUInt32Value(PLAYER_BYTES_3) & ~1) | fields[6].GetUInt8()); SetUInt32Value(PLAYER_FLAGS, fields[12].GetUInt32()); + InitDisplayIds(); + // cleanup inventory related item value fields (its will be filled correctly in _LoadInventory) for(uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) { @@ -14939,7 +14926,7 @@ void Player::_LoadMailedItems(Mail *mail) if(!proto) { - sLog.outError( "Player %u have unknown item_template (ProtoType) in mailed items(GUID: %u template: %u) in mail (%u), deleted.", GetGUIDLow(), item_guid_low, item_template,mail->messageID); + sLog.outError( "Player %u has unknown item_template (ProtoType) in mailed items(GUID: %u template: %u) in mail (%u), deleted.", GetGUIDLow(), item_guid_low, item_template,mail->messageID); CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid = '%u'", item_guid_low); CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", item_guid_low); continue; @@ -15530,7 +15517,6 @@ void Player::SaveToDB() SetByteValue(UNIT_FIELD_BYTES_1, 0, UNIT_STAND_STATE_STAND); SetByteValue(UNIT_FIELD_BYTES_2, 3, 0); // shapeshift RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - SetDisplayId(GetNativeDisplayId()); bool inworld = IsInWorld(); @@ -15675,7 +15661,6 @@ void Player::SaveToDB() CharacterDatabase.CommitTransaction(); // restore state (before aura apply, if aura remove flag then aura must set it ack by self) - SetDisplayId(tmp_displayid); SetUInt32Value(UNIT_FIELD_BYTES_1, tmp_bytes); SetUInt32Value(UNIT_FIELD_BYTES_2, tmp_bytes2); SetUInt32Value(UNIT_FIELD_FLAGS, tmp_flags); @@ -16119,28 +16104,17 @@ void Player::SetFloatValueInDB(uint16 index, float value, uint64 guid) void Player::Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair) { - // 0 1 2 3 4 - QueryResult* result = CharacterDatabase.PQuery("SELECT data, race, class, playerBytes, playerBytes2 FROM characters WHERE guid = '%u'", GUID_LOPART(guid)); + // 0 + QueryResult* result = CharacterDatabase.PQuery("SELECT playerBytes2 FROM characters WHERE guid = '%u'", GUID_LOPART(guid)); if(!result) return; Field* fields = result->Fetch(); - Tokens tokens = StrSplit(fields[0].GetString(), " "); - - PlayerInfo const* info = objmgr.GetPlayerInfo(fields[1].GetUInt8(), fields[2].GetUInt8()); - if(!info) - return; - - // TODO: do not access data field here - SetUInt32ValueInArray(tokens, UNIT_FIELD_DISPLAYID, gender ? info->displayId_f : info->displayId_m); - SetUInt32ValueInArray(tokens, UNIT_FIELD_NATIVEDISPLAYID, gender ? info->displayId_f : info->displayId_m); - - uint32 player_bytes2 = fields[4].GetUInt32(); + uint32 player_bytes2 = fields[0].GetUInt32(); player_bytes2 &= ~0xFF; player_bytes2 |= facialHair; - SaveValuesArrayInDB(tokens, guid); CharacterDatabase.PExecute("UPDATE characters SET gender = '%u', playerBytes = '%u', playerBytes2 = '%u' WHERE guid = '%u'", gender, skin | (face << 8) | (hairStyle << 16) | (hairColor << 24), player_bytes2, GUID_LOPART(guid)); delete result; @@ -17162,6 +17136,32 @@ void Player::InitDataForForm(bool reapplyMods) UpdateAttackPowerAndDamage(true); } +void Player::InitDisplayIds() +{ + PlayerInfo const *info = objmgr.GetPlayerInfo(getRace(), getClass()); + if(!info) + { + sLog.outError("Player %u has incorrect race/class pair. Can't init display ids.", GetGUIDLow()); + return; + } + + uint8 gender = getGender(); + switch(gender) + { + case GENDER_FEMALE: + SetDisplayId(info->displayId_f ); + SetNativeDisplayId(info->displayId_f ); + break; + case GENDER_MALE: + SetDisplayId(info->displayId_m ); + SetNativeDisplayId(info->displayId_m ); + break; + default: + sLog.outError("Invalid gender %u for player",gender); + return; + } +} + // 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, uint8 bag, uint8 slot) { diff --git a/src/game/Player.h b/src/game/Player.h index a30471d0a..f7a656f81 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1777,6 +1777,8 @@ class MANGOS_DLL_SPEC Player : public Unit static uint32 getFactionForRace(uint8 race); void setFactionForRace(uint8 race); + void InitDisplayIds(); + bool IsAtGroupRewardDistance(WorldObject const* pRewardSource) const; bool RewardPlayerAndGroupAtKill(Unit* pVictim); void RewardPlayerAndGroupAtEvent(uint32 creature_id,WorldObject* pRewardSource); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index c808c1fd9..d0843e609 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2321,7 +2321,7 @@ void Spell::EffectUnlearnSpecialization( uint32 i ) _player->removeSpell(spellToUnlearn); - sLog.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() ); + sLog.outDebug( "Spell: Player %u has unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() ); } void Spell::EffectPowerDrain(uint32 i) @@ -3324,7 +3324,7 @@ void Spell::EffectLearnSpell(uint32 i) uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i]; player->learnSpell(spellToLearn,false); - sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() ); + sLog.outDebug( "Spell: Player %u has learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() ); } void Spell::EffectDispel(uint32 i) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 182d6e4c6..4ec5f6741 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8136" + #define REVISION_NR "8137" #endif // __REVISION_NR_H__ From 0b9e41332ca139cba484c6f8259df35f7f33da45 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 7 Jul 2009 00:05:20 +0400 Subject: [PATCH 21/33] Allow cancel mind control spells while control target. --- src/game/SpellHandler.cpp | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 04499d490..373f76489 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -27,6 +27,7 @@ #include "Spell.h" #include "ScriptCalls.h" #include "Totem.h" +#include "SpellAuras.h" void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) { @@ -377,10 +378,6 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket) { CHECK_PACKET_SIZE(recvPacket,4); - // ignore for remote control state - if(_player->m_mover != _player) - return; - uint32 spellId; recvPacket >> spellId; @@ -388,10 +385,34 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket) if (!spellInfo) return; - // not allow remove non positive spells and spells with attr SPELL_ATTR_CANT_CANCEL - if(!IsPositiveSpell(spellId) || (spellInfo->Attributes & SPELL_ATTR_CANT_CANCEL)) + if (spellInfo->Attributes & SPELL_ATTR_CANT_CANCEL) return; + if(!IsPositiveSpell(spellId)) + { + // ignore for remote control state + if (_player->m_mover != _player) + { + // except own aura spells + bool allow = false; + for(int k = 0; k < 3; ++k) + { + if (spellInfo->EffectApplyAuraName[k] == SPELL_AURA_MOD_POSSESS || + spellInfo->EffectApplyAuraName[k] == SPELL_AURA_MOD_POSSESS_PET) + { + allow = true; + break; + } + } + + // this also include case when aura not found + if(!allow) + return; + } + else + return; + } + // channeled spell case (it currently casted then) if (IsChanneledSpell(spellInfo)) { From c8bb0c75a36bae3e3b6ac4626b12ce6ef14d2138 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 7 Jul 2009 00:06:25 +0400 Subject: [PATCH 22/33] [8138] Prevent stacking pet mind control auras. Thanks to NetSky for reset. --- src/game/Spell.cpp | 17 +++++++++++++++++ src/shared/revision_nr.h | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index b85946086..890d217f0 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -4387,6 +4387,23 @@ SpellCastResult Spell::CheckCast(bool strict) break; } + case SPELL_AURA_MOD_POSSESS_PET: + { + if(m_caster->GetCharmGUID()) + return SPELL_FAILED_ALREADY_HAVE_CHARM; + + if(m_caster->GetCharmerGUID()) + return SPELL_FAILED_CHARMED; + + Pet* pet = m_caster->GetPet(); + if(!pet) + return SPELL_FAILED_NO_PET; + + if(pet->GetCharmerGUID()) + return SPELL_FAILED_CHARMED; + + break; + } case SPELL_AURA_MOUNTED: { if (m_caster->IsInWater()) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 4ec5f6741..534b8c87b 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8137" + #define REVISION_NR "8138" #endif // __REVISION_NR_H__ From fccba20c9d48edb4cb50027e8aac507affe46bb6 Mon Sep 17 00:00:00 2001 From: ApoC Date: Mon, 6 Jul 2009 19:50:06 +0200 Subject: [PATCH 23/33] [8139] Implemented aura SPELL_AURA_ABILITY_PERIODIC_CRIT(286). This commit affects spells 49868, 58435, 63068, 63091, 63503, 64915, 64925. Signed-off-by: ApoC --- src/game/SpellAuraDefines.h | 2 +- src/game/SpellAuras.cpp | 28 +++++++++++++++++++++++++--- src/game/SpellAuras.h | 2 ++ src/game/Unit.cpp | 4 ++-- src/game/Unit.h | 3 ++- src/shared/revision_nr.h | 2 +- 6 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index 02519e375..9254468ca 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -328,7 +328,7 @@ enum AuraType SPELL_AURA_MOD_HEALING_RECEIVED = 283, // Possibly only for some spell family class spells SPELL_AURA_284, SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR = 285, - SPELL_AURA_286, + SPELL_AURA_ABILITY_PERIODIC_CRIT = 286, SPELL_AURA_DEFLECT_SPELLS, SPELL_AURA_288, SPELL_AURA_289, diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index a1cb7643d..4048fb8a0 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -336,7 +336,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus &Aura::HandleUnused, //284 not used by any spells (3.08a) &Aura::HandleAuraModAttackPowerOfArmor, //285 SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR implemented in Player::UpdateAttackPowerAndDamage - &Aura::HandleUnused, //286 not used by any spells (3.08a) + &Aura::HandleNoImmediateEffect, //286 SPELL_AURA_ABILITY_PERIODIC_CRIT implemented in Aura::IsCritFromAbilityAura called from AuraEffect::PeriodicTick &Aura::HandleNoImmediateEffect, //287 SPELL_AURA_DEFLECT_SPELLS implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult &Aura::HandleUnused, //288 not used by any spells (3.09) except 1 test spell. &Aura::HandleUnused, //289 unused @@ -5896,6 +5896,9 @@ void Aura::PeriodicTick() else pdamage = uint32(m_target->GetMaxHealth()*amount/100); + // This method can modify pdamage + bool isCrit = IsCritFromAbilityAura(pCaster, pdamage); + // As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit // Reduce dot damage from resilience for players if (m_target->GetTypeId() == TYPEID_PLAYER) @@ -5908,7 +5911,7 @@ void Aura::PeriodicTick() pCaster->DealDamageMods(m_target, pdamage, &absorb); - SpellPeriodicAuraLogInfo pInfo(this, pdamage, 0, absorb, resist, 0.0f); + SpellPeriodicAuraLogInfo pInfo(this, pdamage, 0, absorb, resist, 0.0f, isCrit); m_target->SendPeriodicAuraLog(&pInfo); Unit* target = m_target; // aura can be deleted in DealDamage @@ -6030,10 +6033,13 @@ void Aura::PeriodicTick() pdamage = pCaster->SpellHealingBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount()); + // This method can modify pdamage + bool isCrit = IsCritFromAbilityAura(pCaster, pdamage); + sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); - SpellPeriodicAuraLogInfo pInfo(this, pdamage, 0, 0, 0, 0.0f); + SpellPeriodicAuraLogInfo pInfo(this, pdamage, 0, 0, 0, 0.0f, isCrit); m_target->SendPeriodicAuraLog(&pInfo); int32 gain = m_target->ModifyHealth(pdamage); @@ -6921,3 +6927,19 @@ void Aura::HandleAuraSafeFall( bool Apply, bool Real ) if(Apply && Real && GetId() == 32474 && m_target->GetTypeId() == TYPEID_PLAYER) ((Player*)m_target)->ActivateTaxiPathTo(506, GetId()); } + +bool Aura::IsCritFromAbilityAura(Unit* caster, uint32& damage) +{ + Unit::AuraList const& auras = caster->GetAurasByType(SPELL_AURA_ABILITY_PERIODIC_CRIT); + for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + { + if (!(*itr)->isAffectedOnSpell(m_spellProto)) + continue; + + if (caster->isSpellCrit(m_target, m_spellProto, GetSpellSchoolMask(m_spellProto))) + damage = caster->SpellCriticalDamageBonus(m_spellProto, damage, m_target); + + return true; + } + return false; +} diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 1588992d3..f0767e299 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -325,6 +325,8 @@ class MANGOS_DLL_SPEC Aura protected: Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL); + bool IsCritFromAbilityAura(Unit* caster, uint32& damage); + Modifier m_modifier; SpellModifier *m_spellmod; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 7ca85987f..2d3cd341c 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -4278,13 +4278,13 @@ void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo *pInfo) data << uint32(GetSpellSchoolMask(aura->GetSpellProto())); data << uint32(pInfo->absorb); // absorb data << uint32(pInfo->resist); // resist - data << uint8(0); // new 3.1.2 + data << uint8(pInfo->critical ? 1 : 0); // new 3.1.2 critical flag break; case SPELL_AURA_PERIODIC_HEAL: case SPELL_AURA_OBS_MOD_HEALTH: data << uint32(pInfo->damage); // damage data << uint32(pInfo->overDamage); // overheal? - data << uint8(0); // new 3.1.2 + data << uint8(pInfo->critical ? 1 : 0); // new 3.1.2 critical flag break; case SPELL_AURA_OBS_MOD_MANA: case SPELL_AURA_PERIODIC_ENERGIZE: diff --git a/src/game/Unit.h b/src/game/Unit.h index fe35362b1..faefbefcd 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -686,7 +686,7 @@ struct SpellNonMeleeDamage{ struct SpellPeriodicAuraLogInfo { - SpellPeriodicAuraLogInfo(Aura *_aura, uint32 _damage, uint32 _overDamage, uint32 _absorb, uint32 _resist, float _multiplier) + SpellPeriodicAuraLogInfo(Aura *_aura, uint32 _damage, uint32 _overDamage, uint32 _absorb, uint32 _resist, float _multiplier, bool _critical = false) : aura(_aura), damage(_damage), overDamage(_overDamage), absorb(_absorb), resist(_resist), multiplier(_multiplier) {} Aura *aura; @@ -695,6 +695,7 @@ struct SpellPeriodicAuraLogInfo uint32 resist; uint32 overDamage; // overkill/overheal float multiplier; + bool critical; }; uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missCondition); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 534b8c87b..cd2e6680c 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8138" + #define REVISION_NR "8139" #endif // __REVISION_NR_H__ From 0f6d312e59c2173671cae9a3b8e0c8844c9d6e4c Mon Sep 17 00:00:00 2001 From: ApoC Date: Mon, 6 Jul 2009 23:15:46 +0200 Subject: [PATCH 24/33] [8140] Fixed dummy spell proc for 31876 and ranks. Signed-off-by: ApoC --- sql/mangos.sql | 8 ++++---- sql/updates/8140_01_mangos_spell_proc_event.sql | 7 +++++++ sql/updates/Makefile.am | 2 ++ src/game/Unit.cpp | 11 +++++++++++ src/shared/revision_nr.h | 2 +- 5 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 sql/updates/8140_01_mangos_spell_proc_event.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index f566859cb..c63f3b6cf 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -23,7 +23,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, - `required_8115_01_mangos_playercreateinfo_action` bit(1) default NULL + `required_8140_01_mangos_spell_proc_event` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -17123,9 +17123,9 @@ INSERT INTO `spell_proc_event` VALUES (31836, 0x00000000, 10, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (31871, 0x00000000, 10, 0x00000010, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0), (31872, 0x00000000, 10, 0x00000010, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0), -(31876, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), -(31877, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), -(31878, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(31876, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0), +(31877, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0), +(31878, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0), (31904, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0.000000, 0.000000, 0), (32385, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (32387, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), diff --git a/sql/updates/8140_01_mangos_spell_proc_event.sql b/sql/updates/8140_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..84a6ef378 --- /dev/null +++ b/sql/updates/8140_01_mangos_spell_proc_event.sql @@ -0,0 +1,7 @@ +ALTER TABLE db_version CHANGE COLUMN required_8115_01_mangos_playercreateinfo_action required_8140_01_mangos_spell_proc_event bit; + +DELETE FROM spell_proc_event WHERE entry IN (31876, 31877, 31878); +INSERT INTO spell_proc_event VALUES +(31876, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0), +(31877, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0), +(31878, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0); \ No newline at end of file diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index ef83aa02b..c9002001c 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -242,6 +242,7 @@ pkgdata_DATA = \ 8104_01_characters.sql \ 8112_01_mangos_spell_proc_event.sql \ 8115_01_mangos_playercreateinfo_action.sql \ + 8140_01_mangos_spell_proc_event.sql \ README ## Additional files to include when running 'make dist' @@ -464,4 +465,5 @@ EXTRA_DIST = \ 8104_01_characters.sql \ 8112_01_mangos_spell_proc_event.sql \ 8115_01_mangos_playercreateinfo_action.sql \ + 8140_01_mangos_spell_proc_event.sql \ README diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 2d3cd341c..f0ff6b6a1 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -5521,6 +5521,17 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu } return true; } + // Judgements of the Wise + case 31876: + case 31877: + case 31878: + target = this; + basepoints0 = GetCreatePowers(POWER_MANA) * 25 / 100; + triggered_spell_id = 31930; + + // Replenishment + CastSpell(this, 57669, true, NULL, triggeredByAura); + break; // Holy Power (Redemption Armor set) case 28789: { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index cd2e6680c..6fb2f7fbc 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8139" + #define REVISION_NR "8140" #endif // __REVISION_NR_H__ From 6002d7ea2c16c2e22cc28753253c53e16e1f46c1 Mon Sep 17 00:00:00 2001 From: ApoC Date: Tue, 7 Jul 2009 01:39:56 +0200 Subject: [PATCH 25/33] Implemented precast spell store as dynamicaly allocated list of precasts. Signed-off-by: ApoC --- src/game/Spell.cpp | 30 ++++++++++++++++++------------ src/game/Spell.h | 10 +++++++++- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 890d217f0..a0ce1f390 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -405,7 +405,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi focusObject = NULL; m_cast_count = 0; m_glyphIndex = 0; - m_preCastSpell = 0; + m_preCastSpells = NULL; m_triggeredByAuraSpell = NULL; //Auto Shot & Shoot (wand) @@ -445,6 +445,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi Spell::~Spell() { + delete m_preCastSpells; } template @@ -550,7 +551,7 @@ void Spell::FillTargetMap() if(m_targets.getUnitTarget()) tmpUnitMap.push_back(m_targets.getUnitTarget()); else - tmpUnitMap.push_back(m_caster); + tmpUnitMap.push_back(m_caster); break; case TARGET_AREAEFFECT_INSTANT: // All 17/7 pairs used for dest teleportation, A processed in effect code SetTargetMap(i, m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); @@ -1238,8 +1239,13 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) unit->IncrDiminishing(m_diminishGroup); // Apply additional spell effects to target - if (m_preCastSpell) - m_caster->CastSpell(unit, m_preCastSpell, true, m_CastItem); + if (m_preCastSpells) + { + for (SpellPrecasts::const_iterator i = m_preCastSpells->begin(); i != m_preCastSpells->end(); ++i) + m_caster->CastSpell(unit, *i, true, m_CastItem); + delete m_preCastSpells; + m_preCastSpells = NULL; + } for(uint32 effectNumber = 0; effectNumber < 3; ++effectNumber) { @@ -2288,17 +2294,17 @@ void Spell::cast(bool skipCheck) case SPELLFAMILY_GENERIC: { if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages - m_preCastSpell = 11196; // Recently Bandaged + AddPrecastSpell(11196); // Recently Bandaged else if(m_spellInfo->SpellIconID == 1662 && m_spellInfo->AttributesEx & 0x20) // Blood Fury (Racial) - m_preCastSpell = 23230; // Blood Fury - Healing Reduction + AddPrecastSpell(23230); // Blood Fury - Healing Reduction break; } case SPELLFAMILY_MAGE: { // Ice Block if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000008000000000)) - m_preCastSpell = 41425; // Hypothermia + AddPrecastSpell(41425); // Hypothermia break; } case SPELLFAMILY_PRIEST: @@ -2306,27 +2312,27 @@ void Spell::cast(bool skipCheck) // Power Word: Shield if (m_spellInfo->Mechanic == MECHANIC_SHIELD && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000001))) - m_preCastSpell = 6788; // Weakened Soul + AddPrecastSpell(6788); // Weakened Soul // Dispersion (transform) if (m_spellInfo->Id == 47585) - m_preCastSpell = 60069; // Dispersion (mana regen) + AddPrecastSpell(60069); // Dispersion (mana regen) break; } case SPELLFAMILY_PALADIN: { // Divine Shield, Divine Protection or Hand of Protection if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400080)) - m_preCastSpell = 25771; // Forbearance + AddPrecastSpell(25771); // Forbearance break; } case SPELLFAMILY_SHAMAN: { // Bloodlust if (m_spellInfo->Id == 2825) - m_preCastSpell = 57724; // Sated + AddPrecastSpell(57724); // Sated // Heroism else if (m_spellInfo->Id == 32182) - m_preCastSpell = 57723; // Exhaustion + AddPrecastSpell(57723); // Exhaustion break; } default: diff --git a/src/game/Spell.h b/src/game/Spell.h index 01c25060d..3583f546a 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -204,6 +204,7 @@ enum SpellTargets #define SPELL_SPELL_CHANNEL_UPDATE_INTERVAL (1*IN_MILISECONDS) typedef std::multimap SpellTargetTimeMap; +typedef std::list SpellPrecasts; class Spell { @@ -335,6 +336,13 @@ class Spell void TakeCastItem(); void TriggerSpell(); + void AddPrecastSpell(uint32 spellId) + { + if (!m_preCastSpells) + m_preCastSpells = new SpellPrecasts(); + m_preCastSpells->push_back(spellId); + } + SpellCastResult CheckCast(bool strict); SpellCastResult CheckPetCast(Unit* target); @@ -399,7 +407,7 @@ class Spell Item* m_CastItem; uint8 m_cast_count; uint32 m_glyphIndex; - uint32 m_preCastSpell; + SpellPrecasts *m_preCastSpells; SpellCastTargets m_targets; int32 GetCastTime() const { return m_casttime; } From afdfa4f56455d94f61fa862e15748b7602a0e47f Mon Sep 17 00:00:00 2001 From: ApoC Date: Tue, 7 Jul 2009 01:41:34 +0200 Subject: [PATCH 26/33] Cast 61987 also with 25771 as precasts. Signed-off-by: ApoC --- src/game/Spell.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index a0ce1f390..a4d975296 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2322,7 +2322,12 @@ void Spell::cast(bool skipCheck) { // Divine Shield, Divine Protection or Hand of Protection if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400080)) + { AddPrecastSpell(25771); // Forbearance + AddPrecastSpell(61987); // Avenging Wrath Marker + } + else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x200000000000)) + AddPrecastSpell(61987); // Avenging Wrath Marker break; } case SPELLFAMILY_SHAMAN: @@ -3666,8 +3671,17 @@ SpellCastResult Spell::CheckCast(bool strict) // Caster aura req check if need if(m_spellInfo->casterAuraSpell && !m_caster->HasAura(m_spellInfo->casterAuraSpell)) return SPELL_FAILED_CASTER_AURASTATE; - if(m_spellInfo->excludeCasterAuraSpell && m_caster->HasAura(m_spellInfo->excludeCasterAuraSpell)) - return SPELL_FAILED_CASTER_AURASTATE; + if(m_spellInfo->excludeCasterAuraSpell) + { + // Special cases of non existing auras handling + if(m_spellInfo->excludeCasterAuraSpell == 61988) + { + if(m_caster->HasAura(61987)) + return SPELL_FAILED_CASTER_AURASTATE; + } + else if(m_caster->HasAura(m_spellInfo->excludeCasterAuraSpell)) + return SPELL_FAILED_CASTER_AURASTATE; + } // cancel autorepeat spells if cast start when moving // (not wand currently autorepeat cast delayed to moving stop anyway in spell update code) From 42300153cefb9a735eed860048c34e9812a78de5 Mon Sep 17 00:00:00 2001 From: QAston Date: Tue, 7 Jul 2009 13:58:16 +0200 Subject: [PATCH 27/33] [8141] Comment fix. I would like to also appology to QAston for not mentioned him in my prev. commit (db13c2fe18ff3953851eaaf86922ee57510e556a) as patch author. I am sorry. ApoC Signed-off-by: ApoC --- src/game/SpellAuras.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 4048fb8a0..3a0862d9a 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -336,7 +336,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus &Aura::HandleUnused, //284 not used by any spells (3.08a) &Aura::HandleAuraModAttackPowerOfArmor, //285 SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR implemented in Player::UpdateAttackPowerAndDamage - &Aura::HandleNoImmediateEffect, //286 SPELL_AURA_ABILITY_PERIODIC_CRIT implemented in Aura::IsCritFromAbilityAura called from AuraEffect::PeriodicTick + &Aura::HandleNoImmediateEffect, //286 SPELL_AURA_ABILITY_PERIODIC_CRIT implemented in Aura::IsCritFromAbilityAura called from Aura::PeriodicTick &Aura::HandleNoImmediateEffect, //287 SPELL_AURA_DEFLECT_SPELLS implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult &Aura::HandleUnused, //288 not used by any spells (3.09) except 1 test spell. &Aura::HandleUnused, //289 unused diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 6fb2f7fbc..8f4e615d1 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8140" + #define REVISION_NR "8141" #endif // __REVISION_NR_H__ From 5d4b581009212935b0f7fde1bddef3a4a6bd7379 Mon Sep 17 00:00:00 2001 From: ApoC Date: Tue, 7 Jul 2009 16:12:04 +0200 Subject: [PATCH 28/33] [8142] Remade precast spell system to be more similar to trigger spell system. * Removed runtime allocation of list * Methods and defines from precast spell system and trigger system moved closer to each other Signed-off-by: ApoC --- src/game/Spell.cpp | 12 +++++------- src/game/Spell.h | 12 +++--------- src/shared/revision_nr.h | 2 +- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index a4d975296..c6e7e6372 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -395,6 +395,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi m_castPositionX = m_castPositionY = m_castPositionZ = 0; m_TriggerSpells.clear(); + m_preCastSpells.clear(); m_IsTriggeredSpell = triggered; //m_AreaAura = false; m_CastItem = NULL; @@ -405,7 +406,6 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi focusObject = NULL; m_cast_count = 0; m_glyphIndex = 0; - m_preCastSpells = NULL; m_triggeredByAuraSpell = NULL; //Auto Shot & Shoot (wand) @@ -445,7 +445,6 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi Spell::~Spell() { - delete m_preCastSpells; } template @@ -1239,12 +1238,11 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) unit->IncrDiminishing(m_diminishGroup); // Apply additional spell effects to target - if (m_preCastSpells) + while (!m_preCastSpells.empty()) { - for (SpellPrecasts::const_iterator i = m_preCastSpells->begin(); i != m_preCastSpells->end(); ++i) - m_caster->CastSpell(unit, *i, true, m_CastItem); - delete m_preCastSpells; - m_preCastSpells = NULL; + uint32 spellId = *m_preCastSpells.begin(); + m_caster->CastSpell(unit, spellId, true, m_CastItem); + m_preCastSpells.erase(m_preCastSpells.begin()); } for(uint32 effectNumber = 0; effectNumber < 3; ++effectNumber) diff --git a/src/game/Spell.h b/src/game/Spell.h index 3583f546a..d3b587e95 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -204,7 +204,6 @@ enum SpellTargets #define SPELL_SPELL_CHANNEL_UPDATE_INTERVAL (1*IN_MILISECONDS) typedef std::multimap SpellTargetTimeMap; -typedef std::list SpellPrecasts; class Spell { @@ -336,13 +335,6 @@ class Spell void TakeCastItem(); void TriggerSpell(); - void AddPrecastSpell(uint32 spellId) - { - if (!m_preCastSpells) - m_preCastSpells = new SpellPrecasts(); - m_preCastSpells->push_back(spellId); - } - SpellCastResult CheckCast(bool strict); SpellCastResult CheckPetCast(Unit* target); @@ -407,7 +399,6 @@ class Spell Item* m_CastItem; uint8 m_cast_count; uint32 m_glyphIndex; - SpellPrecasts *m_preCastSpells; SpellCastTargets m_targets; int32 GetCastTime() const { return m_casttime; } @@ -448,6 +439,7 @@ class Spell bool CheckTargetCreatureType(Unit* target) const; void AddTriggeredSpell(SpellEntry const* spell) { m_TriggerSpells.push_back(spell); } + void AddPrecastSpell(uint32 spellId) { m_preCastSpells.push_back(spellId); } void CleanupTargetList(); protected: @@ -567,7 +559,9 @@ class Spell //List For Triggered Spells typedef std::list TriggerSpells; + typedef std::list SpellPrecasts; TriggerSpells m_TriggerSpells; + SpellPrecasts m_preCastSpells; uint32 m_spellState; uint32 m_timer; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 8f4e615d1..652bc3566 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8141" + #define REVISION_NR "8142" #endif // __REVISION_NR_H__ From 4b4eb0a6d52ae6ccc243d9cfb594d8951c668cd3 Mon Sep 17 00:00:00 2001 From: ApoC Date: Tue, 7 Jul 2009 19:23:50 +0200 Subject: [PATCH 29/33] [8143] Fixed Aura::IsCritFromAbilityAura * If not applied critical damage bonus don't clasify tick as critical. Signed-off-by: ApoC --- src/game/SpellAuras.cpp | 6 +++--- src/shared/revision_nr.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 3a0862d9a..45b98cda2 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -6935,10 +6935,10 @@ bool Aura::IsCritFromAbilityAura(Unit* caster, uint32& damage) { if (!(*itr)->isAffectedOnSpell(m_spellProto)) continue; + if (!caster->isSpellCrit(m_target, m_spellProto, GetSpellSchoolMask(m_spellProto))) + break; - if (caster->isSpellCrit(m_target, m_spellProto, GetSpellSchoolMask(m_spellProto))) - damage = caster->SpellCriticalDamageBonus(m_spellProto, damage, m_target); - + damage = caster->SpellCriticalDamageBonus(m_spellProto, damage, m_target); return true; } return false; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 652bc3566..6490457c2 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8142" + #define REVISION_NR "8143" #endif // __REVISION_NR_H__ From 17d0cda6378f701504a6deefd3b70dc24e083e92 Mon Sep 17 00:00:00 2001 From: ApoC Date: Tue, 7 Jul 2009 19:41:12 +0200 Subject: [PATCH 30/33] [8144] Forgotten uninitialized value fix. Signed-off-by: ApoC --- src/game/Unit.h | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/Unit.h b/src/game/Unit.h index faefbefcd..ace8b0293 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -687,7 +687,7 @@ struct SpellNonMeleeDamage{ struct SpellPeriodicAuraLogInfo { SpellPeriodicAuraLogInfo(Aura *_aura, uint32 _damage, uint32 _overDamage, uint32 _absorb, uint32 _resist, float _multiplier, bool _critical = false) - : aura(_aura), damage(_damage), overDamage(_overDamage), absorb(_absorb), resist(_resist), multiplier(_multiplier) {} + : aura(_aura), damage(_damage), overDamage(_overDamage), absorb(_absorb), resist(_resist), multiplier(_multiplier), critical(_critical) {} Aura *aura; uint32 damage; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 6490457c2..cf607d70e 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8143" + #define REVISION_NR "8144" #endif // __REVISION_NR_H__ From 2d25d7f8bc091c80beb23bbfd46fe99beb7b5c94 Mon Sep 17 00:00:00 2001 From: Ambal Date: Tue, 7 Jul 2009 23:01:00 +0400 Subject: [PATCH 31/33] [8145] Use constant name instead not-safe explicit value. Signed-off-by: VladimirMangos --- src/game/GridDefines.h | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/GridDefines.h b/src/game/GridDefines.h index d5ddf3aaf..6565e0e0f 100644 --- a/src/game/GridDefines.h +++ b/src/game/GridDefines.h @@ -65,7 +65,7 @@ typedef GridRefManager GameObjectMapType; typedef GridRefManager PlayerMapType; typedef Grid GridType; -typedef NGrid<8, Player, AllWorldObjectTypes, AllGridObjectTypes> NGridType; +typedef NGrid NGridType; typedef TypeMapContainer GridTypeMapContainer; typedef TypeMapContainer WorldTypeMapContainer; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index cf607d70e..51560ed5e 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8144" + #define REVISION_NR "8145" #endif // __REVISION_NR_H__ From 1ad013e25b89cded916c49addacb7af441ddddb2 Mon Sep 17 00:00:00 2001 From: ApoC Date: Tue, 7 Jul 2009 21:54:23 +0200 Subject: [PATCH 32/33] [8146] Fixed handling of eventchance for CreatureEventAI. Check event chance after timers advances othewise event is not scheduled to next time period and event chance is again checked on next AI update. Signed-off-by: ApoC --- src/game/CreatureEventAI.cpp | 14 +++++++------- src/shared/revision_nr.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index 7b7e6966e..ca0384740 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -112,13 +112,6 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction if (pHolder.Event.event_inverse_phase_mask & (1 << Phase)) return false; - //Store random here so that all random actions match up - uint32 rnd = rand(); - - //Return if chance for event is not met - if (pHolder.Event.event_chance <= rnd % 100) - return false; - CreatureEventAI_Event const& event = pHolder.Event; //Check event conditions based on the event type, also reset events @@ -330,6 +323,13 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction if (!(pHolder.Event.event_flags & EFLAG_REPEATABLE)) pHolder.Enabled = false; + //Store random here so that all random actions match up + uint32 rnd = rand(); + + //Return if chance for event is not met + if (pHolder.Event.event_chance <= rnd % 100) + return false; + //Process actions for (uint32 j = 0; j < MAX_ACTIONS; j++) ProcessAction(pHolder.Event.action[j], rnd, pHolder.Event.event_id, pActionInvoker); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 51560ed5e..1faff6528 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8145" + #define REVISION_NR "8146" #endif // __REVISION_NR_H__ From 3bfe549a2bd30680a4eefedc906a75a63851339d Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 8 Jul 2009 17:50:02 +0400 Subject: [PATCH 33/33] [8147] Some fixes and cleanups in mind control and charmed code. Mind control stil not finished. * Allow command to mind controlled unit attack target at client. Rename related flag to UNIT_FLAG_PLAYER_CONTROLLED. * Move code for pet action bar remove at client side to new function Player::RemovePetActionBar * Not allow cast spells with SPELL_AURA_MOD_POSSESS and SPELL_AURA_MOD_POSSESS_PET by non-players and simplify related code base at this. --- src/game/PetAI.cpp | 2 +- src/game/Player.cpp | 19 ++-- src/game/Player.h | 2 + src/game/Spell.cpp | 33 ++++++ src/game/SpellAuras.cpp | 218 +++++++++++++++++++-------------------- src/game/Unit.h | 2 +- src/shared/revision_nr.h | 2 +- 7 files changed, 153 insertions(+), 125 deletions(-) diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index cd0e1db02..9c4223e34 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -335,4 +335,4 @@ void PetAI::AttackedBy(Unit *attacker) if(!m_creature->getVictim() && m_creature->GetCharmInfo() && !m_creature->GetCharmInfo()->HasReactState(REACT_PASSIVE) && (!m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY) || m_creature->canReachWithAttack(attacker))) AttackStart(attacker); -} +} \ No newline at end of file diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 77bf6c22f..f81ef2e17 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -16359,9 +16359,7 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent) if(pet->isControlled()) { - WorldPacket data(SMSG_PET_SPELLS, 8); - data << uint64(0); - GetSession()->SendPacket(&data); + RemovePetActionBar(); if(GetGroup()) SetGroupUpdateFlag(GROUP_UPDATE_PET); @@ -16623,6 +16621,13 @@ void Player::CharmSpellInitialize() GetSession()->SendPacket(&data); } +void Player::RemovePetActionBar() +{ + WorldPacket data(SMSG_PET_SPELLS, 8); + data << uint64(0); + SendDirectMessage(&data); +} + bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell) { if (!mod || !spellInfo) @@ -19380,7 +19385,7 @@ void Player::EnterVehicle(Vehicle *vehicle) vehicle->SetCharmerGUID(GetGUID()); vehicle->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); + vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); vehicle->setFaction(getFaction()); SetCharm(vehicle); // charm @@ -19432,7 +19437,7 @@ void Player::ExitVehicle(Vehicle *vehicle) { vehicle->SetCharmerGUID(0); vehicle->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); + vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H); SetCharm(NULL); @@ -19454,9 +19459,7 @@ void Player::ExitVehicle(Vehicle *vehicle) data << uint32(0); // fall time GetSession()->SendPacket(&data); - data.Initialize(SMSG_PET_SPELLS, 8); - data << uint64(0); - GetSession()->SendPacket(&data); + RemovePetActionBar(); // maybe called at dummy aura remove? // CastSpell(this, 45472, true); // Parachute diff --git a/src/game/Player.h b/src/game/Player.h index f7a656f81..efe279b1c 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1442,6 +1442,8 @@ class MANGOS_DLL_SPEC Player : public Unit void PetSpellInitialize(); void CharmSpellInitialize(); void PossessSpellInitialize(); + void RemovePetActionBar(); + bool HasSpell(uint32 spell) const; bool HasActiveSpell(uint32 spell) const; // show in spellbook TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell) const; diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index c6e7e6372..4cd2aaf68 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -4383,8 +4383,38 @@ SpellCastResult Spell::CheckCast(bool strict) break; } case SPELL_AURA_MOD_POSSESS: + { + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return SPELL_FAILED_UNKNOWN; + + if(m_targets.getUnitTarget() == m_caster) + return SPELL_FAILED_BAD_TARGETS; + + if(m_caster->GetPetGUID()) + return SPELL_FAILED_ALREADY_HAVE_SUMMON; + + if(m_caster->GetCharmGUID()) + return SPELL_FAILED_ALREADY_HAVE_CHARM; + + if(m_caster->GetCharmerGUID()) + return SPELL_FAILED_CHARMED; + + if(!m_targets.getUnitTarget()) + return SPELL_FAILED_BAD_IMPLICIT_TARGETS; + + if(m_targets.getUnitTarget()->GetCharmerGUID()) + return SPELL_FAILED_CHARMED; + + if(int32(m_targets.getUnitTarget()->getLevel()) > CalculateDamage(i,m_targets.getUnitTarget())) + return SPELL_FAILED_HIGHLEVEL; + + break; + } case SPELL_AURA_MOD_CHARM: { + if(m_targets.getUnitTarget() == m_caster) + return SPELL_FAILED_BAD_TARGETS; + if(m_caster->GetPetGUID()) return SPELL_FAILED_ALREADY_HAVE_SUMMON; @@ -4407,6 +4437,9 @@ SpellCastResult Spell::CheckCast(bool strict) } case SPELL_AURA_MOD_POSSESS_PET: { + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return SPELL_FAILED_UNKNOWN; + if(m_caster->GetCharmGUID()) return SPELL_FAILED_ALREADY_HAVE_CHARM; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 45b98cda2..df1cd5497 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3074,33 +3074,33 @@ void Aura::HandleModPossess(bool apply, bool Real) if(!Real) return; - if(m_target->getLevel() > m_modifier.m_amount) - return; - // not possess yourself if(GetCasterGUID() == m_target->GetGUID()) return; Unit* caster = GetCaster(); - if(!caster) + if(!caster || caster->GetTypeId() != TYPEID_PLAYER) return; + Player* p_caster = (Player*)caster; + + if( apply ) { - m_target->SetCharmerGUID(GetCasterGUID()); - m_target->setFaction(caster->getFaction()); + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); - caster->SetCharm(m_target); + m_target->SetCharmerGUID(p_caster->GetGUID()); + m_target->setFaction(p_caster->getFaction()); - if(caster->GetTypeId() == TYPEID_PLAYER) - { - ((Player*)caster)->SetFarSightGUID(m_target->GetGUID()); - ((Player*)caster)->SetClientControl(m_target, 1); - ((Player*)caster)->SetMover(m_target); - } + p_caster->SetCharm(m_target); + + p_caster->SetFarSightGUID(m_target->GetGUID()); + p_caster->SetClientControl(m_target, 1); + p_caster->SetMover(m_target); m_target->CombatStop(); m_target->DeleteThreatList(); + if(m_target->GetTypeId() == TYPEID_UNIT) { m_target->StopMoving(); @@ -3115,13 +3115,14 @@ void Aura::HandleModPossess(bool apply, bool Real) if(CharmInfo *charmInfo = m_target->InitCharmInfo(m_target)) charmInfo->InitPossessCreateSpells(); - if(caster->GetTypeId() == TYPEID_PLAYER) - ((Player*)caster)->PossessSpellInitialize(); + p_caster->PossessSpellInitialize(); } else { + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); + m_target->SetCharmerGUID(0); - caster->InterruptSpell(CURRENT_CHANNELED_SPELL); // the spell is not automatically canceled when interrupted, do it now + p_caster->InterruptSpell(CURRENT_CHANNELED_SPELL); // the spell is not automatically canceled when interrupted, do it now if(m_target->GetTypeId() == TYPEID_PLAYER) { @@ -3134,18 +3135,13 @@ void Aura::HandleModPossess(bool apply, bool Real) m_target->setFaction(cinfo->faction_A); } - caster->SetCharm(NULL); + p_caster->SetCharm(NULL); - if(caster->GetTypeId() == TYPEID_PLAYER) - { - ((Player*)caster)->SetFarSightGUID(0); - ((Player*)caster)->SetClientControl(m_target, 0); - ((Player*)caster)->SetMover(NULL); + p_caster->SetFarSightGUID(0); + p_caster->SetClientControl(m_target, 0); + p_caster->SetMover(NULL); - WorldPacket data(SMSG_PET_SPELLS, 8); - data << uint64(0); - ((Player*)caster)->GetSession()->SendPacket(&data); - } + p_caster->RemovePetActionBar(); if(m_target->GetTypeId() == TYPEID_UNIT) { @@ -3170,14 +3166,16 @@ void Aura::HandleModPossessPet(bool apply, bool Real) if(!pet || pet != m_target) return; - if(apply) - pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); - else - pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); + Player* p_caster = (Player*)caster; - ((Player*)caster)->SetFarSightGUID(apply ? pet->GetGUID() : 0); - ((Player*)caster)->SetCharm(apply ? pet : NULL); - ((Player*)caster)->SetClientControl(pet, apply ? 1 : 0); + if(apply) + pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); + else + pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); + + p_caster->SetFarSightGUID(apply ? pet->GetGUID() : 0); + p_caster->SetCharm(apply ? pet : NULL); + p_caster->SetClientControl(pet, apply ? 1 : 0); ((Player*)caster)->SetMover(apply ? pet : NULL); if(apply) @@ -3217,100 +3215,92 @@ void Aura::HandleModCharm(bool apply, bool Real) if(!caster) return; - if(int32(m_target->getLevel()) <= m_modifier.m_amount) + if( apply ) { - if( apply ) + m_target->SetCharmerGUID(GetCasterGUID()); + m_target->setFaction(caster->getFaction()); + m_target->CastStop(m_target == caster ? GetId() : 0); + caster->SetCharm(m_target); + + m_target->CombatStop(); + m_target->DeleteThreatList(); + + if(m_target->GetTypeId() == TYPEID_UNIT) { - m_target->SetCharmerGUID(GetCasterGUID()); - m_target->setFaction(caster->getFaction()); - m_target->CastStop(m_target == caster ? GetId() : 0); - caster->SetCharm(m_target); + ((Creature*)m_target)->AIM_Initialize(); + CharmInfo *charmInfo = m_target->InitCharmInfo(m_target); + charmInfo->InitCharmCreateSpells(); + charmInfo->SetReactState( REACT_DEFENSIVE ); - m_target->CombatStop(); - m_target->DeleteThreatList(); - - if(m_target->GetTypeId() == TYPEID_UNIT) - { - ((Creature*)m_target)->AIM_Initialize(); - CharmInfo *charmInfo = m_target->InitCharmInfo(m_target); - charmInfo->InitCharmCreateSpells(); - charmInfo->SetReactState( REACT_DEFENSIVE ); - - if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK) - { - CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); - if(cinfo && cinfo->type == CREATURE_TYPE_DEMON) - { - //does not appear to have relevance. Why code added initially? See note below at !apply - //to prevent client crash - //m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048); - //just to enable stat window - charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true); - //if charmed two demons the same session, the 2nd gets the 1st one's name - m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); - } - } - } - - if(caster->GetTypeId() == TYPEID_PLAYER) - { - ((Player*)caster)->CharmSpellInitialize(); - } - } - else - { - m_target->SetCharmerGUID(0); - - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->setFactionForRace(m_target->getRace()); - else + if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK) { CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); - - // restore faction - if(((Creature*)m_target)->isPet()) + if(cinfo && cinfo->type == CREATURE_TYPE_DEMON) { - if(Unit* owner = m_target->GetOwner()) - m_target->setFaction(owner->getFaction()); - else if(cinfo) - m_target->setFaction(cinfo->faction_A); + //does not appear to have relevance. Why code added initially? See note below at !apply + //to prevent client crash + //m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048); + //just to enable stat window + charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true); + //if charmed two demons the same session, the 2nd gets the 1st one's name + m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); } - else if(cinfo) // normal creature + } + } + + if(caster->GetTypeId() == TYPEID_PLAYER) + ((Player*)caster)->CharmSpellInitialize(); + } + else + { + m_target->SetCharmerGUID(0); + + if(m_target->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_target)->setFactionForRace(m_target->getRace()); + else + { + CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); + + // restore faction + if(((Creature*)m_target)->isPet()) + { + if(Unit* owner = m_target->GetOwner()) + m_target->setFaction(owner->getFaction()); + else if(cinfo) m_target->setFaction(cinfo->faction_A); - - // restore UNIT_FIELD_BYTES_0 - if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON) - { - //does not appear to have relevance. Why code added initially? Class, gender, powertype should be same. - //db field removed and replaced with better way to set class, restore using this if problems - /*CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon(); - if(cainfo && cainfo->bytes0 != 0) - m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0); - else - m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);*/ - - if(m_target->GetCharmInfo()) - m_target->GetCharmInfo()->SetPetNumber(0, true); - else - sLog.outError("Aura::HandleModCharm: target (GUID: %u TypeId: %u) has a charm aura but no charm info!", m_target->GetGUIDLow(), m_target->GetTypeId()); - } } + else if(cinfo) // normal creature + m_target->setFaction(cinfo->faction_A); - caster->SetCharm(NULL); - - if(caster->GetTypeId() == TYPEID_PLAYER) + // restore UNIT_FIELD_BYTES_0 + if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON) { - WorldPacket data(SMSG_PET_SPELLS, 8); - data << uint64(0); - ((Player*)caster)->GetSession()->SendPacket(&data); - } - if(m_target->GetTypeId() == TYPEID_UNIT) - { - ((Creature*)m_target)->AIM_Initialize(); - if (((Creature*)m_target)->AI()) - ((Creature*)m_target)->AI()->AttackedBy(caster); + //does not appear to have relevance. Why code added initially? Class, gender, powertype should be same. + //db field removed and replaced with better way to set class, restore using this if problems + /*CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon(); + if(cainfo && cainfo->bytes0 != 0) + m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0); + else + m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);*/ + + if(m_target->GetCharmInfo()) + m_target->GetCharmInfo()->SetPetNumber(0, true); + else + sLog.outError("Aura::HandleModCharm: target (GUID: %u TypeId: %u) has a charm aura but no charm info!", m_target->GetGUIDLow(), m_target->GetTypeId()); } } + + caster->SetCharm(NULL); + + if(caster->GetTypeId() == TYPEID_PLAYER) + ((Player*)caster)->RemovePetActionBar(); + + if(m_target->GetTypeId() == TYPEID_UNIT) + { + ((Creature*)m_target)->AIM_Initialize(); + if (((Creature*)m_target)->AI()) + ((Creature*)m_target)->AI()->AttackedBy(caster); + } } } diff --git a/src/game/Unit.h b/src/game/Unit.h index ace8b0293..8762723a7 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -514,7 +514,7 @@ enum UnitFlags UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip. UNIT_FLAG_CONFUSED = 0x00400000, UNIT_FLAG_FLEEING = 0x00800000, - UNIT_FLAG_UNK_24 = 0x01000000, // used in spell Eyes of the Beast for pet... + UNIT_FLAG_PLAYER_CONTROLLED= 0x01000000, // used in spell Eyes of the Beast for pet... let attack by controlled creature UNIT_FLAG_NOT_SELECTABLE = 0x02000000, UNIT_FLAG_SKINNABLE = 0x04000000, UNIT_FLAG_MOUNT = 0x08000000, diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 1faff6528..ff2b133ff 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8146" + #define REVISION_NR "8147" #endif // __REVISION_NR_H__