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 | } |