bool Item::IsLimitedToAnotherMapOrZone(uint32 cur_mapId, uint32 cur_zoneId) const { ItemPrototype const* proto = GetProto(); return proto && ((proto->Map && proto->Map != cur_mapId) || (proto->Area && proto->Area != cur_zoneId)); }
bool Item::LoadFromDB(uint32 guidLow, Field *fields, ObjectGuid ownerGuid) { // create item before any checks for store correct guid // and allow use "FSetState(ITEM_REMOVED); SaveToDB();" for deleting item from DB Object::_Create(ObjectGuid(HIGHGUID_ITEM, guidLow)); if (!LoadValues(fields[0].GetString())) { sLog.outError("Item #%d have broken data in `data` field. Can't be loaded.", guidLow); return false; } bool need_save = false; // need explicit save data at load fixes // overwrite possible wrong/corrupted guid ObjectGuid new_item_guid = ObjectGuid(HIGHGUID_ITEM, guidLow); if (GetGuidValue(OBJECT_FIELD_GUID) != new_item_guid) { SetGuidValue(OBJECT_FIELD_GUID, new_item_guid); need_save = true; } ItemPrototype const* proto = GetProto(); if(!proto) return false; // update max durability (and durability) if need if(proto->MaxDurability!= GetUInt32Value(ITEM_FIELD_MAXDURABILITY)) { SetUInt32Value(ITEM_FIELD_MAXDURABILITY,proto->MaxDurability); if(GetUInt32Value(ITEM_FIELD_DURABILITY) > proto->MaxDurability) SetUInt32Value(ITEM_FIELD_DURABILITY,proto->MaxDurability); need_save = true; } // recalculate suffix factor if(GetItemRandomPropertyId() < 0) { if(UpdateItemSuffixFactor()) need_save = true; } // Remove bind flag for items vs NO_BIND set if (IsSoulBound() && proto->Bonding == NO_BIND) { ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_BINDED, false); need_save = true; } // update duration if need, and remove if not need if ((proto->Duration == 0) != (GetUInt32Value(ITEM_FIELD_DURATION) == 0)) { SetUInt32Value(ITEM_FIELD_DURATION, proto->Duration); need_save = true; } // set correct owner if (!ownerGuid.IsEmpty() && GetOwnerGuid() != ownerGuid) { SetOwnerGuid(ownerGuid); need_save = true; } // set correct wrapped state if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED)) { // wrapped item must be wrapper (used version that not stackable) if (!(proto->Flags & ITEM_FLAG_WRAPPER) || GetMaxStackCount() > 1) { RemoveFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED); need_save = true; // also cleanup for sure gift table CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE item_guid = '%u'", GetGUIDLow()); } } if (need_save) // normal item changed state set not work at loading { std::ostringstream ss; ss << "UPDATE item_instance SET data = '"; for(uint16 i = 0; i < m_valuesCount; ++i ) ss << GetUInt32Value(i) << " "; ss << "', owner_guid = '" << GetOwnerGuid().GetCounter() << "' WHERE guid = '" << guidLow << "'"; CharacterDatabase.Execute( ss.str().c_str() ); } return true; }
bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result) { // create item before any checks for store correct guid // and allow use "FSetState(ITEM_REMOVED); SaveToDB();" for deleting item from DB Object::_Create(guid, 0, HIGHGUID_ITEM); if (!result) result = CharacterDatabase.PQuery("SELECT data FROM item_instance WHERE guid = '%u'", guid); if (!result) { sLog->outError("Item (GUID: %u owner: %u) not found in table item_instance, can't load. ", guid, GUID_LOPART(owner_guid)); return false; } Field *fields = result->Fetch(); if (!LoadValues(fields[0].GetString())) { sLog->outError("Item #%d has invalid data in data field. Not loaded.", guid); return false; } bool need_save = false; // need explicit save data at load fixes // overwrite possible wrong/corrupted guid uint64 new_item_guid = MAKE_NEW_GUID(guid, 0, HIGHGUID_ITEM); if (GetUInt64Value(OBJECT_FIELD_GUID) != new_item_guid) { SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_ITEM)); need_save = true; } ItemPrototype const* proto = GetProto(); if (!proto) return false; // recalculate suffix factor if (GetItemRandomPropertyId() < 0) { if (UpdateItemSuffixFactor()) need_save = true; } // Remove bind flag for items vs NO_BIND set if (IsSoulBound() && proto->Bonding == NO_BIND) { ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_BINDED, false); need_save = true; } // update duration if need, and remove if not need if ((proto->Duration == 0) != (GetUInt32Value(ITEM_FIELD_DURATION) == 0)) { SetUInt32Value(ITEM_FIELD_DURATION, abs(proto->Duration)); need_save = true; } // set correct owner if (owner_guid != 0 && GetOwnerGUID() != owner_guid) { SetOwnerGUID(owner_guid); need_save = true; } if (need_save) // normal item changed state set not work at loading { std::ostringstream ss; ss << "UPDATE item_instance SET data = '"; for (uint16 i = 0; i < m_valuesCount; ++i) ss << GetUInt32Value(i) << " "; ss << "', owner_guid = '" << GUID_LOPART(GetOwnerGUID()) << "' WHERE guid = '" << guid << "'"; CharacterDatabase.Execute(ss.str().c_str()); } return true; }
void Item::ApplyEnchantmentBonus( uint32 Slot, bool Apply ) { if( m_owner == NULL ) return; EnchantmentMap::iterator itr = Enchantments.find( Slot ); if( itr == Enchantments.end() ) return; EnchantEntry* Entry = itr->second.Enchantment; uint32 RandomSuffixAmount = itr->second.RandomSuffix; if( itr->second.BonusApplied == Apply ) return; itr->second.BonusApplied = Apply; if( Apply ) { // Send the enchantment time update packet. SendEnchantTimeUpdate( itr->second.Slot, itr->second.Duration ); } // Apply the visual on the player. uint32 ItemSlot = m_owner->GetItemInterface()->GetInventorySlotByGuid( GetGUID() ); if(ItemSlot < EQUIPMENT_SLOT_END) { uint32 VisibleBase = PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + ItemSlot * PLAYER_VISIBLE_ITEM_LENGTH; m_owner->SetUInt32Value( VisibleBase, Apply ? Entry->Id : 0 ); } // Another one of those for loop that where not indented properly god knows what will break // but i made it actually affect the code below it for( uint32 c = 0; c < 3; c++ ) { if( Entry->type[c] ) { // Depending on the enchantment type, take the appropriate course of action. switch( Entry->type[c] ) { case 1: // Trigger spell on melee attack. { if( Apply && Entry->spell[c] != 0 ) { // Create a proc trigger spell ProcTriggerSpell TS; TS.caster = m_owner->GetGUID(); TS.origId = 0; TS.procFlags = PROC_ON_MELEE_ATTACK; if(ItemSlot == EQUIPMENT_SLOT_MAINHAND * PLAYER_VISIBLE_ITEM_LENGTH) TS.weapon_damage_type = 1; // Proc only on main hand attacks else if(ItemSlot == EQUIPMENT_SLOT_OFFHAND * PLAYER_VISIBLE_ITEM_LENGTH) TS.weapon_damage_type = 2; // Proc only on off hand attacks else TS.weapon_damage_type = 0; // Doesn't depend on weapon TS.procCharges = 0; /* This needs to be modified based on the attack speed of the weapon. * Secondly, need to assign some static chance for instant attacks (ss, * gouge, etc.) */ if( !Entry->min[c] && GetProto()->Class == ITEM_CLASS_WEAPON ) { float speed = (float)GetProto()->Delay; /////// procChance calc /////// float ppm = 0; SpellEntry* sp = dbcSpell.LookupEntry( Entry->spell[c] ); if( sp ) { switch( sp->NameHash ) { case SPELL_HASH_FROSTBRAND_ATTACK: ppm = 9; break; } } if( ppm != 0 ) { float pcount = 60/ppm; float chance = (speed/10) / pcount; TS.procChance = (uint32)chance; } else TS.procChance = (uint32)( speed / 600.0f ); /////////////////////////////// } else TS.procChance = Entry->min[c]; DEBUG_LOG( "Enchant", "Setting procChance to %u%%.", TS.procChance ); TS.deleted = false; TS.spellId = Entry->spell[c]; m_owner->m_procSpells.push_back( TS ); } else { // Remove the proctriggerspell uint32 SpellId; list< struct ProcTriggerSpell >::iterator itr/*, itr2*/; for( itr = m_owner->m_procSpells.begin(); itr != m_owner->m_procSpells.end(); ) { SpellId = itr->spellId; /*itr2 = itr++;*/ if( SpellId == Entry->spell[c] ) { //m_owner->m_procSpells.erase(itr2); itr->deleted = true; } itr++; } } }break; case 2: // Mod damage done. { int32 val = Entry->min[c]; if( RandomSuffixAmount ) val = RANDOM_SUFFIX_MAGIC_CALCULATION( RandomSuffixAmount, GetItemRandomSuffixFactor() ); if( Apply ) m_owner->ModUnsigned32Value( PLAYER_FIELD_MOD_DAMAGE_DONE_POS, val ); else m_owner->ModUnsigned32Value( PLAYER_FIELD_MOD_DAMAGE_DONE_POS, -val ); m_owner->CalcDamage(); }break; case 3: // Cast spell (usually means apply aura) { if( Apply ) { SpellCastTargets targets( m_owner->GetGUID() ); SpellEntry* sp; if( Entry->spell[c] != 0 ) { sp = dbcSpell.LookupEntryForced( Entry->spell[c] ); if( sp == NULL ) continue; Spell* spell = NULLSPELL; //Never found out why, //but this Blade of Life's Inevitability spell must be casted by the item, not owner. if( m_itemProto->ItemId != 34349 ) spell = (new Spell( m_owner, sp, true, NULLAURA )); else spell = (new Spell( TO_ITEM(this), sp, true, NULLAURA )); spell->i_caster = TO_ITEM(this); spell->prepare( &targets ); } } else { if( Entry->spell[c] != 0 ) m_owner->RemoveAura( Entry->spell[c] ); } }break; case 4: // Modify physical resistance { int32 val = Entry->min[c]; if( RandomSuffixAmount ) val = RANDOM_SUFFIX_MAGIC_CALCULATION( RandomSuffixAmount, GetItemRandomSuffixFactor() ); if( Apply ) { m_owner->FlatResistanceModifierPos[Entry->spell[c]] += val; } else { m_owner->FlatResistanceModifierPos[Entry->spell[c]] -= val; } m_owner->CalcResistance( Entry->spell[c] ); }break; case 5: //Modify rating ...order is PLAYER_FIELD_COMBAT_RATING_1 and above { //spellid is enum ITEM_STAT_TYPE //min=max is amount int32 val = Entry->min[c]; if( RandomSuffixAmount ) val = RANDOM_SUFFIX_MAGIC_CALCULATION( RandomSuffixAmount, GetItemRandomSuffixFactor() ); m_owner->ModifyBonuses( Entry->spell[c], Apply ? val : -val ); m_owner->UpdateStats(); }break; case 6: // Rockbiter weapon (increase damage per second... how the hell do you calc that) { if( Apply ) { //m_owner->ModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS, Entry->min[c]); //if i'm not wrong then we should apply DMPS formula for this. This will have somewhat a larger value 28->34 int32 val = Entry->min[c]; if( RandomSuffixAmount ) val = RANDOM_SUFFIX_MAGIC_CALCULATION( RandomSuffixAmount, GetItemRandomSuffixFactor() ); int32 value = GetProto()->Delay * val / 1000; m_owner->ModUnsigned32Value( PLAYER_FIELD_MOD_DAMAGE_DONE_POS, value ); } else { int32 val = Entry->min[c]; if( RandomSuffixAmount ) val = RANDOM_SUFFIX_MAGIC_CALCULATION( RandomSuffixAmount, GetItemRandomSuffixFactor() ); int32 value =- (int32)(GetProto()->Delay * val / 1000 ); m_owner->ModUnsigned32Value( PLAYER_FIELD_MOD_DAMAGE_DONE_POS, value ); } m_owner->CalcDamage(); }break; default: { DEBUG_LOG( "Enchant","Unknown enchantment type: %u (%u)", Entry->type[c], Entry->Id ); }break; } } } }