Advertisement
Rochet2

Transmogrification.cpp

Jun 26th, 2012
509
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. Transmogrification 3.3.5a - Gossip Menu
  3. By Rochet2
  4. Now with DB implemented
  5.  
  6. ScriptName for NPC:
  7. NPC_Transmogrify
  8.  
  9. ScriptLoader.cpp:
  10. void AddSC_NPC_Transmogrify();
  11. AddSC_NPC_Transmogrify();
  12.  
  13. TODO:
  14. Strip fake display on:
  15. mail,
  16. trade,
  17. guild bank,
  18. auction
  19. // not really needed, all items are soulbound, except on cata. What about account bound?
  20.  
  21. Are the qualities right?
  22. What can and cant be used as source or target..?
  23.  
  24. Cant transmogrify:
  25. rediculus items // Foereaper: would be fun to stab people with a fish
  26.  
  27. Item link icon to Are You sure text
  28.  
  29. Make DB saving even better
  30.  
  31. Test on cata -> implement UI xD?
  32. */
  33.  
  34. #include "ScriptPCH.h"
  35.  
  36. class NPC_Transmogrify : public CreatureScript
  37. {
  38. public:
  39.     NPC_Transmogrify() : CreatureScript("NPC_Transmogrify") { }
  40.  
  41.     bool OnGossipHello(Player* pPlayer, Creature* pUnit)
  42.     {
  43.         pPlayer->PlayerTalkClass->ClearMenus();
  44.         for (uint8 Slot = EQUIPMENT_SLOT_START; Slot < EQUIPMENT_SLOT_TABARD; Slot++) // EQUIPMENT_SLOT_END
  45.         {
  46.             if (Item* pItem = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, Slot))
  47.                 if(HasGoodQuality(pItem))
  48.                     if(char* SlotName = GetSlotName(Slot))
  49.                         pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, SlotName, EQUIPMENT_SLOT_END, Slot);
  50.         }
  51.         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);
  52.         pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TALK, "Update Menu", EQUIPMENT_SLOT_END+1, 0);
  53.         pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pUnit->GetGUID());        
  54.         return true;
  55.     }
  56.  
  57.     bool OnGossipSelect(Player* pPlayer, Creature* pUnit, uint32 sender, uint32 uiAction)
  58.     {
  59.         pPlayer->PlayerTalkClass->ClearMenus();
  60.         if(sender == EQUIPMENT_SLOT_END) // Show items you can use
  61.         {
  62.             if (Item* OLD = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, uiAction))
  63.             {
  64.                 uint32 GUID = pPlayer->GetGUIDLow();
  65.                 Items[GUID].clear();
  66.                 uint32 limit = 0;
  67.                 for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
  68.                 {
  69.                     if(limit > 30)
  70.                         break;
  71.                     if (Item* pItem = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, i))
  72.                     {
  73.                         uint32 Display = pItem->GetTemplate()->DisplayInfoID;
  74.                         if(IsSuitable(pItem, OLD, pPlayer))
  75.                         {
  76.                             if(Items[GUID].find(Display) == Items[GUID].end())
  77.                             {
  78.                                 limit++;
  79.                                 Items[GUID][Display] = pItem;
  80.                                 pPlayer->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, pItem->GetTemplate()->Name1, uiAction, Display, "Using this item for transmogrigy will bind it to you and make it non-refundable and non-tradeable.\nDo you wish to continue?\n\n"+ pItem->GetTemplate()->Name1, GetSellPrice(OLD, pPlayer), false);
  81.                             }
  82.                         }
  83.                     }
  84.                 }
  85.  
  86.                 for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
  87.                 {
  88.                     if (Bag* pBag = pPlayer->GetBagByPos(i))
  89.                         for (uint32 j = 0; j < pBag->GetBagSize(); j++)
  90.                         {
  91.                             if(limit > 30)
  92.                                 break;
  93.                             if (Item* pItem = pPlayer->GetItemByPos(i, j))
  94.                             {
  95.                                 uint32 Display = pItem->GetTemplate()->DisplayInfoID;
  96.                                 if(IsSuitable(pItem, OLD, pPlayer))
  97.                                     if(Items[GUID].find(Display) == Items[GUID].end())
  98.                                     {
  99.                                         limit++;
  100.                                         Items[GUID][Display] = pItem;
  101.                                         pPlayer->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, pItem->GetTemplate()->Name1, uiAction, Display, "Using this item for transmogrigy will bind it to you and make it non-refundable and non-tradeable.\nDo you wish to continue?\n\n"+ pItem->GetTemplate()->Name1, GetSellPrice(OLD, pPlayer), false);
  102.                                     }
  103.                             }
  104.                         }
  105.                 }
  106.  
  107.                 pPlayer->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, "Remove transmogrification", EQUIPMENT_SLOT_END+3, uiAction, "Remove transmogrification from "+(std::string)GetSlotName(uiAction)+"?", 0, false);
  108.                 pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TALK, "Back..", EQUIPMENT_SLOT_END+1, 0);
  109.                 pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pUnit->GetGUID());
  110.             }
  111.             else
  112.                 OnGossipHello(pPlayer, pUnit);
  113.         }
  114.         else if(sender == EQUIPMENT_SLOT_END+1) // Back
  115.             OnGossipHello(pPlayer, pUnit);
  116.         else if(sender == EQUIPMENT_SLOT_END+2) // Remove Transmogrifications
  117.         {
  118.             for (uint8 Slot = EQUIPMENT_SLOT_START; Slot < EQUIPMENT_SLOT_END; Slot++)
  119.                 if (Item* pItem = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, Slot))
  120.                 {
  121.                     if(pItem->FakeEntry || pItem->FakeOwner)
  122.                     {
  123.                         CharacterDatabase.PExecute("UPDATE item_instance SET FakeEntry = 0, FakeOwner = 0 WHERE guid = %u", pItem->GetGUIDLow());
  124.                         pItem->FakeEntry = NULL;
  125.                         pItem->FakeOwner = NULL;
  126.                     }
  127.                     pPlayer->SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (Slot * 2), pItem->GetEntry());
  128.                 }
  129.                 OnGossipHello(pPlayer, pUnit);
  130.         }
  131.         else if(sender == EQUIPMENT_SLOT_END+3) // Remove Transmogrification from single item
  132.         {
  133.             if (Item* pItem = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, uiAction))
  134.             {
  135.                 if(pItem->FakeEntry || pItem->FakeOwner)
  136.                 {
  137.                     CharacterDatabase.PExecute("UPDATE item_instance SET FakeEntry = 0, FakeOwner = 0 WHERE guid = %u", pItem->GetGUIDLow());
  138.                     pItem->FakeEntry = NULL;
  139.                     pItem->FakeOwner = NULL;
  140.                 }
  141.                 pPlayer->SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (uiAction * 2), pItem->GetEntry());
  142.             }
  143.             OnGossipSelect(pPlayer, pUnit, EQUIPMENT_SLOT_END, uiAction);
  144.         }
  145.         else // Transmogrify
  146.         {
  147.             uint32 GUID = pPlayer->GetGUIDLow();
  148.             if(Item* OLD = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, sender))
  149.             {
  150.                 if(Items[GUID].find(uiAction) != Items[GUID].end() && Items[GUID][uiAction]->IsInWorld())
  151.                 {
  152.                     Item* pItem = Items[GUID][uiAction];
  153.                     if(pItem->GetOwnerGUID() == pPlayer->GetGUID() && (pItem->IsInBag() || pItem->GetBagSlot() == INVENTORY_SLOT_BAG_0) && IsSuitable(pItem, OLD, pPlayer))
  154.                     {
  155.                         pPlayer->ModifyMoney(-1*GetSellPrice(OLD, pPlayer)); // take cost
  156.                         pItem->SetNotRefundable(pPlayer);
  157.                         pItem->SetBinding(true); // soulbound
  158.                         uint32 FakeEntry = pItem->GetEntry();
  159.                         CharacterDatabase.PExecute("UPDATE item_instance SET FakeEntry = %u, FakeOwner = %u WHERE guid = %u", FakeEntry, pPlayer->GetGUIDLow(), OLD->GetGUIDLow());
  160.                         OLD->FakeEntry = FakeEntry;
  161.                         OLD->FakeOwner = pPlayer->GetGUIDLow();
  162.                         // pPlayer->SetVisibleItemSlot(sender, OLD); // No need to use this, useless checking
  163.                         pPlayer->UpdateUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (sender * 2), FakeEntry); // use this instead
  164.                         pPlayer->GetSession()->SendAreaTriggerMessage("%s transmogrified", GetSlotName(sender));
  165.                     }
  166.                     else
  167.                         pPlayer->GetSession()->SendNotification("Selected items are not suitable");
  168.                 }
  169.                 else
  170.                     pPlayer->GetSession()->SendNotification("Selected item does not exist");
  171.             }
  172.             else
  173.                 pPlayer->GetSession()->SendNotification("Equipment slot is empty");
  174.             Items[GUID].clear();
  175.             OnGossipSelect(pPlayer, pUnit, EQUIPMENT_SLOT_END, sender);
  176.         }
  177.         return true;
  178.     }
  179.  
  180. private:
  181.     std::map<uint64, std::map<uint32, Item*> > Items; // Items[GUID][DISPLAY] = item
  182.  
  183.     char * GetSlotName(uint8 slot)
  184.     {
  185.         switch(slot)
  186.         {
  187.         case EQUIPMENT_SLOT_HEAD      : return "Head";
  188.         case EQUIPMENT_SLOT_SHOULDERS : return "Shoulders";
  189.         case EQUIPMENT_SLOT_BODY      : return "Shirt";
  190.         case EQUIPMENT_SLOT_CHEST     : return "Chest";
  191.         case EQUIPMENT_SLOT_WAIST     : return "Waist";
  192.         case EQUIPMENT_SLOT_LEGS      : return "Legs";
  193.         case EQUIPMENT_SLOT_FEET      : return "Feet";
  194.         case EQUIPMENT_SLOT_WRISTS    : return "Wrists";
  195.         case EQUIPMENT_SLOT_HANDS     : return "Hands";
  196.         case EQUIPMENT_SLOT_BACK      : return "Back";
  197.         case EQUIPMENT_SLOT_MAINHAND  : return "Main hand";
  198.         case EQUIPMENT_SLOT_OFFHAND   : return "Off hand";
  199.         case EQUIPMENT_SLOT_RANGED    : return "Ranged";
  200.         case EQUIPMENT_SLOT_TABARD    : return "Tabard";
  201.         default: return NULL;
  202.         }
  203.     }
  204.  
  205.     bool IsSuitable(Item* pItem, Item* OLD, Player* pPlayer)
  206.     {
  207.         if(OLD->GetTemplate()->DisplayInfoID != pItem->GetTemplate()->DisplayInfoID)
  208.         {
  209.             if(const ItemTemplate* FakeItemTemplate = sObjectMgr->GetItemTemplate(OLD->FakeEntry))
  210.                 if(FakeItemTemplate->DisplayInfoID == pItem->GetTemplate()->DisplayInfoID)
  211.                     return false;
  212.             if(pPlayer->CanUseItem(pItem, false) == EQUIP_ERR_OK)
  213.                 if(HasGoodQuality(pItem))
  214.                 {
  215.                     uint32 NClass = pItem->GetTemplate()->Class;
  216.                     uint32 OClass = OLD->GetTemplate()->Class;
  217.                     uint32 NSubClass = pItem->GetTemplate()->SubClass;
  218.                     uint32 OSubClass = OLD->GetTemplate()->SubClass;
  219.                     uint32 NEWinv = pItem->GetTemplate()->InventoryType;
  220.                     uint32 OLDinv = OLD->GetTemplate()->InventoryType;
  221.                     if(NClass == OClass) // not possibly the best structure here, but atleast I got my head around this
  222.                         if(NClass == ITEM_CLASS_WEAPON && NSubClass != ITEM_SUBCLASS_WEAPON_FISHING_POLE && OSubClass != ITEM_SUBCLASS_WEAPON_FISHING_POLE)
  223.                         {
  224.                             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)))
  225.                                 if(NEWinv == OLDinv || (NEWinv == INVTYPE_WEAPON && (OLDinv == INVTYPE_WEAPONMAINHAND || OLDinv == INVTYPE_WEAPONOFFHAND)))
  226.                                     return true;
  227.                         }
  228.                         else if(NClass == ITEM_CLASS_ARMOR)
  229.                             if(NSubClass == OSubClass)
  230.                                 if(NEWinv == OLDinv || (NEWinv == INVTYPE_CHEST && OLDinv == INVTYPE_ROBE) || (NEWinv == INVTYPE_ROBE && OLDinv == INVTYPE_CHEST))
  231.                                     return true;
  232.                 }
  233.         }
  234.         return false;
  235.     }
  236.  
  237.     bool HasGoodQuality(Item* pItem)
  238.     {
  239.         uint32 Quality = pItem->GetTemplate()->Quality;
  240.         if(Quality == ITEM_QUALITY_UNCOMMON || Quality == ITEM_QUALITY_RARE || Quality == ITEM_QUALITY_EPIC || Quality == ITEM_QUALITY_HEIRLOOM)
  241.             return true;
  242.         return false;
  243.     }
  244.  
  245.     uint32 GetSellPrice(Item* pItem, Player* pPlayer) // The formula is not right
  246.     {
  247.         uint32 Price = pItem->GetTemplate()->SellPrice;
  248.         uint32 MinPrice = pPlayer->getLevel() * 1176;
  249.         if(Price < MinPrice)
  250.             return MinPrice;
  251.         return Price;
  252.     }
  253. };
  254.  
  255. void AddSC_NPC_Transmogrify()
  256. {
  257.     new NPC_Transmogrify();
  258. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement