diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game/Item.cpp | 7 | ||||
-rw-r--r-- | src/game/Player.cpp | 201 | ||||
-rw-r--r-- | src/game/Player.h | 3 | ||||
-rw-r--r-- | src/game/Spell.cpp | 48 | ||||
-rw-r--r-- | src/game/Spell.h | 1 | ||||
-rw-r--r-- | src/game/SpellEffects.cpp | 29 |
6 files changed, 224 insertions, 65 deletions
diff --git a/src/game/Item.cpp b/src/game/Item.cpp index 1633885d382..0197de1d3ff 100644 --- a/src/game/Item.cpp +++ b/src/game/Item.cpp @@ -285,15 +285,8 @@ void Item::UpdateDuration(Player* owner, uint32 diff) if (GetUInt32Value(ITEM_FIELD_DURATION)<=diff) { - // variables to hold item location and entry data after item gets destroyed - uint32 itemEntry = GetEntry(); - uint8 bagSlot = GetBagSlot(); - uint8 slot = GetSlot(); - uint16 pos = GetPos(); - Script->ItemExpire(owner, GetProto()); owner->DestroyItem(GetBagSlot(), GetSlot(), true); - owner->HandleDestroyItemReplace(itemEntry, bagSlot, slot, pos); return; } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index afc39c93bb2..58c80f46652 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -9413,10 +9413,100 @@ bool Player::HasItemOrGemWithLimitCategoryEquipped( uint32 limitCategory, uint32 return false; } +uint8 Player::CountItemWithLimitCategory(uint32 limitCategory, Item* skipItem) const +{ + uint8 tempcount = 0; + for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i) + { + Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if (!pItem) + continue; + + if (pItem == skipItem) + continue; + + ItemPrototype const *pProto = pItem->GetProto(); + if (pProto && pProto->ItemLimitCategory == limitCategory) + tempcount += pItem->GetCount(); + } + + for(int i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i) + { + Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if (!pItem) + continue; + + if (pItem == skipItem) + continue; + + ItemPrototype const *pProto = pItem->GetProto(); + if (pProto && pProto->ItemLimitCategory == limitCategory) + tempcount += pItem->GetCount(); + } + + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) + { + Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if (!pBag) + continue; + + for(uint32 j = 0; j < pBag->GetBagSize(); ++j) + { + Item *pItem = GetItemByPos( i, j ); + + if (!pItem) + continue; + + if (pItem == skipItem) + continue; + + if (pItem->GetProto()->ItemLimitCategory == limitCategory) + tempcount += pItem->GetCount(); + } + } + + for(int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; ++i) + { + Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if (!pItem) + continue; + + if (pItem == skipItem) + continue; + + ItemPrototype const *pProto = pItem->GetProto(); + if (pProto && pProto->ItemLimitCategory == limitCategory) + tempcount += pItem->GetCount(); + } + + for(int i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i) + { + Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + if (!pBag) + continue; + + for(uint32 j = 0; j < pBag->GetBagSize(); ++j) + { + Item *pItem = GetItemByPos( i, j ); + + if(!pItem) + continue; + + if(pItem == skipItem) + continue; + + if(pItem->GetProto()->ItemLimitCategory == limitCategory) + tempcount += pItem->GetCount(); + } + } + + return tempcount; +} + uint8 Player::_CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count ) const { ItemPrototype const *pProto = objmgr.GetItemPrototype(entry); - if( !pProto ) + if (!pProto) { if(no_space_count) *no_space_count = count; @@ -9424,18 +9514,36 @@ uint8 Player::_CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, } // no maximum - if(pProto->MaxCount <= 0 || pProto->MaxCount == 2147483647) + if (pProto->MaxCount <= 0 && pProto->ItemLimitCategory == 0 || pProto->MaxCount == 2147483647) return EQUIP_ERR_OK; - uint32 curcount = GetItemCount(pProto->ItemId,true,pItem); + uint32 curcount; + if (pProto->ItemLimitCategory) + curcount = CountItemWithLimitCategory(pProto->ItemLimitCategory,pItem); + else + curcount = GetItemCount(pProto->ItemId,true,pItem); - if (curcount + count > uint32(pProto->MaxCount)) + if ((curcount + count > uint32(pProto->MaxCount)) && !(pProto->ItemLimitCategory)) { - if(no_space_count) + if (no_space_count) *no_space_count = count +curcount - pProto->MaxCount; return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; } + if (pProto->ItemLimitCategory && pProto->Class!=ITEM_CLASS_GEM) // gem have equip check (maybe sort by bonding?) + { + ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(pProto->ItemLimitCategory); + if (!limitEntry) + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + + if (curcount + count > limitEntry->maxCount) + { + if (no_space_count) + *no_space_count = count + curcount - limitEntry->maxCount; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; // attempt add too many limit category items + } + } + return EQUIP_ERR_OK; } @@ -11396,54 +11504,6 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update) } } - -void Player::HandleDestroyItemReplace( uint32 itemEntry, uint8 bag ,uint8 slot, uint16 pos ) -{ - if(!itemEntry || !slot || !bag) - return; - - uint32 newItemEntry = 0; - switch(itemEntry) - { - case 39878: // Mysterious Unhatched Egg - newItemEntry = 39883; - break; - case 44717: // Disgusting Jar - newItemEntry = 44718; - break; - default: - return; - } - - Item *pNewItem = Item::CreateItem( newItemEntry, 1, this); - if( !pNewItem ) - return; - - if( IsInventoryPos( pos ) ) - { - ItemPosCountVec dest; - uint8 msg = CanStoreItem( bag, slot, dest, pNewItem, true ); - if( msg == EQUIP_ERR_OK ) - { - StoreItem( dest, pNewItem, true); - return; - } - } - else if( IsBankPos ( pos ) ) - { - ItemPosCountVec dest; - uint8 msg = CanBankItem( bag, slot, dest, pNewItem, true ); - if( msg == EQUIP_ERR_OK ) - { - BankItem( dest, pNewItem, true); - return; - } - } - - // fail - delete pNewItem; -} - void Player::DestroyItemCount(uint32 item, uint32 count, bool update, bool unequip_check) { sLog.outDebug( "STORAGE: DestroyItemCount item = %u, count = %u", item, count); @@ -11630,6 +11690,41 @@ void Player::DestroyConjuredItems( bool update ) DestroyItem( INVENTORY_SLOT_BAG_0, i, update); } +Item* Player::GetItemByEntry(uint32 entry) const +{ + // in inventory + for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; ++i) + { + if (Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + if (pItem->GetEntry() == entry) + return pItem; + } + + + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) + { + if (Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + { + for(uint32 j = 0; j < pBag->GetBagSize(); ++j) + { + if (Item* pItem = pBag->GetItemByPos(j)) + if (pItem->GetEntry()==entry) + return pItem; + } + } + } + + + for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; ++i) + { + if (Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + if (pItem->GetEntry()==entry) + return pItem; + } + + return NULL; +} + void Player::DestroyItemCount( Item* pItem, uint32 &count, bool update ) { if(!pItem) diff --git a/src/game/Player.h b/src/game/Player.h index ed7f1f3e7d6..53358c03817 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1106,6 +1106,7 @@ class TRINITY_DLL_SPEC Player : public Unit, public GridObject<Player> uint8 FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap ) const; uint32 GetItemCount( uint32 item, bool inBankAlso = false, Item* skipItem = NULL ) const; Item* GetItemByGuid( uint64 guid ) const; + Item* GetItemByEntry( uint32 entry ) const; Item* GetItemByPos( uint16 pos ) const; Item* GetItemByPos( uint8 bag, uint8 slot ) const; inline Item* GetUseableItemByPos( uint8 bag, uint8 slot ) const //Does additional check for disarmed weapons @@ -1134,6 +1135,7 @@ class TRINITY_DLL_SPEC Player : public Unit, public GridObject<Player> bool CanNoReagentCast(SpellEntry const* spellInfo) const; bool HasItemOrGemWithIdEquipped( uint32 item, uint32 count, uint8 except_slot = NULL_SLOT) const; bool HasItemOrGemWithLimitCategoryEquipped( uint32 limitCategory, uint32 count, uint8 except_slot = NULL_SLOT) const; + uint8 CountItemWithLimitCategory(uint32 limitCategory, Item* skipItem = NULL) const; uint8 CanTakeMoreSimilarItems(Item* pItem) const { return _CanTakeMoreSimilarItems(pItem->GetEntry(),pItem->GetCount(),pItem); } uint8 CanTakeMoreSimilarItems(uint32 entry, uint32 count) const { return _CanTakeMoreSimilarItems(entry,count,NULL); } uint8 CanStoreNewItem( uint8 bag, uint8 slot, ItemPosCountVec& dest, uint32 item, uint32 count, uint32* no_space_count = NULL ) const @@ -1192,7 +1194,6 @@ class TRINITY_DLL_SPEC Player : public Unit, public GridObject<Player> void MoveItemToInventory(ItemPosCountVec const& dest, Item* pItem, bool update, bool in_characterInventoryDB = false); // in trade, guild bank, mail.... void RemoveItemDependentAurasAndCasts( Item * pItem ); - void HandleDestroyItemReplace( uint32 itemEntry, uint8 bag , uint8 slot , uint16 pos); void DestroyItem( uint8 bag, uint8 slot, bool update ); void DestroyItemCount( uint32 item, uint32 count, bool update, bool unequip_check = false); void DestroyItemCount( Item* item, uint32& count, bool update ); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 0e56c276bb0..a33c7335d9f 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -3458,6 +3458,17 @@ void Spell::SendCastResult(Player* caster, SpellEntry const* spellInfo, uint8 ca data << uint32(spellInfo->EquippedItemSubClassMask); //data << uint32(spellInfo->EquippedItemInventoryTypeMask); break; + case SPELL_FAILED_TOO_MANY_OF_ITEM: + { + uint32 item; + for(int8 x=0;x < 3;x++) + if (spellInfo->EffectItemType[x]) + item = spellInfo->EffectItemType[x]; + ItemPrototype const *pProto = objmgr.GetItemPrototype(item); + if (pProto && pProto->ItemLimitCategory) + data << uint32(pProto->ItemLimitCategory); + break; + } default: break; } @@ -5770,8 +5781,22 @@ SpellCastResult Spell::CheckItems() uint8 msg = p_caster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, m_spellInfo->EffectItemType[i], 1 ); if (msg != EQUIP_ERR_OK ) { - p_caster->SendEquipError( msg, NULL, NULL ); - return SPELL_FAILED_DONT_REPORT; + ItemPrototype const *pProto = objmgr.GetItemPrototype(m_spellInfo->EffectItemType[i]); + if (pProto && !(pProto->ItemLimitCategory)) + { + p_caster->SendEquipError( msg, NULL, NULL ); + return SPELL_FAILED_DONT_REPORT; + } + else + { + if (!(m_spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x40000000)))) + return SPELL_FAILED_TOO_MANY_OF_ITEM; + else if (!(p_caster->HasItemCount(m_spellInfo->EffectItemType[i],1))) + return SPELL_FAILED_TOO_MANY_OF_ITEM; + else + p_caster->CastSpell(m_caster,m_spellInfo->CalculateSimpleValue(1),false); // move this to anywhere + return SPELL_FAILED_DONT_REPORT; + } } } break; @@ -5973,7 +5998,24 @@ SpellCastResult Spell::CheckItems() } break; } - default:break; + case SPELL_EFFECT_CREATE_MANA_GEM: + { + uint32 item_id = m_spellInfo->EffectItemType[i]; + ItemPrototype const *pProto = objmgr.GetItemPrototype(item_id); + + if (!pProto) + return SPELL_FAILED_ITEM_AT_MAX_CHARGES; + + if (Item* pitem = p_caster->GetItemByEntry(item_id)) + { + for(int x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) + if (pProto->Spells[x].SpellCharges != 0 && pitem->GetSpellCharges(x) == pProto->Spells[x].SpellCharges) + return SPELL_FAILED_ITEM_AT_MAX_CHARGES; + } + break; + } + default: + break; } } diff --git a/src/game/Spell.h b/src/game/Spell.h index 15af2664fa4..96d220bd696 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -364,6 +364,7 @@ class Spell void EffectSpecCount(uint32 i); void EffectActivateSpec(uint32 i); void EffectCastButtons(uint32 i); + void EffectRechargeManaGem(uint32 i); typedef std::set<Aura *> UsedSpellMods; diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index b12b7797c03..8a60e9b4845 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -131,7 +131,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID - &Spell::EffectUnused, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID) + &Spell::EffectRechargeManaGem, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID) &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT @@ -7497,3 +7497,30 @@ void Spell::EffectCastButtons(uint32 i) } } } + +void Spell::EffectRechargeManaGem(uint32 i) +{ + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + Player *player = (Player*)m_caster; + + if (!player) + return; + + uint32 item_id = m_spellInfo->EffectItemType[0]; + + ItemPrototype const *pProto = objmgr.GetItemPrototype(item_id); + if(!pProto) + { + player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + if (Item* pItem = player->GetItemByEntry(item_id)) + { + for(int x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) + pItem->SetSpellCharges(x,pProto->Spells[x].SpellCharges); + pItem->SetState(ITEM_CHANGED,player); + } +} |