From 3490f642cf5bb7abd59ec001eb773044cf9d0b4e Mon Sep 17 00:00:00 2001 From: sanctum32 Date: Mon, 18 Nov 2013 19:04:50 +0200 Subject: [PATCH] [12736] Implemented reforge, also added missing part for HandleObjectUpdateFailedOpcode --- src/game/DBCStores.cpp | 11 +- src/game/DBCStores.h | 1 + src/game/DBCStructure.h | 11 +- src/game/DBCfmt.h | 3 +- src/game/Item.cpp | 105 ++++++++++++++++- src/game/Item.h | 5 + src/game/ItemHandler.cpp | 75 +++++++++++- src/game/ItemPrototype.h | 1 + src/game/MiscHandler.cpp | 7 ++ src/game/Opcodes.cpp | 4 +- src/game/Opcodes.h | 4 +- src/game/Player.cpp | 240 ++++++++++++++++++++++++++++++++++++++ src/game/Player.h | 1 + src/game/TradeHandler.cpp | 2 +- src/game/Unit.h | 1 + src/game/WorldSession.h | 5 + src/shared/revision_nr.h | 2 +- 17 files changed, 464 insertions(+), 14 deletions(-) diff --git a/src/game/DBCStores.cpp b/src/game/DBCStores.cpp index e2c573501..d9eb3ba1c 100644 --- a/src/game/DBCStores.cpp +++ b/src/game/DBCStores.cpp @@ -131,9 +131,11 @@ DBCStorage sItemDamageTwoHandStore(ItemDamagefmt) DBCStorage sItemDamageTwoHandCasterStore(ItemDamagefmt); DBCStorage sItemDamageWandStore(ItemDamagefmt); //DBCStorage sItemDisplayInfoStore(ItemDisplayTemplateEntryfmt); -- not used currently -DBCStorage sItemLimitCategoryStore(ItemLimitCategoryEntryfmt); -DBCStorage sItemRandomPropertiesStore(ItemRandomPropertiesfmt); -DBCStorage sItemRandomSuffixStore(ItemRandomSuffixfmt); +DBCStorage sItemLimitCategoryStore(ItemLimitCategoryEntryfmt); +DBCStorage sItemRandomPropertiesStore(ItemRandomPropertiesfmt); +DBCStorage sItemRandomSuffixStore(ItemRandomSuffixfmt); +DBCStorage sItemReforgeStore(ItemReforgefmt); + DBCStorage sItemSetStore(ItemSetEntryfmt); DBCStorage sLiquidTypeStore(LiquidTypefmt); DBCStorage sLockStore(LockEntryfmt); @@ -417,7 +419,7 @@ void LoadDBCStores(const std::string& dataPath) exit(1); } - const uint32 DBCFilesCount = 124; + const uint32 DBCFilesCount = 129; BarGoLink bar(DBCFilesCount); @@ -536,6 +538,7 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemArmorShieldStore, dbcPath,"ItemArmorShield.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemArmorTotalStore, dbcPath,"ItemArmorTotal.dbc"); LoadDBC(availableDbcLocales, bar, bad_dbc_files, sItemBagFamilyStore, dbcPath, "ItemBagFamily.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemReforgeStore, dbcPath, "ItemReforge.dbc"); LoadDBC(availableDbcLocales, bar, bad_dbc_files, sItemClassStore, dbcPath, "ItemClass.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemDamageAmmoStore, dbcPath,"ItemDamageAmmo.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemDamageOneHandStore, dbcPath,"ItemDamageOneHand.dbc"); diff --git a/src/game/DBCStores.h b/src/game/DBCStores.h index 69f4e12f9..b7fd92811 100644 --- a/src/game/DBCStores.h +++ b/src/game/DBCStores.h @@ -171,6 +171,7 @@ extern DBCStorage sItemDamageWandStore; extern DBCStorage sItemLimitCategoryStore; extern DBCStorage sItemRandomPropertiesStore; extern DBCStorage sItemRandomSuffixStore; +extern DBCStorage sItemReforgeStore; extern DBCStorage sItemSetStore; extern DBCStorage sLiquidTypeStore; extern DBCStorage sLockStore; diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index b17f738e6..a8a0a67a3 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -1162,7 +1162,7 @@ struct ItemClassEntry uint32 Class; // 1 //uint32 unk2; // 2 looks like second class //uint32 unk3; // 3 1 for weapons - //float Multiplier // 4 + float PriceFactor; // 4 DBCString name; // 5 m_name_lang }; @@ -1223,6 +1223,15 @@ struct ItemRandomSuffixEntry uint32 prefix[5]; // 8-12 m_allocationPct }; +struct ItemReforgeEntry +{ + uint32 Id; // 0 + uint32 SourceStat; // 1 + float SourceMultiplier; // 2 + uint32 FinalStat; // 3 + float FinalMultiplier; // 4 +}; + struct ItemSetEntry { //uint32 id // 0 m_ID diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h index afa3ec9ce..d93510882 100644 --- a/src/game/DBCfmt.h +++ b/src/game/DBCfmt.h @@ -71,7 +71,7 @@ const char GtSpellScalingfmt[]="df"; const char GtOCTBaseHPByClassfmt[]="df"; const char GtOCTBaseMPByClassfmt[]="df"; const char Holidaysfmt[] = "nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; -const char ItemClassfmt[]="nixxxs"; +const char ItemClassfmt[]="nixxfs"; const char ItemArmorQualityfmt[]="nfffffffi"; const char ItemArmorShieldfmt[]="nifffffff"; const char ItemArmorTotalfmt[]="niffff"; @@ -82,6 +82,7 @@ const char ItemDamagefmt[]="nfffffffi"; const char ItemLimitCategoryEntryfmt[]="nxii"; const char ItemRandomPropertiesfmt[]="nxiiiiis"; const char ItemRandomSuffixfmt[]="nsxiiiiiiiiii"; +const char ItemReforgefmt[]="nifif"; const char ItemSetEntryfmt[]="dsxxxxxxxxxxxxxxxxxiiiiiiiiiiiiiiiiii"; const char LiquidTypefmt[] = "nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char LockEntryfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx"; diff --git a/src/game/Item.cpp b/src/game/Item.cpp index 6ddda7601..c2a46c820 100644 --- a/src/game/Item.cpp +++ b/src/game/Item.cpp @@ -812,8 +812,8 @@ void Item::SetItemRandomProperties(int32 randomPropId) SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, item_rand->ID); SetState(ITEM_CHANGED); } - for (uint32 i = PROP_ENCHANTMENT_SLOT_2; i < PROP_ENCHANTMENT_SLOT_2 + 3; ++i) - SetEnchantment(EnchantmentSlot(i), item_rand->enchant_id[i - PROP_ENCHANTMENT_SLOT_2], 0, 0); + for (uint32 i = PROP_ENCHANTMENT_SLOT_1; i < PROP_ENCHANTMENT_SLOT_4; ++i) + SetEnchantment(EnchantmentSlot(i), item_rand->enchant_id[i - PROP_ENCHANTMENT_SLOT_1], 0, 0); } } else @@ -829,7 +829,7 @@ void Item::SetItemRandomProperties(int32 randomPropId) SetState(ITEM_CHANGED); } - for (uint32 i = PROP_ENCHANTMENT_SLOT_0; i < PROP_ENCHANTMENT_SLOT_0 + 3; ++i) + for (uint32 i = PROP_ENCHANTMENT_SLOT_0; i < PROP_ENCHANTMENT_SLOT_4; ++i) SetEnchantment(EnchantmentSlot(i), item_rand->enchant_id[i - PROP_ENCHANTMENT_SLOT_0], 0, 0); } } @@ -1394,3 +1394,102 @@ void Item::SetLootState(ItemLootUpdateState state) if (m_lootState != ITEM_LOOT_NONE && m_lootState != ITEM_LOOT_UNCHANGED && m_lootState != ITEM_LOOT_TEMPORARY) SetState(ITEM_CHANGED); } + +uint32 Item::GetSpecialPrice(ItemPrototype const* proto, uint32 minimumPrice /*= 10000*/) +{ + uint32 cost = 0; + + if (proto->Flags2 & ITEM_FLAG2_HAS_NORMAL_PRICE) + cost = proto->SellPrice; + else + { + bool normalPrice = true; + //cost = Item::GetSellPrice(proto, normalPrice); + cost = proto->SellPrice; + + if (!normalPrice) + { + if (proto->BuyCount <= 1) + { + ItemClassEntry const* classEntry = sItemClassStore.LookupEntry(proto->Class); + if (classEntry) + cost *= classEntry->PriceFactor; + else + cost = 0; + } + else + cost /= 4 * proto->BuyCount; + } + else + cost = proto->SellPrice; + } + + if (cost < minimumPrice) + cost = minimumPrice; + + return cost; +} + +int32 Item::GetReforgableStat(ItemModType statType) const +{ + ItemPrototype const* proto = GetProto(); + for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) + if (proto->ItemStat[i].ItemStatType == statType) + return proto->ItemStat[i].ItemStatValue; + + int32 randomPropId = GetItemRandomPropertyId(); + if (!randomPropId) + return 0; + + if (randomPropId < 0) + { + ItemRandomSuffixEntry const* randomSuffix = sItemRandomSuffixStore.LookupEntry(-randomPropId); + if (!randomSuffix) + return 0; + + for (uint32 e = PROP_ENCHANTMENT_SLOT_0; e <= PROP_ENCHANTMENT_SLOT_4; ++e) + { + if (SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(GetEnchantmentId(EnchantmentSlot(e)))) + { + for (uint32 f = 0; f < 3; ++f) + { + if (enchant->type[f] == ITEM_ENCHANTMENT_TYPE_STAT && enchant->spellid[f] == statType) + { + for (int k = 0; k < 5; ++k) + { + if (randomSuffix->enchant_id[k] == enchant->ID) + return int32((randomSuffix->prefix[k] * GetItemSuffixFactor()) / 10000); + } + } + } + } + } + } + else + { + ItemRandomPropertiesEntry const* randomProp = sItemRandomPropertiesStore.LookupEntry(randomPropId); + if (!randomProp) + return 0; + + for (uint32 e = PROP_ENCHANTMENT_SLOT_0; e <= PROP_ENCHANTMENT_SLOT_4; ++e) + { + if (SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(GetEnchantmentId(EnchantmentSlot(e)))) + { + for (uint32 f = 0; f < 3; ++f) + { + if (enchant->type[f] == ITEM_ENCHANTMENT_TYPE_STAT && enchant->spellid[f] == statType) + { + for (int k = 0; k < 3; ++k) + { + if (randomProp->enchant_id[k] == enchant->ID) + return int32(enchant->amount[k]); + } + } + } + } + } + + } + return 0; +} + diff --git a/src/game/Item.h b/src/game/Item.h index 37f26b658..429678fea 100644 --- a/src/game/Item.h +++ b/src/game/Item.h @@ -388,6 +388,11 @@ class MANGOS_DLL_SPEC Item : public Object void AddToClientUpdateList() override; void RemoveFromClientUpdateList() override; void BuildUpdateData(UpdateDataMapType& update_players) override; + + // Reforge + static uint32 GetSpecialPrice(ItemPrototype const* proto, uint32 minimumPrice = 10000); + uint32 GetSpecialPrice(uint32 minimumPrice = 10000) const { return Item::GetSpecialPrice(GetProto(), minimumPrice); } + int32 GetReforgableStat(ItemModType statType) const; private: std::string m_text; uint8 m_slot; diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 853bc5947..8efb27f5f 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -1481,4 +1481,77 @@ void WorldSession::SendItemSparseDb2Reply(uint32 entry) data.append(buff); SendPacket(&data); -} +} + +void WorldSession::SendReforgeResult(bool success) +{ + WorldPacket data(SMSG_REFORGE_RESULT, 1); + data.WriteBit(success); + SendPacket(&data); +} + +void WorldSession::HandleReforgeItemOpcode(WorldPacket& recvData) +{ + uint32 slot, reforgeEntry; + ObjectGuid guid; + uint32 bag; + Player* player = GetPlayer(); + + recvData >> reforgeEntry >> slot >> bag; + recvData.ReadGuidMask<2, 6, 3, 4, 1, 0, 7, 5>(guid); + recvData.ReadGuidBytes<2, 3, 6, 4, 1, 0, 7, 5>(guid); + + if (!player->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_REFORGER)) + { + sLog.outDebug("WORLD: HandleReforgeItemOpcode - Unit (GUID: %s) not found or player can't interact with it.", guid.GetString().c_str()); + SendReforgeResult(false); + return; + } + + Item* item = player->GetItemByPos(bag, slot); + if (!item) + { + sLog.outDebug("WORLD: HandleReforgeItemOpcode - Player (Guid: %s) tried to reforge an invalid/non-existant item.", player->GetGuidStr().c_str()); + SendReforgeResult(false); + return; + } + + if (!reforgeEntry) + { + // Reset the item + if (item->IsEquipped()) + player->ApplyReforgeEnchantment(item, false); + + item->ClearEnchantment(REFORGE_ENCHANTMENT_SLOT); + SendReforgeResult(true); + return; + } + + ItemReforgeEntry const* stats = sItemReforgeStore.LookupEntry(reforgeEntry); + if (!stats) + { + sLog.outDebug("WORLD: HandleReforgeItemOpcode - Player (Guid: %s) tried to reforge an item with invalid reforge entry (%u).", player->GetGuidStr().c_str(), reforgeEntry); + SendReforgeResult(false); + return; + } + + if (!item->GetReforgableStat(ItemModType(stats->SourceStat)) || item->GetReforgableStat(ItemModType(stats->FinalStat))) // Cheating, you cant reforge to a stat that the item already has, nor reforge from a stat that the item does not have + { + SendReforgeResult(false); + return; + } + + if (player->GetMoney() < uint64(item->GetSpecialPrice())) // cheating + { + SendReforgeResult(false); + return; + } + + player->ModifyMoney(-int64(item->GetSpecialPrice())); + item->SetEnchantment(REFORGE_ENCHANTMENT_SLOT, reforgeEntry, 0, 0); + SendReforgeResult(true); + + if (item->IsEquipped()) + player->ApplyReforgeEnchantment(item, true); +} + diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h index 812df16c9..301ba5854 100644 --- a/src/game/ItemPrototype.h +++ b/src/game/ItemPrototype.h @@ -158,6 +158,7 @@ enum ItemPrototypeFlags2 ITEM_FLAG2_UNK8 = 0x00000080, ITEM_FLAG2_NEED_ROLL_DISABLED = 0x00000100, // need roll during looting is not allowed for this item ITEM_FLAG2_CASTER_WEAPON = 0x00000200, // uses caster specific dbc file for DPS calculations + ITEM_FLAG2_HAS_NORMAL_PRICE = 0x00004000, }; enum BagFamilyMask diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index aba2c6502..fa5b3404b 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1604,5 +1604,12 @@ void WorldSession::HandleObjectUpdateFailedOpcode(WorldPacket& recv_data) recv_data.ReadGuidBytes<6, 7, 2, 3, 1, 4, 0, 5>(guid); DEBUG_LOG("WORLD: Received CMSG_OBJECT_UPDATE_FAILED from %s (%u) guid: %s", GetPlayerName(), GetAccountId(), guid.GetString().c_str()); + if (_player->IsInWorld()) + { + if (WorldObject* obj = _player->GetMap()->GetWorldObject(guid)) + obj->SendCreateUpdateToPlayer(_player); + } + else + sLog.outError("WorldSession::HandleObjectUpdateFailedOpcode: received from player not in map"); } diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index eb1e78fe1..12d89a568 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -1408,5 +1408,7 @@ void InitializeOpcodes() OPCODE(SMSG_PVP_OPTIONS_ENABLED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(CMSG_REQUEST_HOTFIX, STATUS_AUTHED, PROCESS_INPLACE, &WorldSession::HandleRequestHotfix ); OPCODE(SMSG_DB_REPLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - OPCODE(CMSG_OBJECT_UPDATE_FAILED, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleObjectUpdateFailedOpcode ); + //OPCODE(CMSG_OBJECT_UPDATE_FAILED, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleObjectUpdateFailedOpcode ); + OPCODE(CMSG_REFORGE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReforgeItemOpcode ); + OPCODE(SMSG_REFORGE_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); }; diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index ffcee06ec..6d4a7b907 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -1426,7 +1426,9 @@ enum Opcodes SMSG_PVP_OPTIONS_ENABLED = 0x50A1, // 4.3.4 15595 CMSG_REQUEST_HOTFIX = 0x2401, // 4.3.4 15595 SMSG_DB_REPLY = 0x38A4, // 4.3.4 15595 - CMSG_OBJECT_UPDATE_FAILED = 0x3808, // 4.3.4 15595 + CMSG_OBJECT_UPDATE_FAILED = 0x3808, // 4.3.4 15595 + CMSG_REFORGE_ITEM = 0x331A, // 4.3.4 15595 + SMSG_REFORGE_RESULT = 0x58A4, // 4.3.4 15595 }; #define MAX_OPCODE_TABLE_SIZE 0xFFFF diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 65257fc79..2b33eb88a 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -12450,6 +12450,12 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool if (slot >= MAX_ENCHANTMENT_SLOT) return; + if (slot == REFORGE_ENCHANTMENT_SLOT) + { + ApplyReforgeEnchantment(item, apply); + return; + } + uint32 enchant_id = item->GetEnchantmentId(slot); if (!enchant_id) return; @@ -12741,6 +12747,240 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool } } +void Player::ApplyReforgeEnchantment(Item* item, bool apply) +{ + + if (!item) + return; + + ItemReforgeEntry const* reforge = sItemReforgeStore.LookupEntry(item->GetEnchantmentId(REFORGE_ENCHANTMENT_SLOT)); + if (!reforge) + return; + + float removeValue = item->GetReforgableStat(ItemModType(reforge->SourceStat)) * reforge->SourceMultiplier; + + float addValue = removeValue * reforge->FinalMultiplier; + + switch (reforge->SourceStat) + { + case ITEM_MOD_HEALTH: + HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, -removeValue, apply); + break; + case ITEM_MOD_AGILITY: + HandleStatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, -removeValue, apply); + ApplyStatBuffMod(STAT_AGILITY, -removeValue, apply); + break; + case ITEM_MOD_STRENGTH: + HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, -removeValue, apply); + ApplyStatBuffMod(STAT_STRENGTH, -removeValue, apply); + break; + case ITEM_MOD_INTELLECT: + HandleStatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, -removeValue, apply); + ApplyStatBuffMod(STAT_INTELLECT, -removeValue, apply); + break; + case ITEM_MOD_SPIRIT: + HandleStatModifier(UNIT_MOD_STAT_SPIRIT, TOTAL_VALUE, -removeValue, apply); + ApplyStatBuffMod(STAT_SPIRIT, -removeValue, apply); + break; + case ITEM_MOD_STAMINA: + HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, -removeValue, apply); + ApplyStatBuffMod(STAT_STAMINA, -removeValue, apply); + break; + case ITEM_MOD_DEFENSE_SKILL_RATING: + ApplyRatingMod(CR_DEFENSE_SKILL, -int32(removeValue), apply); + break; + case ITEM_MOD_DODGE_RATING: + ApplyRatingMod(CR_DODGE, -int32(removeValue), apply); + break; + case ITEM_MOD_PARRY_RATING: + ApplyRatingMod(CR_PARRY, -int32(removeValue), apply); + break; + case ITEM_MOD_BLOCK_RATING: + ApplyRatingMod(CR_BLOCK, -int32(removeValue), apply); + break; + case ITEM_MOD_HIT_MELEE_RATING: + ApplyRatingMod(CR_HIT_MELEE, -int32(removeValue), apply); + break; + case ITEM_MOD_HIT_RANGED_RATING: + ApplyRatingMod(CR_HIT_RANGED, -int32(removeValue), apply); + break; + case ITEM_MOD_HIT_SPELL_RATING: + ApplyRatingMod(CR_HIT_SPELL, -int32(removeValue), apply); + break; + case ITEM_MOD_CRIT_MELEE_RATING: + ApplyRatingMod(CR_CRIT_MELEE, -int32(removeValue), apply); + break; + case ITEM_MOD_CRIT_RANGED_RATING: + ApplyRatingMod(CR_CRIT_RANGED, -int32(removeValue), apply); + break; + case ITEM_MOD_CRIT_SPELL_RATING: + ApplyRatingMod(CR_CRIT_SPELL, -int32(removeValue), apply); + break; + case ITEM_MOD_HASTE_SPELL_RATING: + ApplyRatingMod(CR_HASTE_SPELL, -int32(removeValue), apply); + break; + case ITEM_MOD_HIT_RATING: + ApplyRatingMod(CR_HIT_MELEE, -int32(removeValue), apply); + ApplyRatingMod(CR_HIT_RANGED, -int32(removeValue), apply); + ApplyRatingMod(CR_HIT_SPELL, -int32(removeValue), apply); + break; + case ITEM_MOD_CRIT_RATING: + ApplyRatingMod(CR_CRIT_MELEE, -int32(removeValue), apply); + ApplyRatingMod(CR_CRIT_RANGED, -int32(removeValue), apply); + ApplyRatingMod(CR_CRIT_SPELL, -int32(removeValue), apply); + break; + case ITEM_MOD_RESILIENCE_RATING: + ApplyRatingMod(CR_RESILIENCE_DAMAGE_TAKEN, -int32(removeValue), apply); + break; + case ITEM_MOD_HASTE_RATING: + ApplyRatingMod(CR_HASTE_MELEE, -int32(removeValue), apply); + ApplyRatingMod(CR_HASTE_RANGED, -int32(removeValue), apply); + ApplyRatingMod(CR_HASTE_SPELL, -int32(removeValue), apply); + break; + case ITEM_MOD_EXPERTISE_RATING: + ApplyRatingMod(CR_EXPERTISE, -int32(removeValue), apply); + break; + case ITEM_MOD_ATTACK_POWER: + HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, -removeValue, apply); + HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, -removeValue, apply); + break; + case ITEM_MOD_RANGED_ATTACK_POWER: + HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, -removeValue, apply); + break; + case ITEM_MOD_MANA_REGENERATION: + ApplyManaRegenBonus(-int32(removeValue), apply); + break; + case ITEM_MOD_ARMOR_PENETRATION_RATING: + ApplyRatingMod(CR_ARMOR_PENETRATION, -int32(removeValue), apply); + break; + case ITEM_MOD_SPELL_POWER: + ApplySpellPowerBonus(-int32(removeValue), apply); + break; + case ITEM_MOD_HEALTH_REGEN: + ApplyHealthRegenBonus(-int32(removeValue), apply); + break; + case ITEM_MOD_SPELL_PENETRATION: + ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, -int32(removeValue), apply); + m_spellPenetrationItemMod += apply ? -int32(removeValue) : int32(removeValue); + break; + case ITEM_MOD_BLOCK_VALUE: + break; + case ITEM_MOD_MASTERY_RATING: + ApplyRatingMod(CR_MASTERY, -int32(removeValue), apply); + break; + + } + + switch (reforge->FinalStat) + { + case ITEM_MOD_HEALTH: + HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, addValue, apply); + break; + case ITEM_MOD_AGILITY: + HandleStatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, addValue, apply); + ApplyStatBuffMod(STAT_AGILITY, addValue, apply); + break; + case ITEM_MOD_STRENGTH: + HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, addValue, apply); + ApplyStatBuffMod(STAT_STRENGTH, addValue, apply); + break; + case ITEM_MOD_INTELLECT: + HandleStatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, addValue, apply); + ApplyStatBuffMod(STAT_INTELLECT, addValue, apply); + break; + case ITEM_MOD_SPIRIT: + HandleStatModifier(UNIT_MOD_STAT_SPIRIT, TOTAL_VALUE, addValue, apply); + ApplyStatBuffMod(STAT_SPIRIT, addValue, apply); + break; + case ITEM_MOD_STAMINA: + HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, addValue, apply); + ApplyStatBuffMod(STAT_STAMINA, addValue, apply); + break; + case ITEM_MOD_DEFENSE_SKILL_RATING: + ApplyRatingMod(CR_DEFENSE_SKILL, int32(addValue), apply); + break; + case ITEM_MOD_DODGE_RATING: + ApplyRatingMod(CR_DODGE, int32(addValue), apply); + break; + case ITEM_MOD_PARRY_RATING: + ApplyRatingMod(CR_PARRY, int32(addValue), apply); + break; + case ITEM_MOD_BLOCK_RATING: + ApplyRatingMod(CR_BLOCK, int32(addValue), apply); + break; + case ITEM_MOD_HIT_MELEE_RATING: + ApplyRatingMod(CR_HIT_MELEE, int32(addValue), apply); + break; + case ITEM_MOD_HIT_RANGED_RATING: + ApplyRatingMod(CR_HIT_RANGED, int32(addValue), apply); + break; + case ITEM_MOD_HIT_SPELL_RATING: + ApplyRatingMod(CR_HIT_SPELL, int32(addValue), apply); + break; + case ITEM_MOD_CRIT_MELEE_RATING: + ApplyRatingMod(CR_CRIT_MELEE, int32(addValue), apply); + break; + case ITEM_MOD_CRIT_RANGED_RATING: + ApplyRatingMod(CR_CRIT_RANGED, int32(addValue), apply); + break; + case ITEM_MOD_CRIT_SPELL_RATING: + ApplyRatingMod(CR_CRIT_SPELL, int32(addValue), apply); + break; + case ITEM_MOD_HASTE_SPELL_RATING: + ApplyRatingMod(CR_HASTE_SPELL, int32(addValue), apply); + break; + case ITEM_MOD_HIT_RATING: + ApplyRatingMod(CR_HIT_MELEE, int32(addValue), apply); + ApplyRatingMod(CR_HIT_RANGED, int32(addValue), apply); + ApplyRatingMod(CR_HIT_SPELL, int32(addValue), apply); + break; + case ITEM_MOD_CRIT_RATING: + ApplyRatingMod(CR_CRIT_MELEE, int32(addValue), apply); + ApplyRatingMod(CR_CRIT_RANGED, int32(addValue), apply); + ApplyRatingMod(CR_CRIT_SPELL, int32(addValue), apply); + break; + case ITEM_MOD_RESILIENCE_RATING: + ApplyRatingMod(CR_RESILIENCE_DAMAGE_TAKEN, int32(addValue), apply); + break; + case ITEM_MOD_HASTE_RATING: + ApplyRatingMod(CR_HASTE_MELEE, int32(addValue), apply); + ApplyRatingMod(CR_HASTE_RANGED, int32(addValue), apply); + ApplyRatingMod(CR_HASTE_SPELL, int32(addValue), apply); + break; + case ITEM_MOD_EXPERTISE_RATING: + ApplyRatingMod(CR_EXPERTISE, int32(addValue), apply); + break; + case ITEM_MOD_ATTACK_POWER: + HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, addValue, apply); + HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, addValue, apply); + break; + case ITEM_MOD_RANGED_ATTACK_POWER: + HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, addValue, apply); + break; + case ITEM_MOD_MANA_REGENERATION: + ApplyManaRegenBonus(int32(addValue), apply); + break; + case ITEM_MOD_ARMOR_PENETRATION_RATING: + ApplyRatingMod(CR_ARMOR_PENETRATION, int32(addValue), apply); + break; + case ITEM_MOD_SPELL_POWER: + ApplySpellPowerBonus(int32(addValue), apply); + break; + case ITEM_MOD_HEALTH_REGEN: + ApplyHealthRegenBonus(int32(addValue), apply); + break; + case ITEM_MOD_SPELL_PENETRATION: + ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, int32(addValue), apply); + m_spellPenetrationItemMod += apply ? int32(addValue) : -int32(addValue); + break; + case ITEM_MOD_BLOCK_VALUE: + break; + case ITEM_MOD_MASTERY_RATING: + ApplyRatingMod(CR_MASTERY, int32(addValue), apply); + break; + } +} + void Player::SendEnchantmentDurations() { for (EnchantDurationList::const_iterator itr = m_enchantDuration.begin(); itr != m_enchantDuration.end(); ++itr) diff --git a/src/game/Player.h b/src/game/Player.h index 8cd3b1f0e..339cb1783 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1290,6 +1290,7 @@ class MANGOS_DLL_SPEC Player : public Unit void AddEnchantmentDuration(Item* item, EnchantmentSlot slot, uint32 duration); void ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool apply_dur = true, bool ignore_condition = false); void ApplyEnchantment(Item* item, bool apply); + void ApplyReforgeEnchantment(Item* item, bool apply); void SendEnchantmentDurations(); void BuildEnchantmentsInfoData(WorldPacket* data); void AddItemDurations(Item* item); diff --git a/src/game/TradeHandler.cpp b/src/game/TradeHandler.cpp index 37ade660b..2a8165ed1 100644 --- a/src/game/TradeHandler.cpp +++ b/src/game/TradeHandler.cpp @@ -145,7 +145,7 @@ void WorldSession::SendUpdateTrade(bool trader_state /*= true*/) data << uint32(item->GetEnchantmentId(EnchantmentSlot(enchant_slot))); data << uint32(item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY)); data.WriteGuidBytes<6, 2, 7, 4>(creatorGuid); - data << uint32(0); // reforge Id + data << uint32(item->GetEnchantmentId(REFORGE_ENCHANTMENT_SLOT)); // reforge Id data << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY)); data << uint32(item->GetItemRandomPropertyId()); data.WriteGuidBytes<3>(creatorGuid); diff --git a/src/game/Unit.h b/src/game/Unit.h index 375ca87a4..44692ca2c 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -653,6 +653,7 @@ enum NPCFlags UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click), dynamic, set at loading and don't must be set in DB UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000, // players with mounts that have vehicle data should have it set + UNIT_NPC_FLAG_REFORGER = 0x08000000, // reforging }; // used in most movement packets (send and received), 30 bits in client diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 45e3c1881..797401226 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -888,6 +888,11 @@ class MANGOS_DLL_SPEC WorldSession void HandleQueryQuestsCompletedOpcode(WorldPacket& recv_data); void HandleQuestPOIQueryOpcode(WorldPacket& recv_data); void HandleSetCurrencyFlagsOpcode(WorldPacket& recv_data); + + // Reforge + void HandleReforgeItemOpcode(WorldPacket& recvData); + void SendReforgeResult(bool success); + private: // private trade methods void moveItems(Item* myItems[], Item* hisItems[]); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 652198ab9..ed0e62709 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 "12735" + #define REVISION_NR "12736" #endif // __REVISION_NR_H__