Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/src/server/game/Entities/Item/ItemPrototype.h b/src/server/game/Entities/Item/ItemPrototype.h
- index 5088a30..f83078b 100755
- --- a/src/server/game/Entities/Item/ItemPrototype.h
- +++ b/src/server/game/Entities/Item/ItemPrototype.h
- @@ -743,6 +743,7 @@ struct ItemTemplate
- // Benchmarked: Faster than std::map (insert/find)
- typedef UNORDERED_MAP<uint32, ItemTemplate> ItemTemplateContainer;
- +typedef UNORDERED_MAP<uint32, std::map<uint32, int32> > ItemFakeStatContainer; // custom
- struct ItemLocale
- {
- diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
- index 3b51411..8380965 100755
- --- a/src/server/game/Entities/Player/Player.cpp
- +++ b/src/server/game/Entities/Player/Player.cpp
- @@ -7737,6 +7737,10 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
- if (only_level_scale && !ssv)
- return;
- + uint32 lowGUID = 0;
- + if(Item* invItem = GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
- + if(sObjectMgr->_itemFakeStatStore.find(invItem->GetGUIDLow()) != sObjectMgr->_itemFakeStatStore.end())
- + lowGUID = invItem->GetGUIDLow();
- for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
- {
- uint32 statType = 0;
- @@ -7755,6 +7759,8 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
- continue;
- statType = proto->ItemStat[i].ItemStatType;
- val = proto->ItemStat[i].ItemStatValue;
- + if(lowGUID && sObjectMgr->_itemFakeStatStore[lowGUID].find(i) != sObjectMgr->_itemFakeStatStore[lowGUID].end())
- + val += sObjectMgr->_itemFakeStatStore[lowGUID][i];
- }
- if (val == 0)
- diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
- index fcc0315..2e3adff 100755
- --- a/src/server/game/Globals/ObjectMgr.h
- +++ b/src/server/game/Globals/ObjectMgr.h
- @@ -1145,6 +1145,8 @@ class ObjectMgr
- void LoadFactionChangeSpells();
- void LoadFactionChangeReputations();
- + ItemFakeStatContainer _itemFakeStatStore; // custom
- +
- private:
- // first free id for selected id type
- uint32 _auctionId;
- diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
- index ed5b563..f4a7ef4 100755
- --- a/src/server/game/Scripting/ScriptLoader.cpp
- +++ b/src/server/game/Scripting/ScriptLoader.cpp
- @@ -1249,6 +1249,7 @@ void AddBattlegroundScripts()
- #ifdef SCRIPTS
- /* This is where custom scripts' loading functions should be declared. */
- +void AddSC_REFORGER_NPC();
- #endif
- void AddCustomScripts()
- @@ -1256,5 +1257,6 @@ void AddCustomScripts()
- #ifdef SCRIPTS
- /* This is where custom scripts should be added. */
- + AddSC_REFORGER_NPC();
- #endif
- }
- diff --git a/src/server/scripts/Custom/CMakeLists.txt b/src/server/scripts/Custom/CMakeLists.txt
- index 62abde2..f3302dc 100644
- --- a/src/server/scripts/Custom/CMakeLists.txt
- +++ b/src/server/scripts/Custom/CMakeLists.txt
- @@ -10,6 +10,7 @@
- set(scripts_STAT_SRCS
- ${scripts_STAT_SRCS}
- + Custom/Reforging.cpp
- )
- message(" -> Prepared: Custom")
- diff --git a/src/server/scripts/Custom/Reforging.cpp b/src/server/scripts/Custom/Reforging.cpp
- new file mode 100644
- index 0000000..fcd4a39
- --- /dev/null
- +++ b/src/server/scripts/Custom/Reforging.cpp
- @@ -0,0 +1,526 @@
- +#include "ScriptPCH.h"
- +struct accepted_stat_format {uint32 stat_type; char* stat_name; int32 base_stat_change; };
- +
- +// ########################################################################################
- +// Reforging config
- +// ########################################################################################
- +static const uint32 tokenEntry = 49426; // token entry
- +static const uint8 maxTokenAmount = 3; // max token cost (multiplies the max stat amount also)
- +static const uint8 maxReforges = 3; // maximum reforges for one item
- +static const bool send_cache_packets = true; // change player cache?
- +
- +static const accepted_stat_format accepted_stat_types[] =
- +{
- + // See ItemPrototype.h for ItemModType definitions. You can add more rows for more stats.
- + {ITEM_MOD_HEALTH, "Health", 5000},
- + {ITEM_MOD_STRENGTH, "Strength", 250},
- + {ITEM_MOD_INTELLECT, "Intellect", 250},
- + {ITEM_MOD_AGILITY, "Agility", 100},
- + {ITEM_MOD_SPIRIT, "Spirit", 250},
- + {ITEM_MOD_STAMINA, "Stamina", 500},
- + {ITEM_MOD_ATTACK_POWER, "Attack power", 500},
- + {ITEM_MOD_SPELL_POWER, "Spell power", 500},
- +};
- +
- +// ########################################################################################
- +
- +static const uint32 accepted_stat_types_max = sizeof(accepted_stat_types) / sizeof(accepted_stat_format);
- +struct playerItems_format {uint32 Entry, lowGUID;};
- +static UNORDERED_MAP<uint32, std::vector<playerItems_format> > playerItems;
- +
- +static const void SendReforgePackets(Player* player)
- +{
- + if(!send_cache_packets)
- + return;
- +
- + uint32 pGUID = player->GetGUIDLow();
- + if(playerItems.find(pGUID) == playerItems.end())
- + return;
- +
- + for (std::vector<playerItems_format>::iterator it = playerItems[pGUID].begin(); it != playerItems[pGUID].end(); it++)
- + {
- + // See how enchanthing is done
- + // Update player cache (self only) pure visual.
- + // HandleItemQuerySingleOpcode copy paste:
- + const ItemTemplate* proto = sObjectMgr->GetItemTemplate(it->Entry);
- + std::string Name = proto->Name1;
- + std::string Description = proto->Description;
- + int loc_idx = player->GetSession()->GetSessionDbLocaleIndex();
- + if (loc_idx >= 0)
- + {
- + if (ItemLocale const* il = sObjectMgr->GetItemLocale(proto->ItemId))
- + {
- + ObjectMgr::GetLocaleString(il->Name, loc_idx, Name);
- + ObjectMgr::GetLocaleString(il->Description, loc_idx, Description);
- + }
- + }
- + WorldPacket data(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 600);
- + data << proto->ItemId;
- + data << proto->Class;
- + data << proto->SubClass;
- + data << int32(proto->Unk0);
- + data << Name;
- + data << uint8(0x00);
- + data << uint8(0x00);
- + data << uint8(0x00);
- + data << proto->DisplayInfoID;
- + data << proto->Quality;
- + data << proto->Flags;
- + data << proto->Flags2;
- + data << proto->BuyPrice;
- + data << proto->SellPrice;
- + data << proto->InventoryType;
- + data << proto->AllowableClass;
- + data << proto->AllowableRace;
- + data << proto->ItemLevel;
- + data << proto->RequiredLevel;
- + data << proto->RequiredSkill;
- + data << proto->RequiredSkillRank;
- + data << proto->RequiredSpell;
- + data << proto->RequiredHonorRank;
- + data << proto->RequiredCityRank;
- + data << proto->RequiredReputationFaction;
- + data << proto->RequiredReputationRank;
- + data << int32(proto->MaxCount);
- + data << int32(proto->Stackable);
- + data << proto->ContainerSlots;
- + data << proto->StatsCount;
- + for (uint32 i = 0; i < proto->StatsCount; ++i)
- + {
- + data << proto->ItemStat[i].ItemStatType;
- + if(sObjectMgr->_itemFakeStatStore[it->lowGUID].find(i) != sObjectMgr->_itemFakeStatStore[it->lowGUID].end())
- + data << proto->ItemStat[i].ItemStatValue + sObjectMgr->_itemFakeStatStore[it->lowGUID][i];
- + else
- + data << proto->ItemStat[i].ItemStatValue;
- + }
- + data << proto->ScalingStatDistribution;
- + data << proto->ScalingStatValue;
- + for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
- + {
- + data << proto->Damage[i].DamageMin;
- + data << proto->Damage[i].DamageMax;
- + data << proto->Damage[i].DamageType;
- + }
- + data << proto->Armor;
- + data << proto->HolyRes;
- + data << proto->FireRes;
- + data << proto->NatureRes;
- + data << proto->FrostRes;
- + data << proto->ShadowRes;
- + data << proto->ArcaneRes;
- + data << proto->Delay;
- + data << proto->AmmoType;
- + data << proto->RangedModRange;
- + for (int s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s)
- + {
- + SpellInfo const* spell = sSpellMgr->GetSpellInfo(proto->Spells[s].SpellId);
- + if (spell)
- + {
- + bool db_data = proto->Spells[s].SpellCooldown >= 0 || proto->Spells[s].SpellCategoryCooldown >= 0;
- + data << proto->Spells[s].SpellId;
- + data << proto->Spells[s].SpellTrigger;
- + data << uint32(-abs(proto->Spells[s].SpellCharges));
- + if (db_data)
- + {
- + data << uint32(proto->Spells[s].SpellCooldown);
- + data << uint32(proto->Spells[s].SpellCategory);
- + data << uint32(proto->Spells[s].SpellCategoryCooldown);
- + }
- + else
- + {
- + data << uint32(spell->RecoveryTime);
- + data << uint32(spell->Category);
- + data << uint32(spell->CategoryRecoveryTime);
- + }
- + }
- + else
- + {
- + data << uint32(0);
- + data << uint32(0);
- + data << uint32(0);
- + data << uint32(-1);
- + data << uint32(0);
- + data << uint32(-1);
- + }
- + }
- + data << proto->Bonding;
- + data << Description;
- + data << proto->PageText;
- + data << proto->LanguageID;
- + data << proto->PageMaterial;
- + data << proto->StartQuest;
- + data << proto->LockID;
- + data << int32(proto->Material);
- + data << proto->Sheath;
- + data << proto->RandomProperty;
- + data << proto->RandomSuffix;
- + data << proto->Block;
- + data << proto->ItemSet;
- + data << proto->MaxDurability;
- + data << proto->Area;
- + data << proto->Map;
- + data << proto->BagFamily;
- + data << proto->TotemCategory;
- + for (int s = 0; s < MAX_ITEM_PROTO_SOCKETS; ++s)
- + {
- + data << proto->Socket[s].Color;
- + data << proto->Socket[s].Content;
- + }
- + data << proto->socketBonus;
- + data << proto->GemProperties;
- + data << proto->RequiredDisenchantSkill;
- + data << proto->ArmorDamageModifier;
- + data << proto->Duration;
- + data << proto->ItemLimitCategory;
- + data << proto->HolidayId;
- + player->GetSession()->SendPacket(&data);
- + }
- +}
- +
- +class REFORGING_DATA_HANDLER : public PlayerScript
- +{
- +public:
- + REFORGING_DATA_HANDLER() : PlayerScript("REFORGING_DATA_HANDLER")
- + {
- + // DB cleanup on startup
- + CharacterDatabase.Execute("DELETE FROM custom_reforges WHERE NOT EXISTS (SELECT 1 FROM item_instance WHERE item_instance.guid = custom_reforges.iGUID)");
- + }
- +
- + // Called when a player logs out.
- + void OnLogout(Player* player)
- + {
- + DeleteSavedReforges(player->GetGUIDLow()); // delete stored reforges from the player (not DB)
- + }
- +
- + void OnLogin(Player* player)
- + {
- + uint32 pGUID = player->GetGUIDLow();
- +
- + DeleteSavedReforges(pGUID); // delete saved reforges from the player before loading them
- + QueryResult result = CharacterDatabase.PQuery("SELECT `iGUID`, `stat_count_id`, `stat_diff`, `Entry` FROM `custom_reforges` WHERE pGUID = %u and EXISTS (SELECT 1 FROM item_instance WHERE item_instance.guid = custom_reforges.iGUID)", pGUID);
- + if (result)
- + {
- + UNORDERED_MAP<uint32, std::map<uint32, int32> > stat_temp_container; // iGUID <stat_count, stat_diff>
- + std::set<uint32> sent_error_message;
- + do
- + {
- + uint32 lowGUID = (*result)[0].GetUInt32();
- + if(sObjectMgr->_itemFakeStatStore.find(lowGUID) != sObjectMgr->_itemFakeStatStore.end() && sObjectMgr->_itemFakeStatStore[lowGUID].size() >= maxReforges)
- + {
- + if(sent_error_message.find(lowGUID) != sent_error_message.end())
- + continue;
- + sLog->outErrorDb("Too many reforges for item lowGUID %u, ignoring extra reforges.", lowGUID);
- + sent_error_message.insert(lowGUID);
- + }
- + else
- + {
- + stat_temp_container[lowGUID][(*result)[1].GetUInt32()] = (*result)[2].GetInt32();
- + playerItems_format temp = {(*result)[3].GetUInt32(), lowGUID}; // temp var so we can insert our stuff
- + playerItems[pGUID].push_back(temp);
- + }
- + } while (result->NextRow());
- +
- + // apply stat changes for all reforged items equipped and save them to container
- + for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; slot++)
- + {
- + if(Item* invItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
- + {
- + uint32 invGUID = invItem->GetGUIDLow();
- + if(stat_temp_container.find(invGUID) != stat_temp_container.end())
- + {
- + player->_ApplyItemMods(invItem, slot, false);
- + for(std::map<uint32, int32>::iterator stat_count_id = stat_temp_container[invGUID].begin(); stat_count_id != stat_temp_container[invGUID].end(); stat_count_id++)
- + {
- + sObjectMgr->_itemFakeStatStore[invGUID][stat_count_id->first] = stat_count_id->second;
- + }
- + player->_ApplyItemMods(invItem, slot, true);
- + stat_temp_container.erase(invGUID); // saved reforges for this item, delete from temp
- + }
- + }
- + }
- +
- + // save the rest of the player's reforges to the container if more exist
- + if(!stat_temp_container.empty())
- + {
- + for(UNORDERED_MAP<uint32, std::map<uint32, int32> >::iterator iGUID = stat_temp_container.begin(); iGUID != stat_temp_container.end(); iGUID++)
- + {
- + for(std::map<uint32, int32>::iterator stat_count_id = iGUID->second.begin(); stat_count_id != iGUID->second.end(); stat_count_id++)
- + {
- + sObjectMgr->_itemFakeStatStore[iGUID->first][stat_count_id->first] = stat_count_id->second;
- + }
- + }
- + }
- + }
- +
- + SendReforgePackets(player);
- + }
- +
- +private:
- +
- + void DeleteSavedReforges(uint32 pGUID)
- + {
- + if(playerItems.find(pGUID) == playerItems.end())
- + return; // Already empty!
- + for (std::vector<playerItems_format>::iterator it = playerItems[pGUID].begin(); it != playerItems[pGUID].end(); it++)
- + {
- + if(sObjectMgr->_itemFakeStatStore.find(it->lowGUID) != sObjectMgr->_itemFakeStatStore.end())
- + sObjectMgr->_itemFakeStatStore.erase(it->lowGUID);
- + }
- + playerItems.erase(pGUID);
- + }
- +};
- +
- +class REFORGER_NPC : public CreatureScript
- +{
- +public:
- + REFORGER_NPC() : CreatureScript("REFORGER_NPC")
- + {
- + for(uint32 i = 0; i < accepted_stat_types_max; i++)
- + {
- + stat_format temp = {accepted_stat_types[i].stat_name, accepted_stat_types[i].base_stat_change};
- + stat_types[accepted_stat_types[i].stat_type] = temp;
- + }
- + }
- +
- + bool OnGossipHello(Player* player, Creature* creature)
- + {
- + if(selectedItem.find(player->GetGUIDLow()) != selectedItem.end())
- + selectedItem.erase(player->GetGUIDLow());
- +
- + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Select equipped item in slot:", MAIN_MENU, 0);
- + for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; slot++)
- + {
- + if(Item* invItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
- + if(IsReforgable(invItem, player))
- + if(char* slotname = GetSlotName(slot, player->GetSession()))
- + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, slotname, SELECT_STAT_INCREASE, slot);
- + }
- + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Update menu", MAIN_MENU, 0);
- + player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
- + return true;
- + }
- +
- + bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action)
- + {
- + player->PlayerTalkClass->ClearMenus();
- + switch(sender)
- + {
- + case MAIN_MENU: OnGossipHello(player, creature); break;
- + case SELECT_STAT_INCREASE:
- + // action = slot
- + if (Item* invItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, action))
- + {
- + if(IsReforgable(invItem, player))
- + {
- + selectedItem[player->GetGUIDLow()] = invItem;
- + const ItemTemplate* proto = invItem->GetTemplate();
- + char label[250];
- +
- + snprintf(label, 250, "Selected item:\n%s", invItem->GetTemplate()->Name1.c_str());
- + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, label, sender, action);
- + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Select stat to increase:", sender, action);
- + bool hasfakestats = ((sObjectMgr->_itemFakeStatStore.find(invItem->GetGUIDLow()) != sObjectMgr->_itemFakeStatStore.end()) ? true : false);
- + for (uint32 i = 0; i < proto->StatsCount; ++i)
- + {
- + if(hasfakestats && sObjectMgr->_itemFakeStatStore[invItem->GetGUIDLow()].find(i) != sObjectMgr->_itemFakeStatStore[invItem->GetGUIDLow()].end())
- + continue; // already modded this stat, skip.
- + if(char* stat_name = GetStatName(proto->ItemStat[i].ItemStatType))
- + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, stat_name, SELECT_TOKEN_COST, i);
- + }
- + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TALK, "Back..", MAIN_MENU, 0);
- + player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
- + }
- + else
- + {
- + player->GetSession()->SendNotification("Item not reforgable");
- + OnGossipHello(player, creature);
- + }
- + }
- + else
- + {
- + player->GetSession()->SendNotification("No item selected");
- + OnGossipHello(player, creature);
- + }
- + break;
- + case SELECT_TOKEN_COST:
- + // action = stat_count_id
- + {
- + Item* invItem = selectedItem[player->GetGUIDLow()];
- + if (invItem && invItem->IsInWorld() && IsReforgable(invItem, player))
- + {
- + const ItemTemplate* proto = invItem->GetTemplate();
- + char label[250];
- + char popup[250];
- +
- + snprintf(label, 250, "Selected item:\n%s", invItem->GetTemplate()->Name1.c_str());
- + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, label, sender, action);
- + snprintf(label, 250, "Selected stat: %s", stat_types[proto->ItemStat[action].ItemStatType].stat_name);
- + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, label, sender, action);
- + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Select amount to increase:", sender, action);
- + for (uint32 i = 1; i <= maxTokenAmount; ++i)
- + {
- + snprintf(label, 250, "Increase by %i for %u x %s", stat_types[proto->ItemStat[action].ItemStatType].stat_base_value*i, i, GetItemName(tokenEntry, player->GetSession()).c_str());
- + snprintf(popup, 250, "Are you sure?\nThe item is set untradeable and non-refundable\n\nCosts %u x %s", i, GetItemName(tokenEntry, player->GetSession()).c_str());
- + player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_TRAINER, label, i, action, popup, 0, false); // sender = token_count, action = stat_count_id
- + }
- + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TALK, "Back..", SELECT_STAT_INCREASE, invItem->GetSlot());
- + player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
- + }
- + else
- + {
- + player->GetSession()->SendNotification("Invalid item selected");
- + OnGossipHello(player, creature);
- + }
- + }
- + break;
- + default: // Reforge
- + // sender = token_count, action = stat_count_id
- + {
- + Item* invItem = selectedItem[player->GetGUIDLow()];
- + if (invItem && invItem->IsInWorld() && IsReforgable(invItem, player))
- + {
- + if(sender && sender <= maxTokenAmount)
- + {
- + if(player->HasItemCount(tokenEntry, sender))
- + {
- + player->DestroyItemCount(tokenEntry, sender, true);
- + UpdatePlayerReforgeStats(invItem, player, action, sender);
- + }
- + else
- + {
- + player->GetSession()->SendNotification("Not enough tokens");
- + OnGossipSelect(player, creature, SELECT_TOKEN_COST, action);
- + return true;
- + }
- + }
- + else
- + player->GetSession()->SendNotification("Invalid token count");
- + }
- + else
- + player->GetSession()->SendNotification("Invalid item selected");
- + OnGossipHello(player, creature);
- + }
- + }
- + return true;
- + }
- +
- +private:
- +
- + enum Senders
- + {
- + MAIN_MENU = GOSSIP_ACTION_INFO_DEF+1,
- + SELECT_ITEM,
- + SELECT_STAT_INCREASE,
- + SELECT_TOKEN_COST,
- + REFORGE,
- + };
- +
- + struct stat_format {char* stat_name; int32 stat_base_value; };
- + UNORDERED_MAP<uint32, struct stat_format> stat_types;
- + UNORDERED_MAP<uint32, Item*> selectedItem;
- +
- + char* GetStatName(uint32 stat_type)
- + {
- + if(stat_types.find(stat_type) != stat_types.end())
- + return stat_types[stat_type].stat_name;
- + return NULL;
- + }
- +
- + char * GetSlotName(uint8 slot, WorldSession* session)
- + {
- + switch (slot)
- + {
- + case EQUIPMENT_SLOT_HEAD : return "Head";
- + case EQUIPMENT_SLOT_NECK : return "Neck";
- + case EQUIPMENT_SLOT_SHOULDERS : return "Shoulders";
- + case EQUIPMENT_SLOT_BODY : return "Shirt";
- + case EQUIPMENT_SLOT_CHEST : return "Chest";
- + case EQUIPMENT_SLOT_WAIST : return "Waist";
- + case EQUIPMENT_SLOT_LEGS : return "Legs";
- + case EQUIPMENT_SLOT_FEET : return "Feet";
- + case EQUIPMENT_SLOT_WRISTS : return "Wrists";
- + case EQUIPMENT_SLOT_HANDS : return "Hands";
- + case EQUIPMENT_SLOT_FINGER1 : return "Right finger";
- + case EQUIPMENT_SLOT_FINGER2 : return "left finger";
- + case EQUIPMENT_SLOT_TRINKET1 : return "Right trinket";
- + case EQUIPMENT_SLOT_TRINKET2 : return "Left trinket";
- + case EQUIPMENT_SLOT_BACK : return "Back";
- + case EQUIPMENT_SLOT_MAINHAND : return "Main hand";
- + case EQUIPMENT_SLOT_OFFHAND : return "Off hand";
- + case EQUIPMENT_SLOT_RANGED : return "Ranged";
- + case EQUIPMENT_SLOT_TABARD : return "Tabard";
- + default: return NULL;
- + }
- + }
- +
- + std::string GetItemName(uint32 entry, WorldSession* session)
- + {
- + const ItemTemplate* itemTemplate = sObjectMgr->GetItemTemplate(entry);
- + std::string name = itemTemplate->Name1;
- + int loc_idx = session->GetSessionDbLocaleIndex();
- + if (loc_idx >= 0)
- + if (ItemLocale const* il = sObjectMgr->GetItemLocale(itemTemplate->ItemId))
- + sObjectMgr->GetLocaleString(il->Name, loc_idx, name);
- + return name;
- + }
- +
- + bool IsReforgable(Item* invItem, Player* player)
- + {
- + if(invItem->IsEquipped() && invItem->GetOwnerGUID() == player->GetGUID())
- + {
- + if(sObjectMgr->_itemFakeStatStore.find(invItem->GetGUIDLow()) != sObjectMgr->_itemFakeStatStore.end())
- + if(sObjectMgr->_itemFakeStatStore[invItem->GetGUIDLow()].size() >= maxReforges)
- + return false;
- + const ItemTemplate* proto = invItem->GetTemplate();
- + // block heirlooms necessary? probably. (their stats are handled differently)
- + if(proto->Quality != ITEM_QUALITY_HEIRLOOM && proto->StatsCount > 0)
- + {
- + for (uint32 i = 0; i < proto->StatsCount; ++i)
- + {
- + if(stat_types.find(proto->ItemStat[i].ItemStatType) == stat_types.end())
- + continue;
- + if(proto->ItemStat[i].ItemStatValue == 0)
- + continue;
- + if(sObjectMgr->_itemFakeStatStore.find(invItem->GetGUIDLow()) != sObjectMgr->_itemFakeStatStore.end())
- + {
- + if(sObjectMgr->_itemFakeStatStore[invItem->GetGUIDLow()].find(i) == sObjectMgr->_itemFakeStatStore[invItem->GetGUIDLow()].end())
- + return true; // found a stat that is not increased yet and is accepted by the script
- + }
- + else
- + return true; // the item is not reforged yet and a good stat was found
- + }
- + }
- + }
- + return false;
- + }
- +
- + void UpdatePlayerReforgeStats(Item* invItem, Player* player, uint32 stat_count_id, uint32 token_count)
- + {
- + const ItemTemplate* proto = invItem->GetTemplate();
- + uint32 stat_diff = stat_types[proto->ItemStat[stat_count_id].ItemStatType].stat_base_value * token_count;
- + uint32 guidlow = invItem->GetGUIDLow();
- +
- + // non tradeable and refundable
- + invItem->SetNotRefundable(player);
- + invItem->SetBinding(true);
- +
- + // Update player stats
- + player->_ApplyItemMods(invItem, invItem->GetSlot(), false);
- + sObjectMgr->_itemFakeStatStore[guidlow][stat_count_id] = stat_diff; // save to container for item stats applying (used a lot)
- + playerItems_format temp = {invItem->GetEntry(), guidlow}; // temp var so we can insert our stuff to playerItems_format
- + playerItems[player->GetGUIDLow()].push_back(temp); // save entry and guid of the item so we can delete the item data on logout
- + player->_ApplyItemMods(invItem, invItem->GetSlot(), true);
- +
- + // save to DB
- + player->SaveToDB(); // save player to DB too, since if a crash comes by, he will get a free reforge and no token removing is saved.
- + CharacterDatabase.PExecute("REPLACE INTO `custom_reforges` (`pGUID`, `Entry`, `iGUID`, `stat_count_id`, `stat_diff`) VALUES (%u, %u, %u, %u, %i)", player->GetGUIDLow(), invItem->GetEntry(), guidlow, stat_count_id, stat_diff);
- +
- + SendReforgePackets(player);
- + }
- +};
- +
- +void AddSC_REFORGER_NPC()
- +{
- + new REFORGER_NPC;
- + new REFORGING_DATA_HANDLER;
- +}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement