SHOW:
|
|
- or go back to the newest paste.
| 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 | - | for (uint8 Slot = EQUIPMENT_SLOT_START; Slot < EQUIPMENT_SLOT_END; Slot++) |
| 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 | - | uint32 Quality = pItem->GetTemplate()->Quality; |
| 28 | + | |
| 29 | - | if(Quality == ITEM_QUALITY_UNCOMMON || Quality == ITEM_QUALITY_RARE || Quality == ITEM_QUALITY_EPIC || Quality == ITEM_QUALITY_HEIRLOOM) |
| 29 | + | Make DB saving even better |
| 30 | ||
| 31 | Test on cata -> implement UI xD? | |
| 32 | */ | |
| 33 | ||
| 34 | - | pPlayer->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, "Remove transmogrifications", EQUIPMENT_SLOT_END+3, 0, "Remove transmogrifications from all equipped items?", 0, false); |
| 34 | + | |
| 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 | - | if(sender == EQUIPMENT_SLOT_END) |
| 43 | + | |
| 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 | - | if(Items[GUID].find(pItem->GetTemplate()->DisplayInfoID) == Items[GUID].end()) |
| 56 | + | |
| 57 | bool OnGossipSelect(Player* pPlayer, Creature* pUnit, uint32 sender, uint32 uiAction) | |
| 58 | {
| |
| 59 | - | Items[GUID][pItem->GetTemplate()->DisplayInfoID] = pItem; |
| 59 | + | |
| 60 | - | pPlayer->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, pItem->GetTemplate()->Name1, uiAction, pItem->GetTemplate()->DisplayInfoID, AreYouSure(uiAction, pItem), 0, false); |
| 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 | - | if(Items[GUID].find(pItem->GetTemplate()->DisplayInfoID) == Items[GUID].end()) |
| 73 | + | uint32 Display = pItem->GetTemplate()->DisplayInfoID; |
| 74 | if(IsSuitable(pItem, OLD, pPlayer)) | |
| 75 | {
| |
| 76 | - | Items[GUID][pItem->GetTemplate()->DisplayInfoID] = pItem; |
| 76 | + | if(Items[GUID].find(Display) == Items[GUID].end()) |
| 77 | - | pPlayer->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, pItem->GetTemplate()->Name1, uiAction, pItem->GetTemplate()->DisplayInfoID, AreYouSure(uiAction, pItem), 0, false); |
| 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 | - | if(Items[GUID].empty()) |
| 82 | + | |
| 83 | } | |
| 84 | - | pPlayer->GetSession()->SendNotification("You have no suitable items in your inventory");
|
| 84 | + | |
| 85 | - | OnGossipHello(pPlayer, pUnit); |
| 85 | + | |
| 86 | - | return true; |
| 86 | + | |
| 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 | - | else if(sender == EQUIPMENT_SLOT_END+1) |
| 94 | + | |
| 95 | uint32 Display = pItem->GetTemplate()->DisplayInfoID; | |
| 96 | - | else if(sender == EQUIPMENT_SLOT_END+2) |
| 96 | + | |
| 97 | - | pPlayer->PlayerTalkClass->SendCloseGossip(); |
| 97 | + | if(Items[GUID].find(Display) == Items[GUID].end()) |
| 98 | - | else if(sender == EQUIPMENT_SLOT_END+3) |
| 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 | - | else |
| 113 | + | |
| 114 | else if(sender == EQUIPMENT_SLOT_END+1) // Back | |
| 115 | OnGossipHello(pPlayer, pUnit); | |
| 116 | - | Item* OLD = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, sender); |
| 116 | + | else if(sender == EQUIPMENT_SLOT_END+2) // Remove Transmogrifications |
| 117 | - | if(!OLD || Items[GUID].find(uiAction) == Items[GUID].end() || !IsSuitable(Items[GUID][uiAction], OLD, pPlayer)) |
| 117 | + | |
| 118 | - | pPlayer->GetSession()->SendNotification("There is no suitable item in the slot");
|
| 118 | + | |
| 119 | if (Item* pItem = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, Slot)) | |
| 120 | {
| |
| 121 | - | uint32 FakeEntry = Items[GUID][uiAction]->GetEntry(); |
| 121 | + | |
| 122 | - | CharacterDatabase.PExecute("UPDATE item_instance SET FakeEntry = %u, FakeOwner = %u WHERE guid = %u", FakeEntry, pPlayer->GetGUIDLow(), OLD->GetGUIDLow());
|
| 122 | + | |
| 123 | - | OLD->FakeEntry = FakeEntry; |
| 123 | + | |
| 124 | - | OLD->FakeOwner = pPlayer->GetGUIDLow(); |
| 124 | + | |
| 125 | - | // pPlayer->SetVisibleItemSlot(sender, OLD); // No need to use this, useless checking |
| 125 | + | |
| 126 | - | pPlayer->UpdateUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (sender * 2), FakeEntry); // use this instead |
| 126 | + | |
| 127 | - | pPlayer->GetSession()->SendAreaTriggerMessage("%s transmogrified", GetSlotName(sender));
|
| 127 | + | |
| 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 | - | if(pItem->GetTemplate()->DisplayInfoID != OLD->GetTemplate()->DisplayInfoID) |
| 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 | - | uint32 Quality = pItem->GetTemplate()->Quality; |
| 164 | + | pPlayer->GetSession()->SendAreaTriggerMessage("%s transmogrified", GetSlotName(sender));
|
| 165 | - | if(Quality == ITEM_QUALITY_UNCOMMON || Quality == ITEM_QUALITY_RARE || Quality == ITEM_QUALITY_EPIC || Quality == ITEM_QUALITY_HEIRLOOM) // Heirlooms also accepted? Remember to change in Gossip Hello too! |
| 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 | - | if(NClass == ITEM_CLASS_WEAPON) |
| 172 | + | |
| 173 | pPlayer->GetSession()->SendNotification("Equipment slot is empty");
| |
| 174 | Items[GUID].clear(); | |
| 175 | OnGossipSelect(pPlayer, pUnit, EQUIPMENT_SLOT_END, sender); | |
| 176 | - | return true; |
| 176 | + | |
| 177 | return true; | |
| 178 | } | |
| 179 | ||
| 180 | - | if(NSubClass == OSubClass && pItem->GetTemplate()->InventoryType == OLD->GetTemplate()->InventoryType) |
| 180 | + | |
| 181 | std::map<uint64, std::map<uint32, Item*> > Items; // Items[GUID][DISPLAY] = item | |
| 182 | - | return true; |
| 182 | + | |
| 183 | char * GetSlotName(uint8 slot) | |
| 184 | {
| |
| 185 | switch(slot) | |
| 186 | - | return false; |
| 186 | + | |
| 187 | case EQUIPMENT_SLOT_HEAD : return "Head"; | |
| 188 | - | std::string AreYouSure(uint8 slot, Item* pItem) |
| 188 | + | |
| 189 | case EQUIPMENT_SLOT_BODY : return "Shirt"; | |
| 190 | - | std::string msg = "Transmogrify "; |
| 190 | + | |
| 191 | - | msg += GetSlotName(slot); |
| 191 | + | |
| 192 | - | msg += "\nTo "; |
| 192 | + | |
| 193 | - | msg += pItem->GetTemplate()->Name1; |
| 193 | + | |
| 194 | - | return msg; |
| 194 | + | |
| 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 | } |