View difference between Paste ID: UTUCD6bE and BdvQMfe5
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
}