Guest User

Classic

a guest
Aug 1st, 2009
385
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.65 KB | None | 0 0
  1. /*
  2. Automated Vendor Machine (AVM)
  3.  
  4. Description:
  5. An NPC who, when talked to, allows you to enter an item NAME or ID, and will present you with all items matching that name or ID.
  6. The user is then able to purchase the found items.
  7.  
  8. By Jotox/Classic
  9.  
  10. Copyright (c) 2009
  11. */
  12.  
  13. //---------------------------
  14. //CONFIG!!
  15. //---------------------------
  16.  
  17. //Max item quality allowed to be purchased.
  18. //Green = 2, Blue = 3, Epic = 4, Legendary = 5, Artifact(GM item) = 6, Heirloom = 7
  19. #define MAX_QUALITY 4 //Default: Legendaries and above cannot be purchased. Epic and below can.
  20.  
  21. //Allow item sets (such as tier 7), conjured items, or quest items to be purchased?
  22. //Default: no for all. Change the 0 to 1 to allow.
  23. #define ALLOW_ITEM_SETS 0
  24. #define ALLOW_CONJURED 0
  25. #define ALLOW_QUEST 0
  26. #define ALLOW_FREE 0
  27. //Note: Free means no extended cost or gold cost. If you allow this, items which sell for more than they are purchased for will be allowed as well.
  28.  
  29. //Enable Extended Cost items. Disabling causes extended cost items to be free (unless you add a gold price to them in your database).
  30. #define ENABLE_EXTENDED_COSTS 1
  31.  
  32. //Enable the banning of items via the "avm_banned_items" table.
  33. #define ENABLE_ITEM_BANNING 1
  34.  
  35. //Maximum number of items found per search. Do not set above 100.
  36. #define MAX_RESULTS 30 //Suggested value for efficiency.
  37.  
  38. //NPC ID
  39. #define NPC_ID 993311
  40.  
  41. //Are you Arcemu? (Set to 1 if you're on arcemu. 0 for aspire.)
  42. #define ARCEMU 0
  43.  
  44. //---------------------------
  45. //END CONFIG -- Do not edit below this if you do not know what you're doing.
  46. //---------------------------
  47.  
  48. #include "StdAfx.h"
  49. #include "Setup.h"
  50. using namespace std;
  51.  
  52. //Arcemu support.
  53. #if ARCEMU > 0
  54. typedef Object* ObjectPointer;
  55. typedef Player* PlayerPointer;
  56. typedef Unit* UnitPointer;
  57. typedef Creature* CreaturePointer;
  58. #define HEARTHSTONE_TOLOWER(x) arcemu_TOLOWER(x)
  59. #endif
  60.  
  61. map< uint32, bool> CItems;//Global list to keep track of items. Map should? be faster than vector looping for finding items in it. Not sure though. W/e.
  62. map< uint32, uint32 > Extended_Cost_List;//List to keep track of extended cost.
  63. map< uint32, bool > banned_items;//List to keep track of banned items.
  64.  
  65. void LoadItemTables()
  66. {
  67. QueryResult * result;
  68.  
  69. if( ENABLE_EXTENDED_COSTS )
  70. {
  71. #if ARCEMU==0
  72. result = WorldDatabase.Query("SELECT DISTINCT item, extendedcost FROM vendors WHERE extendedcost > 0");
  73. #else
  74. result = WorldDatabase.Query("SELECT DISTINCT item, extended_cost FROM vendors WHERE extended_cost > 0");
  75. #endif
  76. if( !result )
  77. printf("(Automated Item Vendor): Error loading extended costs.");
  78. else
  79. {
  80. do
  81. {
  82. uint32 id = result->Fetch()[0].GetUInt32();
  83. uint32 ec = result->Fetch()[1].GetUInt32();
  84. if( dbcItemExtendedCost.LookupEntryForced(ec) )
  85. Extended_Cost_List[ id ] = ec;
  86.  
  87. } while (result->NextRow());
  88. delete result;
  89. }
  90. }
  91.  
  92. if( ENABLE_ITEM_BANNING )
  93. {
  94. result = WorldDatabase.Query("SELECT * FROM avm_banned_items");
  95. if( !result )
  96. printf("(Automated Item Vendor): Error loading banned items.");
  97. else
  98. {
  99. do
  100. {
  101. banned_items[ result->Fetch()[0].GetUInt32() ] = true;
  102. } while (result->NextRow());
  103.  
  104. delete result;
  105. }
  106. }
  107. }
  108.  
  109. void AddItemsToCreature( CreaturePointer unit, vector<ItemPrototype*> &items )
  110. {
  111. for( vector<ItemPrototype*>::iterator itr = items.begin(); itr != items.end(); itr++ )
  112. {
  113. if( !CItems[ (*itr)->ItemId ] )
  114. {
  115. #if ARCEMU > 0
  116. unit->AddVendorItem( (*itr)->ItemId, (*itr)->MaxCount /*Full stack by default.*/, ( (Extended_Cost_List[(*itr)->ItemId ] ) ? dbcItemExtendedCost.LookupEntryForced( Extended_Cost_List[ (*itr)->ItemId ] ) : NULL) );//If we don't add this, when the player tries to buy it will give an error.
  117. #else
  118. unit->AddVendorItem( (*itr)->ItemId, (*itr)->MaxCount /*Full stack by default.*/ );//If we don't add this, when the player tries to buy it will give an error.
  119. if( Extended_Cost_List[ (*itr)->ItemId ] )
  120. {
  121. CreatureItem ci;
  122. unit->GetSellItemByItemId( (*itr)->ItemId , ci);
  123. ci.extended_cost = dbcItemExtendedCost.LookupEntryForced( Extended_Cost_List[ (*itr)->ItemId ] );
  124. }
  125. #endif
  126.  
  127. CItems[ (*itr)->ItemId ] = true;//May as well just keep track of this, to prevent duplication.
  128. }
  129. }
  130. }
  131.  
  132. void SendItemList( CreaturePointer unit, PlayerPointer plr, vector<ItemPrototype*> &items )//Sends a vendor window with only the items in the "items" vector
  133. {
  134. if( items.size() < 1 )
  135. return;//.......we shouldn't get here.
  136. if( !unit || !plr || !plr->IsInWorld() || !plr->GetSession() )
  137. return;//AHH
  138.  
  139. WorldPacket data(((items.size() * 28) + 9)); // allocate
  140.  
  141. data.SetOpcode( SMSG_LIST_INVENTORY );
  142. data << unit->GetGUID();
  143. data << uint8( 0 ); // placeholder for item count
  144.  
  145. uint32 counter = 0;
  146.  
  147. ItemPrototype * curItem;
  148.  
  149. for( vector<ItemPrototype*>::iterator itr = items.begin(); itr != items.end(); itr++ )
  150. {
  151. curItem = *itr;
  152. data << (counter + 1);//Count
  153. data << curItem->ItemId;//Item id
  154. data << curItem->DisplayInfoID;//Display id
  155. data << int32(-1);//Available amount
  156. data << curItem->BuyPrice;//Buyprice
  157. data << int32(-1); // ???
  158. data << curItem->MaxCount;
  159.  
  160. if( Extended_Cost_List[ curItem->ItemId ] )
  161. data << Extended_Cost_List[ curItem->ItemId ];
  162. else
  163. data << uint32(0);//Extended cost
  164.  
  165. counter++;
  166. }
  167.  
  168. const_cast<uint8*>(data.contents())[8] = (uint8)counter; // set count
  169.  
  170. plr->GetSession()->SendPacket( &data );
  171. }
  172.  
  173. bool stringtest( string thing )//Tests whether a string consists SOLELY of numbers or not. returns true if the string is all numbers.
  174. {
  175. char str[256];
  176. sprintf(str, "%d", atoi(thing.c_str()) );//If the string stays the same when all non-number characters are removed, it's only numbrs. duh.
  177. return str == thing;
  178. }
  179.  
  180. bool TestItem( ItemPrototype * it, PlayerPointer plr )
  181. {
  182. if( !it )
  183. return false;
  184.  
  185. if( !(ALLOW_ITEM_SETS) && it->ItemSet )//item sets
  186. return false;
  187.  
  188. if( ( ( !(ALLOW_FREE) && (!it->BuyPrice) || it->BuyPrice < it->SellPrice) ) && !Extended_Cost_List[ it->ItemId ] )// free / sell for more than bought and no extended cost
  189. return false;
  190.  
  191. if( it->Quality > MAX_QUALITY )//quality
  192. return false;
  193.  
  194. if( (!(ALLOW_QUEST) && it->Flags & ITEM_FLAG_QUEST) || (!(ALLOW_CONJURED) && it->Flags & ITEM_FLAG_CONJURED) )//quest / conjured
  195. return false;
  196.  
  197. if( !(ALLOW_QUEST) && it->QuestId )//Quest again
  198. return false;
  199.  
  200. if( banned_items[ it->ItemId ] && !plr->GetSession()->HasGMPermissions() )//only GMs can get banned items.
  201. return false;
  202.  
  203. return true;
  204. }
  205.  
  206. void FindItem( UnitPointer unit, PlayerPointer plr, const char* nameC, vector<ItemPrototype*> &items )
  207. {
  208.  
  209. string name( nameC );
  210.  
  211. int itemid = atoi(name.c_str());
  212. if( itemid && !(itemid==INT_MIN || itemid==INT_MAX) && stringtest(name) )
  213. {
  214. ItemPrototype * it = ItemPrototypeStorage.LookupEntry(itemid);//If it's just an item id, no point in using SQL. eh?
  215.  
  216. if( it && TestItem(it, plr) )
  217. items.push_back(it);
  218.  
  219. if( !items.size() )
  220. unit->SendChatMessageToPlayer(15, 0, "Your item was not found, or was not available for purchase. Please check you have the correct Item I.D. and try again.", plr);//Whisper, in universal language.
  221.  
  222. return;
  223. }
  224.  
  225. string x = name;
  226. HEARTHSTONE_TOLOWER(x);
  227. if(x.length() < 4)
  228. {
  229. unit->SendChatMessageToPlayer(15, 0, "Please enter a name 4 or more letters in length.", plr);
  230. return;
  231. }
  232.  
  233. ItemPrototype * it;
  234. uint32 count = 0;
  235.  
  236. QueryResult * result = WorldDatabase.Query("SELECT entry FROM items WHERE quality <= %u %s AND name1 like '%s' ORDER BY quality DESC, itemlevel DESC LIMIT %u", MAX_QUALITY, ((ALLOW_ITEM_SETS) ? "" : "AND itemset = 0") ,("%" + WorldDatabase.EscapeString(x) + "%").c_str(), MAX_RESULTS );
  237.  
  238. if( !result )
  239. {
  240. unit->SendChatMessageToPlayer(15, 0, "I'm sorry, I could not find your item. Please check the name and try again.", plr);
  241. return;
  242. }
  243.  
  244. do
  245. {
  246. uint32 entry = result->Fetch()[0].GetUInt32();
  247. it = ItemPrototypeStorage.LookupEntry( entry );
  248.  
  249. if( !it || !TestItem(it, plr) )
  250. continue;
  251.  
  252. items.push_back(it);
  253. } while (result->NextRow());
  254.  
  255. delete result;
  256.  
  257. if( !items.size() )
  258. unit->SendChatMessageToPlayer(15, 0, "I'm sorry, that item is unavailable for purchase.", plr);
  259.  
  260. return;
  261. }
  262.  
  263. class SCRIPT_DECL AutomatedItemVendor : public GossipScript
  264. {
  265. public:
  266.  
  267. void GossipHello(ObjectPointer pObject, PlayerPointer plr, bool AutoSend)
  268. {
  269. GossipMenu *Menu;
  270. objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 44333220, plr);
  271.  
  272. #if ARCEMU == 0
  273. Menu->AddItem( 1, "Search for an item to purchase.", 1, true, 0, "Enter the Name or Item ID:");
  274. #else
  275. Menu->AddItem( 1, "Search for an item to purchase.", 1, 1);
  276. #endif
  277.  
  278. Menu->AddItem( 0, "How does this vendor work?", 99);
  279.  
  280. if(AutoSend)
  281. Menu->SendTo(plr);
  282. }
  283.  
  284. void GossipSelectOption(ObjectPointer pObject, PlayerPointer plr, uint32 Id, uint32 IntId, const char * Code)
  285. {
  286. GossipMenu * Menu;
  287. switch (IntId)
  288. {
  289. case 99://Help pl0x
  290. {
  291. string msg = "This vendor is an automated vendor made for your benefit. Simply click on the first option in the menu and enter the name or ID of an item ";
  292. msg += "that you wish to purchase.";
  293. TO_UNIT(pObject)->SendChatMessageToPlayer(15, 0, msg.c_str(), plr);//Whisper, in universal language.
  294. TO_UNIT(pObject)->SendChatMessageToPlayer(15, 0, "I will then find all items with that name, and present them for you to purchase.", plr);
  295. GossipHello(pObject, plr, true);
  296. }break;
  297.  
  298. default://We're looking for an item.
  299. {
  300. vector<ItemPrototype*> items;
  301. FindItem(TO_UNIT(pObject), plr, Code, items);
  302. if( !items.size() )
  303. {
  304. GossipHello(pObject, plr, true);
  305. return;
  306. }
  307.  
  308. AddItemsToCreature( TO_CREATURE( pObject ), items );//Add the items to the creature's vendor list, so the player can actually buy the items instead of just view them
  309.  
  310. SendItemList( TO_CREATURE(pObject), plr, items );//Show him the list of items.
  311.  
  312. items.clear();
  313. }break;
  314.  
  315. }
  316. }
  317.  
  318. void GossipEnd(ObjectPointer pObject, PlayerPointer Plr)
  319. {
  320. TO_UNIT(pObject)->SendChatMessageToPlayer(15, 0, "Thank you for using the Automated Item Vendor. Please Come Again!", Plr);//If you want, you may as well add your own message about voting on your server's website or somethin.
  321. Plr->CleanupGossipMenu();
  322. }
  323.  
  324. void Destroy()
  325. {
  326. delete this;
  327. }
  328. };
  329.  
  330.  
  331. void SetupVendorScript(ScriptMgr * mgr)
  332. {
  333. mgr->register_gossip_script(NPC_ID, (GossipScript*) new AutomatedItemVendor() );
  334.  
  335. LoadItemTables();
  336.  
  337. printf("\nAutomated Item Vendor Loaded Successfully.\n");
  338. }
Advertisement
Add Comment
Please, Sign In to add comment