Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- 3.3
- Transmogrification 3.3.5a - Gossip Menu
- By Rochet2
- Now with DB implemented
- ScriptName for NPC:
- NPC_Transmogrify
- TODO:
- Make DB saving even better (Deleting)? What about coding?
- Fix the cost formula
- TODO in the distant future:
- Are the qualities right? Blizzard might have changed the quality requirements.
- What can and cant be used as source or target..?
- Cant transmogrify:
- rediculus items // Foereaper: would be fun to stab people with a fish
- -- Cant think of any good way to handle this easily
- Cataclysm:
- Test on cata -> implement UI xD?
- Item link icon to Are You sure text
- */
- #define CHECK_QUALITY 0 // 0 for no quality checking, 1 for normal quality checks.
- #define GOLD_COST 0 // 0 for no gold cost, otherwise used as a multiplier. 1 means normal cost. (float values: 0.5f)
- #include "ScriptPCH.h"
- #if(GOLD_COST)
- #define GOLDFUNCTION GetSellPrice(OLD)
- #else
- #define GOLDFUNCTION 0
- #endif
- struct Localization_data
- {
- StringVector Text;
- };
- typedef UNORDERED_MAP<uint32, Localization_data> CustomTextLocale;
- CustomTextLocale _CustomTextLocaleStore;
- #define POPUPs "Using this item for transmogrify will bind it to you and make it non-refundable and non-tradeable.\nDo you wish to continue?\n\n"+ pItem->GetTemplate()->Name1
- enum TextIDs
- {
- POPUP_TRANSMOGRIFY,
- REMOVE_ALL_OPTION,
- REMOVE_ALL_POPUP,
- REMOVE_ONE_OPTION,
- REMOVE_ONE_POPUP,
- REFRESH_OPTION,
- BACK_OPTION,
- MSG_REMOVE_ALL,
- ERR_REMOVE_ALL,
- MSG_REMOVE_ONE,
- ERR_REMOVE_ONE,
- MSG_TRANSMOGRIFIED,
- ERR_NOT_SUITABLE,
- ERR_NOT_EXISTS,
- ERR_SLOT_EMPTY,
- ID_SLOT_HEAD ,
- ID_SLOT_SHOULDERS ,
- ID_SLOT_BODY ,
- ID_SLOT_CHEST ,
- ID_SLOT_WAIST ,
- ID_SLOT_LEGS ,
- ID_SLOT_FEET ,
- ID_SLOT_WRISTS ,
- ID_SLOT_HANDS ,
- ID_SLOT_BACK ,
- ID_SLOT_MAINHAND ,
- ID_SLOT_OFFHAND ,
- ID_SLOT_RANGED ,
- ID_SLOT_TABARD ,
- TEXTIDS_MAX
- };
- class NPC_Transmogrify : public CreatureScript
- {
- public:
- NPC_Transmogrify() : CreatureScript("NPC_Transmogrify") { }
- bool OnGossipHello(Player* pPlayer, Creature* pUnit)
- {
- printf("%s\n", GetText(1, pPlayer)); // Testline
- for (uint8 Slot = EQUIPMENT_SLOT_START; Slot < EQUIPMENT_SLOT_TABARD; Slot++) // EQUIPMENT_SLOT_END
- {
- if (Item* pItem = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, Slot))
- #if(CHECK_QUALITY)
- if(HasGoodQuality(pItem))
- #endif
- if(const char* SlotName = GetSlotName(Slot, pPlayer))
- pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, SlotName, EQUIPMENT_SLOT_END, Slot);
- }
- pPlayer->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, "Remove all transmogrifications", EQUIPMENT_SLOT_END+2, 0, "Remove transmogrifications from all equipped items?", 0, false);
- pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TALK, "Update Menu", EQUIPMENT_SLOT_END+1, 0);
- pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pUnit->GetGUID());
- return true;
- }
- bool OnGossipSelect(Player* pPlayer, Creature* pUnit, uint32 sender, uint32 uiAction)
- {
- pPlayer->PlayerTalkClass->ClearMenus();
- switch(sender)
- {
- case EQUIPMENT_SLOT_END: // Show items you can use
- {
- if (Item* OLD = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, uiAction))
- {
- uint32 GUID = pPlayer->GetGUIDLow();
- Items[GUID].clear();
- uint32 limit = 0;
- for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
- {
- if(limit > 30)
- break;
- if (Item* pItem = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- {
- uint32 Display = pItem->GetTemplate()->DisplayInfoID;
- if(IsSuitable(pItem, OLD, pPlayer))
- if(Items[GUID].find(Display) == Items[GUID].end())
- {
- limit++;
- Items[GUID][Display] = pItem;
- pPlayer->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, pItem->GetTemplate()->Name1, uiAction, Display, POPUPs, GOLDFUNCTION, false);
- }
- }
- }
- for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
- {
- if (Bag* pBag = pPlayer->GetBagByPos(i))
- for (uint32 j = 0; j < pBag->GetBagSize(); j++)
- {
- if(limit > 30)
- break;
- if (Item* pItem = pPlayer->GetItemByPos(i, j))
- {
- uint32 Display = pItem->GetTemplate()->DisplayInfoID;
- if(IsSuitable(pItem, OLD, pPlayer))
- if(Items[GUID].find(Display) == Items[GUID].end())
- {
- limit++;
- Items[GUID][Display] = pItem;
- pPlayer->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, pItem->GetTemplate()->Name1, uiAction, Display, POPUPs, GOLDFUNCTION, false);
- }
- }
- }
- }
- pPlayer->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, GetText(REMOVE_ONE_OPTION, pPlayer), EQUIPMENT_SLOT_END+3, uiAction, (std::string)GetText(REMOVE_ONE_POPUP, pPlayer)+" "+(std::string)GetSlotName(uiAction, pPlayer)+"?", 0, false);
- pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TALK, GetText(BACK_OPTION, pPlayer), EQUIPMENT_SLOT_END+1, 0);
- pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pUnit->GetGUID());
- }
- else
- OnGossipHello(pPlayer, pUnit);
- } break;
- case EQUIPMENT_SLOT_END+1: // Back
- {
- OnGossipHello(pPlayer, pUnit);
- } break;
- case EQUIPMENT_SLOT_END+2: // Remove Transmogrifications
- {
- bool removed = false;
- for (uint8 Slot = EQUIPMENT_SLOT_START; Slot < EQUIPMENT_SLOT_END; Slot++)
- if (Item* pItem = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, Slot))
- {
- if(RemoveDisplay(pItem) && !removed)
- removed = true;
- pPlayer->SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (Slot * 2), pItem->GetEntry());
- }
- if(removed)
- {
- pPlayer->GetSession()->SendAreaTriggerMessage("Transmogrifications removed from equipped items");
- pPlayer->PlayDirectSound(3337);
- }
- else
- pPlayer->GetSession()->SendNotification("You have no transmogrified items equipped");
- OnGossipHello(pPlayer, pUnit);
- } break;
- case EQUIPMENT_SLOT_END+3: // Remove Transmogrification from single item
- {
- if (Item* pItem = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, uiAction))
- {
- if(RemoveDisplay(pItem))
- {
- pPlayer->GetSession()->SendAreaTriggerMessage("%s transmogrification removed", GetSlotName(uiAction, pPlayer));
- pPlayer->PlayDirectSound(3337);
- }
- else
- pPlayer->GetSession()->SendNotification("No transmogrification on %s slot", GetSlotName(uiAction, pPlayer));
- pPlayer->SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (uiAction * 2), pItem->GetEntry());
- }
- OnGossipSelect(pPlayer, pUnit, EQUIPMENT_SLOT_END, uiAction);
- } break;
- default: // Transmogrify
- {
- uint32 GUID = pPlayer->GetGUIDLow();
- if(Item* OLD = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, sender))
- {
- if(Items[GUID].find(uiAction) != Items[GUID].end() && Items[GUID][uiAction]->IsInWorld())
- {
- Item* pItem = Items[GUID][uiAction];
- if(pItem->GetOwnerGUID() == pPlayer->GetGUID() && (pItem->IsInBag() || pItem->GetBagSlot() == INVENTORY_SLOT_BAG_0) && IsSuitable(pItem, OLD, pPlayer))
- {
- #if(GOLD_COST)
- pPlayer->ModifyMoney(-1*GetSellPrice(OLD)); // take cost
- #endif
- pItem->SetNotRefundable(pPlayer);
- pItem->SetBinding(true); // soulbound
- uint32 FakeEntry = pItem->GetEntry();
- CharacterDatabase.PExecute("REPLACE INTO custom_transmogrification (GUID, FakeEntry) VALUES (%u, %u)", OLD->GetGUIDLow(), FakeEntry);
- OLD->FakeEntry = FakeEntry;
- // pPlayer->SetVisibleItemSlot(sender, OLD); // No need to use this, useless checking
- pPlayer->UpdateUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (sender * 2), FakeEntry); // use this instead
- pPlayer->PlayDirectSound(3337);
- pPlayer->GetSession()->SendAreaTriggerMessage("%s transmogrified", GetSlotName(sender, pPlayer));
- }
- else
- pPlayer->GetSession()->SendNotification("Selected items are not suitable");
- }
- else
- pPlayer->GetSession()->SendNotification("Selected item does not exist");
- }
- else
- pPlayer->GetSession()->SendNotification("Equipment slot is empty");
- Items[GUID].clear();
- OnGossipSelect(pPlayer, pUnit, EQUIPMENT_SLOT_END, sender);
- } break;
- }
- return true;
- }
- private:
- std::map<uint64, std::map<uint32, Item*> > Items; // Items[GUID][DISPLAY] = item
- char * GetSlotName(uint8 slot, Player* pPlayer)
- {
- switch(slot)
- {
- case EQUIPMENT_SLOT_HEAD : return GetText(ID_SLOT_HEAD , pPlayer);
- case EQUIPMENT_SLOT_SHOULDERS : return GetText(ID_SLOT_SHOULDERS , pPlayer);
- case EQUIPMENT_SLOT_BODY : return GetText(ID_SLOT_BODY , pPlayer);
- case EQUIPMENT_SLOT_CHEST : return GetText(ID_SLOT_CHEST , pPlayer);
- case EQUIPMENT_SLOT_WAIST : return GetText(ID_SLOT_WAIST , pPlayer);
- case EQUIPMENT_SLOT_LEGS : return GetText(ID_SLOT_LEGS , pPlayer);
- case EQUIPMENT_SLOT_FEET : return GetText(ID_SLOT_FEET , pPlayer);
- case EQUIPMENT_SLOT_WRISTS : return GetText(ID_SLOT_WRISTS , pPlayer);
- case EQUIPMENT_SLOT_HANDS : return GetText(ID_SLOT_HANDS , pPlayer);
- case EQUIPMENT_SLOT_BACK : return GetText(ID_SLOT_BACK , pPlayer);
- case EQUIPMENT_SLOT_MAINHAND : return GetText(ID_SLOT_MAINHAND , pPlayer);
- case EQUIPMENT_SLOT_OFFHAND : return GetText(ID_SLOT_OFFHAND , pPlayer);
- case EQUIPMENT_SLOT_RANGED : return GetText(ID_SLOT_RANGED , pPlayer);
- case EQUIPMENT_SLOT_TABARD : return GetText(ID_SLOT_TABARD , pPlayer);
- default: return NULL;
- }
- }
- bool IsSuitable(Item* pItem, Item* OLD, Player* pPlayer)
- {
- if(OLD->GetTemplate()->DisplayInfoID != pItem->GetTemplate()->DisplayInfoID)
- {
- if(const ItemTemplate* FakeItemTemplate = sObjectMgr->GetItemTemplate(OLD->FakeEntry))
- if(FakeItemTemplate->DisplayInfoID == pItem->GetTemplate()->DisplayInfoID)
- return false;
- if(pPlayer->CanUseItem(pItem, false) == EQUIP_ERR_OK)
- #if(CHECK_QUALITY)
- if(HasGoodQuality(pItem))
- #endif
- {
- uint32 NClass = pItem->GetTemplate()->Class;
- uint32 OClass = OLD->GetTemplate()->Class;
- uint32 NSubClass = pItem->GetTemplate()->SubClass;
- uint32 OSubClass = OLD->GetTemplate()->SubClass;
- uint32 NEWinv = pItem->GetTemplate()->InventoryType;
- uint32 OLDinv = OLD->GetTemplate()->InventoryType;
- if(NClass == OClass) // not possibly the best structure here, but atleast I got my head around this
- if(NClass == ITEM_CLASS_WEAPON && NSubClass != ITEM_SUBCLASS_WEAPON_FISHING_POLE && OSubClass != ITEM_SUBCLASS_WEAPON_FISHING_POLE)
- {
- if(NSubClass == OSubClass || ((NSubClass == ITEM_SUBCLASS_WEAPON_BOW || NSubClass == ITEM_SUBCLASS_WEAPON_GUN || NSubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW) && (OSubClass == ITEM_SUBCLASS_WEAPON_BOW || OSubClass == ITEM_SUBCLASS_WEAPON_GUN || OSubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW)))
- if(NEWinv == OLDinv || (NEWinv == INVTYPE_WEAPON && (OLDinv == INVTYPE_WEAPONMAINHAND || OLDinv == INVTYPE_WEAPONOFFHAND)))
- return true;
- }
- else if(NClass == ITEM_CLASS_ARMOR)
- if(NSubClass == OSubClass)
- if(NEWinv == OLDinv || (NEWinv == INVTYPE_CHEST && OLDinv == INVTYPE_ROBE) || (NEWinv == INVTYPE_ROBE && OLDinv == INVTYPE_CHEST))
- return true;
- }
- }
- return false;
- }
- #if(CHECK_QUALITY)
- bool HasGoodQuality(Item* pItem)
- {
- uint32 Quality = pItem->GetTemplate()->Quality;
- if(Quality == ITEM_QUALITY_UNCOMMON || Quality == ITEM_QUALITY_RARE || Quality == ITEM_QUALITY_EPIC || Quality == ITEM_QUALITY_HEIRLOOM)
- return true;
- return false;
- }
- #endif
- #if(GOLD_COST)
- uint32 GetSellPrice(Item* pItem) // The formula is not blizzlike
- {
- uint32 Price = pItem->GetTemplate()->SellPrice;
- uint32 MinPrice = pItem->GetTemplate()->RequiredLevel * 1176;
- if(Price < MinPrice)
- Price = MinPrice;
- return Price * GOLD_COST;
- }
- #endif
- bool RemoveDisplay(Item* pItem)
- {
- if(pItem->FakeEntry)
- {
- pItem->FakeEntry = 0;
- CharacterDatabase.PExecute("DELETE FROM custom_transmogrification WHERE GUID = %u", pItem->GetGUIDLow());
- return true;
- }
- return false;
- }
- Localization_data const* GetTextLocales(uint32 entry) const
- {
- printf("Getting the textlocales Entry: %u\n", entry);
- CustomTextLocale::const_iterator itr = _CustomTextLocaleStore.find(entry);
- if (itr == _CustomTextLocaleStore.end()) return NULL;
- printf("ReturningTextLocales, not null\n");
- return &itr->second;
- }
- char* GetText(uint32 TextID, Player* pPlayer)
- {
- printf("GotHere\n");
- std::string Text = "ERR NO DEFAULT TEXT FOUND";
- if (Localization_data const* il = GetTextLocales(TextID))
- {
- ObjectMgr::GetLocaleString(il->Text, 0, Text);
- int loc_idx = 0; // pPlayer->GetSession()->GetSessionDbLocaleIndex();
- if (loc_idx > 0)
- {
- printf("loc_idx: %u\n", loc_idx);
- ObjectMgr::GetLocaleString(il->Text, loc_idx, Text);
- }
- }
- std::vector<char> writable(Text.size() + 1);
- std::copy(Text.begin(), Text.end(), writable.begin());
- printf("Returning\n");
- return &writable[0];
- }
- };
- class WORLD_Transmogrify : public WorldScript
- {
- public:
- WORLD_Transmogrify() : WorldScript("WORLD_Transmogrify") { }
- void OnStartup()
- {
- DeleteUnusedTransmogrifications();
- LoadTransmogrificationTexts();
- LoadTransmogrificationLocales();
- }
- private:
- void DeleteUnusedTransmogrifications()
- {
- sLog->outString("Deleting non-existing transmogrification entries...");
- CharacterDatabase.Execute("DELETE FROM custom_transmogrification WHERE NOT EXISTS (SELECT 1 FROM item_instance WHERE item_instance.guid = custom_transmogrification.GUID)");
- sLog->outString();
- }
- void LoadTransmogrificationTexts()
- {
- uint32 oldMSTime = getMSTime();
- AddOriginalText(POPUP_TRANSMOGRIFY, "");
- AddOriginalText(REMOVE_ALL_OPTION , "Remove all transmogrifications");
- AddOriginalText(REMOVE_ALL_POPUP , "Remove transmogrifications from all equipped items?");
- AddOriginalText(REMOVE_ONE_OPTION , "");
- AddOriginalText(REMOVE_ONE_POPUP , "Remove transmogrification from");
- AddOriginalText(REFRESH_OPTION , "Update menu");
- AddOriginalText(BACK_OPTION , "Back..");
- // These could be in Trinity_string
- AddOriginalText(MSG_REMOVE_ALL , "");
- AddOriginalText(ERR_REMOVE_ALL , "");
- AddOriginalText(MSG_REMOVE_ONE , "");
- AddOriginalText(ERR_REMOVE_ONE , "");
- AddOriginalText(MSG_TRANSMOGRIFIED, "");
- AddOriginalText(ERR_NOT_SUITABLE , "");
- AddOriginalText(ERR_NOT_EXISTS , "");
- AddOriginalText(ERR_SLOT_EMPTY , "");
- AddOriginalText(ID_SLOT_HEAD , "Head");
- AddOriginalText(ID_SLOT_SHOULDERS , "Shoulders");
- AddOriginalText(ID_SLOT_BODY , "Shirt");
- AddOriginalText(ID_SLOT_CHEST , "Chest");
- AddOriginalText(ID_SLOT_WAIST , "Belt");
- AddOriginalText(ID_SLOT_LEGS , "Legs");
- AddOriginalText(ID_SLOT_FEET , "Feet");
- AddOriginalText(ID_SLOT_WRISTS , "Wrists");
- AddOriginalText(ID_SLOT_HANDS , "Hands");
- AddOriginalText(ID_SLOT_BACK , "Back");
- AddOriginalText(ID_SLOT_MAINHAND , "Main hand");
- AddOriginalText(ID_SLOT_OFFHAND , "Off hand");
- AddOriginalText(ID_SLOT_RANGED , "Ranged");
- sLog->outString(">> Loaded %u Transmogrification strings in %u ms", TEXTIDS_MAX, GetMSTimeDiffToNow(oldMSTime));
- }
- void LoadTransmogrificationLocales()
- {
- uint32 oldMSTime = getMSTime();
- _CustomTextLocaleStore.clear(); // need for reload case
- QueryResult result = WorldDatabase.Query("SELECT entry, text_loc1, text_loc2, text_loc3, text_loc4, text_loc5, text_loc6, text_loc7, text_loc8 FROM custom_locales_transmogrification");
- if (!result)
- return;
- do
- {
- Field* fields = result->Fetch();
- uint32 entry = fields[0].GetUInt32();
- Localization_data& data = _CustomTextLocaleStore[entry];
- for (int i = 1; i < TOTAL_LOCALES; ++i)
- ObjectMgr::AddLocaleString(fields[i].GetString(), LocaleConstant(i), data.Text);
- } while (result->NextRow());
- sLog->outString(">> Loaded %lu Transmogrification locale strings in %u ms", (unsigned long)_CustomTextLocaleStore.size(), GetMSTimeDiffToNow(oldMSTime));
- sLog->outString();
- }
- void AddOriginalText(uint32 entry, std::string string)
- {
- Localization_data& data = _CustomTextLocaleStore[entry];
- ObjectMgr::AddLocaleString(string, LocaleConstant(0), data.Text);
- }
- };
- void AddSC_NPC_Transmogrify()
- {
- new WORLD_Transmogrify();
- new NPC_Transmogrify();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement