xingchao

bob bot class

Jul 13th, 2019
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. Auto Mall
  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. Also, the vendor displays a menu of
  8.  
  9. This vendor is intended for Level 80 Funservers.
  10.  
  11. By Jotox/Classic
  12.  
  13. Copyright (c) 2009
  14. */
  15.  
  16. //---------------------------
  17. //CONFIG!!
  18. //---------------------------
  19.  
  20. //Max item quality allowed to be purchased.
  21. //Green = 2, Blue = 3, Epic = 4, Legendary = 5, Artifact(GM item) = 6, Heirloom = 7
  22. #define MAX_QUALITY 4 //Default: Legendaries and above cannot be purchased. Epic and below can.
  23.  
  24. //Allow item sets (such as tier 7), conjured items, or quest items to be purchased?
  25. //0 = Not allowed, 1 = Allowed.
  26. #define ALLOW_ITEM_SETS 1
  27. #define ALLOW_CONJURED 0
  28. #define ALLOW_QUEST 0
  29. #define ALLOW_FREE 0
  30. //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.
  31.  
  32. //Enable Extended Cost items. Disabling causes extended cost items to be free (unless you add a gold price to them in your database).
  33. #define ENABLE_EXTENDED_COSTS 1
  34.  
  35. //Enable the banning of items via the "mall_banned_items" table.
  36. #define ENABLE_ITEM_BANNING 1
  37.  
  38. //Maximum number of items found per search. Note: The client can only handle 160 at a time; if more than 160 are found, everything beyond 160 will be discarded.
  39. #define MAX_RESULTS 300
  40.  
  41. //Mall menu -- Mounts and armor and weapons and such.
  42. #define ENABLE_MALL_MENU 1
  43.  
  44. //Item Searching -- Enter an item name or ID and it gives you the results
  45. #define ENABLE_ITEM_SEARCHING 1
  46.  
  47. //Enable bot-to-bot interaction for the portable verison of the script (Fighting enemy bots, buffing ally bots)
  48. #define ENABLE_BOT_FIGHTS 1
  49.  
  50. //NPC ID
  51. #define NPC_ID 993312
  52.  
  53. //Item ID (Item version of the vendor)
  54. #define ITEM_ID 99499
  55.  
  56. //Are you on Arcemu? (0 for Aspire, 1 for ArcEmu)
  57. #define ARCEMU 0
  58.  
  59. //---------------------------
  60. //END CONFIG -- Do not edit below this if you do not know what you're doing.
  61. //---------------------------
  62.  
  63. #include "StdAfx.h"
  64. #include "Setup.h"
  65. using namespace std;
  66.  
  67. //Arcemu support.
  68. #if ARCEMU > 0
  69. typedef Object* ObjectPointer;
  70. typedef Player* PlayerPointer;
  71. typedef Unit* UnitPointer;
  72. typedef Creature* CreaturePointer;
  73. typedef Item* ItemPointer;
  74. typedef Spell* SpellPointer;
  75. #define TO_ITEM(x) static_cast< Item*>(x)
  76. #define HEARTHSTONE_TOLOWER(x) arcemu_TOLOWER(x)
  77. enum GossipIcons {
  78. GOSSIP_ICON_GOSSIP_NORMAL = 0,
  79. GOSSIP_ICON_GOSSIP_VENDOR = 1,
  80. GOSSIP_ICON_GOSSIP_FLIGHT = 2,
  81. GOSSIP_ICON_GOSSIP_TRAINER = 3,
  82. GOSSIP_ICON_GOSSIP_ENGINEER1 = 4,
  83. GOSSIP_ICON_GOSSIP_ENGINEER2 = 5,
  84. GOSSIP_ICON_GOSSIP_AUCTION = 6,
  85. GOSSIP_ICON_GOSSIP_EXTRA = 7,
  86. GOSSIP_ICON_GOSSIP_TABARD = 8,
  87. GOSSIP_ICON_GOSSIP_ARENA = 9,
  88. GOSSIP_ICON_GOSSIP_COIN = 9,
  89. };
  90. #endif
  91.  
  92. map< uint64, set<uint32> * > CItems;//List of a set of items for every creature GUID
  93. map< uint64, set<vector<uint32>*>* > CMenusList;//List of all menus that a creature already has added.
  94. map< uint32, uint32 > Extended_Cost_List;//List to keep track of extended cost.
  95. map< uint32, bool > banned_items;//List to keep track of banned items.
  96. map< uint64, ItemPointer> plr_items;
  97.  
  98. #if ENABLE_MALL_MENU > 0
  99. uint32 counter = 500;
  100.  
  101. struct armor_struc {
  102. vector<uint32> head;
  103. vector<uint32> shoulder;
  104. vector<uint32> body;
  105. vector<uint32> wrist;
  106. vector<uint32> hands;
  107. vector<uint32> waist;
  108. vector<uint32> legs;
  109. vector<uint32> feet;
  110. };
  111.  
  112. armor_struc armor[4];// Cloth = 0, Leather = 1, Mail = 2, Plate = 3. Total of 4.
  113.  
  114. map< string, uint32 > vector_map_map;//the uint32 points to the string's key in vector_map
  115. map< uint32, vector<uint32> *> vector_map;
  116. map< uint32, vector<uint32> *> armor_map;
  117.  
  118. #define armor_CLOTH 0
  119. #define armor_LEATHER 1
  120. #define armor_MAIL 2
  121. #define armor_PLATE 3
  122.  
  123. #endif
  124.  
  125.  
  126. #define BOT_BLUE 29280
  127. #define BOT_RED 29281
  128. #define BOT_BLANK 29279
  129.  
  130. #define SIDE_HORDE 1
  131. #define SIDE_ALLIANCE 0
  132.  
  133. bool IsCustom( uint32 id )
  134. {
  135. return id > 56000;//custom items can't be seen.
  136. }
  137.  
  138. void AddItemsToCreature( CreaturePointer unit, vector<uint32> *items, bool is_menu = true )
  139. {
  140. if( is_menu )
  141. {
  142. if( !CMenusList[ unit->GetGUID() ] || CMenusList[ unit->GetGUID() ]->find( items ) != CMenusList[ unit->GetGUID() ]->end() )
  143. return;
  144. CMenusList[ unit->GetGUID() ]->insert( items );
  145. }
  146. for( vector<uint32>::iterator itr = items->begin(); itr != items->end(); itr++ )
  147. {
  148. ItemPrototype * curItem = ItemPrototypeStorage.LookupEntry(*itr);
  149.  
  150. if( !is_menu && CItems[ unit->GetGUID() ]->find( curItem->ItemId ) != CItems[ unit->GetGUID() ]->end() )
  151. continue;
  152.  
  153. #if ARCEMU > 0
  154. unit->AddVendorItem( curItem->ItemId, curItem->MaxCount /*Full stack by default.*/, ( (Extended_Cost_List[curItem->ItemId ] ) ? dbcItemExtendedCost.LookupEntryForced( Extended_Cost_List[ curItem->ItemId ] ) : NULL) );//If we don't add this, when the player tries to buy it will give an error.
  155. #else
  156. unit->AddVendorItem( curItem->ItemId, curItem->MaxCount /*Full stack by default.*/ );//If we don't add this, when the player tries to buy it will give an error.
  157. if( Extended_Cost_List[ curItem->ItemId ] )
  158. {
  159. CreatureItem ci;
  160. unit->GetSellItemByItemId( curItem->ItemId , ci);
  161. ci.extended_cost = dbcItemExtendedCost.LookupEntryForced( Extended_Cost_List[ curItem->ItemId ] );
  162. }
  163. #endif
  164.  
  165. CItems[ unit->GetGUID() ]->insert( curItem->ItemId );
  166. }
  167. }
  168.  
  169. void SendItemList( CreaturePointer unit, PlayerPointer plr, vector<uint32> * items )//Sends a Mall window with only the items in the "items" vector
  170. {
  171. if( items->size() < 1 )
  172. return;//.......we shouldn't get here.
  173. if( !unit || !plr || !plr->IsInWorld() || !plr->GetSession() )
  174. return;//AHH
  175.  
  176. WorldPacket data(((items->size() * 28) + 9)); // allocate
  177.  
  178. data.SetOpcode( SMSG_LIST_INVENTORY );
  179. data << unit->GetGUID();
  180. data << uint8( 0 ); // placeholder for item count
  181.  
  182. uint32 counter = 0;
  183.  
  184. ItemPrototype * curItem;
  185.  
  186. for( vector<uint32>::iterator itr = items->begin(); itr != items->end(); itr++ )
  187. {
  188. curItem = ItemPrototypeStorage.LookupEntry(*itr);
  189.  
  190. if(curItem->AllowableClass && !(plr->getClassMask() & curItem->AllowableClass))
  191. continue;
  192. if(curItem->AllowableRace && !(plr->getRaceMask() & curItem->AllowableRace))
  193. continue;
  194. if(curItem->RequiredSkill && plr->_HasSkillLine(curItem->RequiredSkill) && plr->_GetSkillLineCurrent( curItem->RequiredSkill ) < curItem->RequiredSkillRank )
  195. continue;//Only show useable recipes.
  196.  
  197. data << (counter + 1);//Count
  198. data << curItem->ItemId;//Item id
  199. data << curItem->DisplayInfoID;//Display id
  200. data << int32(-1);//Available amount
  201. data << curItem->BuyPrice;//Buyprice
  202. data << int32(-1); // ???
  203. data << curItem->MaxCount;
  204.  
  205. if( Extended_Cost_List[ curItem->ItemId ] )
  206. data << Extended_Cost_List[ curItem->ItemId ];
  207. else
  208. data << uint32(0);//Extended cost
  209.  
  210. if( counter == 150 )//15 pages is enough, eh?
  211. break;
  212. ++counter;
  213. }
  214.  
  215. const_cast<uint8*>(data.contents())[8] = (uint8)counter; // set count
  216.  
  217. if( plr->GetSession() )
  218. plr->GetSession()->SendPacket( &data );
  219.  
  220. if( !counter )
  221. unit->SendChatMessageToPlayer(15, 0, "I could not find an item available for your race and class.", plr);//Whisper, in universal language.
  222. }
  223.  
  224. bool stringtest( string thing )//Tests whether a string consists SOLELY of numbers or not. returns true if the string is all numbers.
  225. {
  226. char str[256];
  227. 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.
  228. return str == thing;
  229. }
  230.  
  231. bool TestItem( ItemPrototype * it )
  232. {
  233. if( !it )
  234. return false;
  235.  
  236. if( IsCustom(it->ItemId) )
  237. return false;
  238.  
  239. if( !(ALLOW_ITEM_SETS) && it->ItemSet )//item sets
  240. return false;
  241.  
  242. if( ( ( !(ALLOW_FREE) && (!it->BuyPrice) || it->BuyPrice < it->SellPrice) ) && !Extended_Cost_List[ it->ItemId ] )// free / sell for more than bought and no extended cost
  243. return false;
  244.  
  245. if( it->Quality > MAX_QUALITY )//quality
  246. return false;
  247.  
  248. if( (!(ALLOW_QUEST) && it->Flags & ITEM_FLAG_QUEST) || (!(ALLOW_CONJURED) && it->Flags & ITEM_FLAG_CONJURED) )//quest / conjured
  249. return false;
  250.  
  251. if( !(ALLOW_QUEST) && it->QuestId )//Quest again
  252. return false;
  253.  
  254. if( banned_items[ it->ItemId ] )
  255. return false;
  256.  
  257. return true;
  258. }
  259.  
  260. bool TestItemEntry( uint32 entry )
  261. {
  262. if( IsCustom(entry) )
  263. return false;
  264. return TestItem( ItemPrototypeStorage.LookupEntry(entry) );
  265. }
  266.  
  267. void FindItem( UnitPointer unit, PlayerPointer plr, const char* nameC, vector<uint32> &items )
  268. {
  269.  
  270. string name( nameC );
  271.  
  272. int itemid = atoi(name.c_str());
  273. if( itemid && !(itemid==INT_MIN || itemid==INT_MAX) && stringtest(name) )
  274. {
  275. ItemPrototype * it = ItemPrototypeStorage.LookupEntry(itemid);//If it's just an item id, no point in using SQL. eh?
  276.  
  277. if( it && TestItem(it) )
  278. items.push_back(it->ItemId);
  279.  
  280. if( !items.size() )
  281. 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.
  282.  
  283. return;
  284. }
  285.  
  286. string x = name;
  287. HEARTHSTONE_TOLOWER(x);
  288.  
  289. while( x.find("%") != string::npos )
  290. x.erase( x.find("%") );//Remove wildcard characters.
  291.  
  292. if(x.length() < 3)
  293. {
  294. unit->SendChatMessageToPlayer(15, 0, "Please enter a name 4 or more letters in length.", plr);
  295. return;
  296. }
  297.  
  298. ItemPrototype * it;
  299. uint32 count = 0;
  300.  
  301. QueryResult * result = WorldDatabase.Query("SELECT entry FROM items WHERE quality <= %u %s AND name1 like '%s' ORDER BY quality DESC, class, subclass LIMIT %u", MAX_QUALITY, ((ALLOW_ITEM_SETS) ? "" : "AND itemset = 0") ,("%" + WorldDatabase.EscapeString(x) + "%").c_str(), MAX_RESULTS );
  302.  
  303. if( !result )
  304. {
  305. unit->SendChatMessageToPlayer(15, 0, "I'm sorry, I could not find your item. Please check the name and try again.", plr);
  306. return;
  307. }
  308.  
  309. do
  310. {
  311. uint32 entry = result->Fetch()[0].GetUInt32();
  312. it = ItemPrototypeStorage.LookupEntry( entry );
  313.  
  314. if( !it || !TestItem(it) )
  315. continue;
  316.  
  317. items.push_back(it->ItemId);
  318. } while (result->NextRow());
  319.  
  320. delete result;
  321.  
  322. if( !items.size() )
  323. unit->SendChatMessageToPlayer(15, 0, "I'm sorry, that item is unavailable for purchase.", plr);
  324.  
  325. return;
  326. }
  327.  
  328. void HandleRecipes(ObjectPointer pObject, PlayerPointer plr, uint32 Id, uint32 IntId, const char * Code)
  329. {
  330. GossipMenu *Menu;
  331. objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 44333225, plr);
  332.  
  333.  
  334. Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Alchemy Recipes", vector_map_map["Alchemy Recipes"]);
  335. Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Blacksmithing Recipes", vector_map_map["Blacksmithing Recipes"]);
  336. Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Cooking Recipes", vector_map_map["Cooking Recipes"]);
  337. Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Enchanting Recipes", vector_map_map["Enchanting Recipes"]);
  338. Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Engineering Recipes", vector_map_map["Engineering Recipes"]);
  339. Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Jewelcrafting Recipes", vector_map_map["Jewelcrafting Recipes"]);
  340. //Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Inscription Recipes", vector_map_map["Inscription Recipes"]);
  341. Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Leatherworking Recipes", vector_map_map["Leatherworking Recipes"]);
  342. Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Tailoring Recipes", vector_map_map["Tailoring Recipes"]);
  343.  
  344.  
  345. Menu->AddItem( 7, "[Back]", 1055);
  346.  
  347. Menu->SendTo(plr);
  348.  
  349. }
  350.  
  351.  
  352. void HandleArmor(ObjectPointer pObject, PlayerPointer plr, uint32 Id, uint32 IntId, const char * Code)
  353. {
  354.  
  355. if( IntId > 200 )
  356. {
  357. vector<uint32> *vpointer = armor_map[ IntId ];//Just because references must be initialized.
  358.  
  359. AddItemsToCreature( TO_CREATURE(pObject), vpointer );
  360. SendItemList( TO_CREATURE(pObject), plr, vpointer );//Show the weapons.
  361. return;
  362. }
  363.  
  364. GossipMenu *Menu;
  365. objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 44333225, plr);
  366.  
  367. uint32 armor_class;
  368.  
  369. switch( plr->getClass() )
  370. {
  371. case DEATHKNIGHT:
  372. case WARRIOR:
  373. case PALADIN:
  374. armor_class = armor_PLATE;
  375. break;
  376. case HUNTER:
  377. case SHAMAN:
  378. armor_class = armor_MAIL;
  379. break;
  380. case DRUID:
  381. case ROGUE:
  382. armor_class = armor_LEATHER;
  383. break;
  384. default:
  385. armor_class = armor_CLOTH;
  386. }
  387.  
  388. Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Helms", 200 + ((armor_class + 1) * 10));
  389. Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Cloaks", vector_map_map["Cloaks"]);
  390. Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Shoulders", 200 + ((armor_class + 1) * 10) + 1);
  391. Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Chestpieces", 200 + ((armor_class + 1) * 10) + 2);
  392. Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Wristguards", 200 + ((armor_class + 1) * 10) + 3);
  393. Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Gloves", 200 + ((armor_class + 1) * 10) + 4);
  394. Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Waistbelts", 200 + ((armor_class + 1) * 10) + 5);
  395. Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Leggings", 200 + ((armor_class + 1) * 10) + 6);
  396. Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Boots", 200 + ((armor_class + 1) * 10) + 7);
  397. Menu->AddItem( GOSSIP_ICON_GOSSIP_AUCTION, "Necklaces", vector_map_map["Necklaces"]);
  398. Menu->AddItem( GOSSIP_ICON_GOSSIP_AUCTION, "Rings", vector_map_map["Rings"]);
  399. Menu->AddItem( GOSSIP_ICON_GOSSIP_AUCTION, "Trinkets", vector_map_map["Trinkets"]);
  400. Menu->AddItem( GOSSIP_ICON_GOSSIP_ARENA, "Shields", vector_map_map["Shields"]);
  401. Menu->AddItem( GOSSIP_ICON_GOSSIP_ARENA, "Offhands", vector_map_map["Offhands"]);
  402. Menu->AddItem( GOSSIP_ICON_GOSSIP_TABARD, "Tabards", vector_map_map["Tabards"]);
  403.  
  404. switch( plr->getClass() )
  405. {
  406. case DEATHKNIGHT:
  407. Menu->AddItem( GOSSIP_ICON_GOSSIP_AUCTION, "Sigils", vector_map_map["Sigils"]);
  408. break;
  409. case DRUID:
  410. Menu->AddItem( GOSSIP_ICON_GOSSIP_AUCTION, "Idols", vector_map_map["Idols"]);
  411. break;
  412. case SHAMAN:
  413. Menu->AddItem( GOSSIP_ICON_GOSSIP_AUCTION, "Totems", vector_map_map["Totems"]);
  414. break;
  415. case PALADIN:
  416. Menu->AddItem( GOSSIP_ICON_GOSSIP_AUCTION, "Librams", vector_map_map["Librams"]);
  417. break;
  418. default:
  419. break;
  420. }
  421.  
  422.  
  423. Menu->AddItem( 7, "[Back]", 1055);
  424.  
  425. Menu->SendTo(plr);
  426.  
  427. }
  428.  
  429. void HandleWeapons(ObjectPointer pObject, PlayerPointer plr, uint32 Id, uint32 IntId, const char * Code)
  430. {
  431.  
  432. GossipMenu *Menu;
  433. objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 44333225, plr);
  434.  
  435. Menu->AddItem( 9, "Two-Handed Swords", vector_map_map["Two-Handed Swords"]);
  436. Menu->AddItem( 9, "Two-Handed Maces", vector_map_map["Two-Handed Maces"]);
  437. Menu->AddItem( 9, "Two-Handed Axes", vector_map_map["Two-Handed Axes"]);
  438. Menu->AddItem( 9, "Polearms", vector_map_map["Polearms"]);
  439. Menu->AddItem( 9, "Staves", vector_map_map["Staves"]);
  440.  
  441. Menu->AddItem( 6, "One-Handed Swords", vector_map_map["One-Handed Swords"]);
  442. Menu->AddItem( 6, "One-Handed Maces", vector_map_map["One-Handed Maces"]);
  443. Menu->AddItem( 6, "One-Handed Axes", vector_map_map["One-Handed Axes"]);
  444. Menu->AddItem( 6, "Daggers", vector_map_map["Daggers"]);
  445. Menu->AddItem( 6, "Fist Weapons", vector_map_map["Fist Weapons"]);
  446.  
  447. Menu->AddItem( 2, "Guns", vector_map_map["Guns"]);
  448. Menu->AddItem( 2, "Bows", vector_map_map["Bows"]);
  449. Menu->AddItem( 2, "Crossbows", vector_map_map["Crossbows"]);
  450. Menu->AddItem( 2, "Wands", vector_map_map["Wands"]);
  451. Menu->AddItem( 2, "Thrown",vector_map_map["Thrown"]);
  452.  
  453. Menu->AddItem( 7, "[Back]", 1055);
  454.  
  455. Menu->SendTo(plr);
  456.  
  457. }
  458.  
  459. CreaturePointer make_creature( PlayerPointer plr )
  460. {
  461. float angle = -(3.14159265) / 3;
  462. CreatureProto * proto = CreatureProtoStorage.LookupEntry( NPC_ID + RandomUInt(3) );
  463. CreatureInfo * info = CreatureNameStorage.LookupEntry( NPC_ID + RandomUInt(3) );
  464.  
  465. LocationVector v = plr->GetPositionNC();
  466. float m_followAngle = angle + v.o;
  467. float x = v.x +(3*(cosf(m_followAngle)));
  468. float y = v.y +(3*(sinf(m_followAngle)));
  469. CreaturePointer p = plr->GetMapMgr()->CreateCreature(NPC_ID);
  470. p->SetInstanceID(plr->GetMapMgr()->GetInstanceID());
  471. p->Load(proto, x, y, v.z, angle);//Fix falling thru ground bug.
  472.  
  473. p->SetZoneId(plr->GetZoneId());
  474.  
  475. p->GetAIInterface()->Init(p,AITYPE_PET,MOVEMENTTYPE_NONE,plr);
  476. p->GetAIInterface()->SetUnitToFollow(plr);
  477. p->GetAIInterface()->SetUnitToFollowAngle(angle);
  478. p->GetAIInterface()->SetFollowDistance(3.0f);
  479.  
  480. p->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,35);//Players will see them as green, even though they're actually neutral.
  481. p->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9);
  482.  
  483. p->SetUInt32Value(UNIT_FIELD_DISPLAYID, BOT_BLANK );
  484. p->SetFloatValue( OBJECT_FIELD_SCALE_X, 1.1f );//To make him a reasonable size. Otherwise he would be 0.7f
  485. p->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, plr->GetGUID() );
  486. //p->SetUInt64Value( UNIT_FIELD_CREATEDBY, plr->GetGUID() );
  487. //p->SetUInt64Value(UNIT_FIELD_CBY, plr->GetGUID());
  488.  
  489. p->SetUInt32Value( UNIT_FIELD_HEALTH, 5000 );//Set combat stats. For pet combat :D
  490. p->SetUInt32Value( UNIT_FIELD_MAXHEALTH, 5000 );
  491. p->SetUInt32Value( UNIT_FIELD_BASEATTACKTIME, 2000 + RandomUInt(100) );
  492. p->SetFloatValue( UNIT_FIELD_MINDAMAGE, 100 );
  493. p->SetFloatValue( UNIT_FIELD_MAXDAMAGE, 700 );
  494. for( uint32 i = 0; i < 9; i++ )
  495. p->SetUInt32Value( UNIT_FIELD_RESISTANCES + i, 0 );//the stationary version has all resistances 666, so let's set this to 0.
  496.  
  497.  
  498. p->PushToWorld(plr->GetMapMgr());
  499.  
  500. p->GetAIInterface()->MoveTo( v.x +(2.9*(cosf(m_followAngle))), v.y +(2.9*(sinf(m_followAngle))), v.z, angle);//Hackkkk
  501.  
  502. #if ARCEMU == 0
  503. plr->m_SummonSlots[ 6 ] = p;
  504. #endif
  505.  
  506. return p;
  507. }
  508.  
  509. class SCRIPT_DECL AutoItemMall : public GossipScript
  510. {
  511. public:
  512.  
  513. void GossipHello(ObjectPointer pObject, PlayerPointer plr, bool AutoSend)
  514. {
  515.  
  516. if( pObject->GetTypeId() == TYPEID_ITEM )
  517. {
  518.  
  519. if( !plr->Cooldown_CanCast(ItemPrototypeStorage.LookupEntry(ITEM_ID), 0) || !plr->Cooldown_CanCast(ItemPrototypeStorage.LookupEntry(ITEM_ID), 1) )
  520. {
  521. if( plr->GetSession() )
  522. plr->GetSession()->SendNotification("Your bot is still recharging!");
  523. return;
  524. }
  525.  
  526. for (Object::InRangeSet::iterator itr = plr->GetInRangeSetBegin(); itr != plr->GetInRangeSetEnd(); ++itr)
  527. {
  528. if( (*itr)->IsCreature() && TO_CREATURE(*itr)->GetEntry() >= NPC_ID && TO_CREATURE(*itr)->GetEntry() <= (NPC_ID+3) && (*itr)->GetUInt64Value( UNIT_FIELD_SUMMONEDBY ) == plr->GetGUID() )
  529. {
  530. if( TO_CREATURE(*itr)->CombatStatus.IsInCombat() )
  531. {
  532. string strings[3] = {"Can't you see I'm busy?", "Wait, I almost have this guy...", "You can't put me away now, I'm fighting!"};
  533. TO_CREATURE(*itr)->SendChatMessageToPlayer(15, 0, strings[RandomUInt(2)].c_str(), plr);
  534. return;
  535. }
  536. TO_CREATURE(*itr)->SendChatMessageToPlayer(15, 0, "Goodbye!", plr);
  537. TO_CREATURE(*itr)->SummonExpire();
  538. ItemPrototype * ip = ItemPrototypeStorage.LookupEntry(ITEM_ID);
  539.  
  540. plr->Cooldown_AddItem( ip, 1);//Yay cooldowns!
  541. return;
  542. }
  543. }//Despawn existing vendors, if found.
  544.  
  545. CreaturePointer VendorPersonal = make_creature( plr );
  546. plr_items[ VendorPersonal->GetGUID() ] = TO_ITEM(pObject);
  547.  
  548. VendorPersonal->SendChatMessageToPlayer(15, 0, "Thank you for summoning me! I'm your personal vendor, here for your assistance!", plr);
  549.  
  550. return;
  551. }
  552.  
  553. if( TO_CREATURE(pObject)->CombatStatus.IsInCombat() )
  554. return;
  555.  
  556. if( pObject->GetUInt64Value( UNIT_FIELD_SUMMONEDBY ) > 0 && pObject->GetUInt64Value( UNIT_FIELD_SUMMONEDBY ) != plr->GetGUID() )
  557. {
  558. string strings[3] = {"You don't own me!", "My master says not to talk to strangers...", "I only talk to my master!"};
  559. TO_UNIT(pObject)->SendChatMessageToPlayer(15, 0, strings[RandomUInt(2)].c_str(), plr);
  560. return;
  561. }
  562.  
  563. GossipMenu *Menu;
  564. objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 44333225, plr);
  565.  
  566. if( ENABLE_ITEM_SEARCHING )
  567. {
  568. #if ARCEMU == 0
  569. Menu->AddItem( 1, "Search for an item to purchase.", 1, true);
  570. #else
  571. Menu->AddItem( 1, "Search for an item to purchase.", 1, 1);
  572. #endif
  573. }
  574.  
  575.  
  576. #if ENABLE_MALL_MENU > 0
  577. Menu->AddItem( 9, "Weapons", 100);
  578. Menu->AddItem( 9, "Armor", 200);
  579. Menu->AddItem( 3, "Professions", 334);
  580. Menu->AddItem( 2, "Mounts", vector_map_map["Mounts"]);
  581. Menu->AddItem( 2, "Personal Pets", vector_map_map["Personal Pets"]);
  582. Menu->AddItem( 1, "Bags", vector_map_map["Bags"]);
  583.  
  584. #endif
  585.  
  586. if( ENABLE_ITEM_SEARCHING )
  587. Menu->AddItem( 0, "How does this Mall work?", 99);
  588.  
  589. #if ENABLE_BOT_FIGHTS > 0
  590. if( pObject->GetUInt64Value( UNIT_FIELD_SUMMONEDBY )==plr->GetGUID() && pObject->GetUInt32Value(UNIT_FIELD_DISPLAYID) == BOT_BLANK )//We're a bot, and we're not flagged yet.
  591. Menu->AddItem( 9, "|cffff0000Let Me Fight!", 69);
  592. if( pObject->GetUInt64Value( UNIT_FIELD_SUMMONEDBY )==plr->GetGUID() && pObject->GetUInt32Value(UNIT_FIELD_DISPLAYID) == BOT_RED )//We're a red bot.
  593. Menu->AddItem( 9, "|cff0099FFSwitch Fuels!", 70);
  594. if( pObject->GetUInt64Value( UNIT_FIELD_SUMMONEDBY )==plr->GetGUID() && pObject->GetUInt32Value(UNIT_FIELD_DISPLAYID) == BOT_BLUE )//We're a blue bot! :O
  595. Menu->AddItem( 9, "|cffff0000Switch Fuels!", 71);
  596. #endif
  597.  
  598. if(AutoSend)
  599. Menu->SendTo(plr);
  600. }
  601.  
  602. void GossipSelectOption(ObjectPointer pObject, PlayerPointer plr, uint32 Id, uint32 IntId, const char * Code)
  603. {
  604. if( TO_CREATURE(pObject)->CombatStatus.IsInCombat() )
  605. {
  606. TO_UNIT(pObject)->SendChatMessageToPlayer(15, 0, "Can't you see I'm busy right now?", plr);
  607. plr->Gossip_Complete();
  608. return;
  609. }
  610.  
  611. if( IntId >= 500 && IntId < 1000 )
  612. {
  613. vector<uint32> *vpointer = vector_map[ IntId ];
  614. AddItemsToCreature( TO_CREATURE(pObject), vpointer );
  615. SendItemList( TO_CREATURE(pObject), plr, vpointer );//Show them.
  616. return;
  617. }
  618.  
  619. if( IntId >= 100 && IntId < 200 )
  620. {
  621. HandleWeapons( pObject, plr, Id, IntId, Code );
  622. return;
  623. }
  624. else if( IntId >= 200 && IntId < 300 )
  625. {
  626. HandleArmor( pObject, plr, Id, IntId, Code );
  627. return;
  628. }
  629.  
  630.  
  631. switch (IntId)
  632. {
  633.  
  634. case 69:
  635. case 70:
  636. case 71:
  637. {
  638. plr->Gossip_Complete();
  639. string message = "";
  640. uint32 new_model;
  641. if( pObject->GetUInt32Value( UNIT_FIELD_DISPLAYID) == BOT_BLUE )
  642. new_model = BOT_RED;
  643. if( pObject->GetUInt32Value( UNIT_FIELD_DISPLAYID) == BOT_RED )
  644. new_model = BOT_BLUE;
  645. if( pObject->GetUInt32Value( UNIT_FIELD_DISPLAYID) == BOT_BLANK )
  646. {
  647. new_model = RandomUInt(1) ? BOT_RED : BOT_BLUE;
  648. message = "Time to kick some ass!";
  649. }
  650. pObject->SetUInt32Value( UNIT_FIELD_DISPLAYID, new_model );
  651. if( message != "" )
  652. TO_UNIT(pObject)->SendChatMessageToPlayer(15, 0, message.c_str(), plr);
  653.  
  654. TO_UNIT(pObject)->CastSpell(TO_UNIT(pObject), pObject->GetUInt32Value( UNIT_FIELD_DISPLAYID) == BOT_BLUE ? 36881 : 43045, true);
  655. #if ARCEMU==0
  656. //Something screwed up with aspire AI
  657. TO_UNIT(pObject)->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, pObject->GetUInt32Value( UNIT_FIELD_DISPLAYID) == BOT_BLUE ? 189 : 35);//189 = neutral, all-attackable faction, fix for aspire not being able to fight each other.
  658. TO_UNIT(pObject)->_setFaction();
  659. TO_UNIT(pObject)->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,35);//Players will see them as green, even though they're actually neutral (if they're blue, at least)
  660. #endif
  661.  
  662. }break;
  663. case 334://Random numbers. lol. whatever.
  664. {
  665. HandleRecipes( pObject, plr, Id, IntId, Code );
  666. }break;
  667. case 1055://Back
  668. {
  669. GossipHello(pObject, plr, true);
  670. }break;
  671. case 99://Help pl0x
  672. {
  673. TO_UNIT(pObject)->SendChatMessageToPlayer(15, 0, "This vendor is an \"All-In-One\" mall vendor.", plr);
  674. TO_UNIT(pObject)->SendChatMessageToPlayer(15, 0, "Simply click on one of the options above to view my list of items, or click the \"search\" option and enter the |cffff33ffname|r of the item you're looking for.", plr);
  675.  
  676. GossipHello(pObject, plr, true);
  677. }break;
  678.  
  679. case 1://We're looking for an item.
  680. {
  681. vector<uint32> items;
  682. FindItem(TO_UNIT(pObject), plr, Code, items);
  683. if( !items.size() )
  684. {
  685. GossipHello(pObject, plr, true);
  686. return;
  687. }
  688.  
  689. AddItemsToCreature( TO_CREATURE( pObject ), &items, false );//Add the items to the creature's Mall list, so the player can actually buy the items instead of just view them
  690.  
  691. SendItemList( TO_CREATURE(pObject), plr, &items );//Show him the list of items.
  692.  
  693. items.clear();
  694. }break;
  695.  
  696. }
  697. }
  698.  
  699. void GossipEnd(ObjectPointer pObject, PlayerPointer Plr)
  700. {
  701. TO_UNIT(pObject)->SendChatMessageToPlayer(15, 0, "Thank you for using the Auto Mall. Please Come Again!", Plr);//If you want, you may as well add your own message about voting on your server's website or somethin.
  702. Plr->CleanupGossipMenu();
  703. }
  704.  
  705. void Destroy()
  706. {
  707. delete this;
  708. }
  709. };
  710.  
  711. void LoadItemsFromQuery( char* query, vector<uint32> *items, bool test )
  712. {
  713. if( !query || query == "" )
  714. return;
  715.  
  716. QueryResult* result = WorldDatabase.Query(query);
  717. if( !result )
  718. printf("\n(Auto Mall): Note: Query: %s was empty (Ignore this if you're not a developer).\n", query);
  719. else
  720. {
  721. items->reserve(result->GetRowCount());//Optimization.
  722. do
  723. {
  724. uint32 id = result->Fetch()[0].GetUInt32();
  725.  
  726. if( IsCustom(id) )
  727. continue;
  728.  
  729. if( !test || TestItemEntry( id ) )
  730. items->push_back( id );
  731.  
  732. } while (result->NextRow());
  733. delete result;
  734. }
  735.  
  736. }
  737.  
  738. void LoadItemsFromQuery2( char* query, string label, bool test )
  739. {
  740. vector_map[counter] = new vector<uint32>;
  741. LoadItemsFromQuery(query, vector_map[counter], test);
  742. vector_map_map[label] = counter;
  743. counter++;
  744. }
  745.  
  746. void LoadArmorFromQuery( string subclass, string slot, vector<uint32> * items )
  747. {
  748. string query = "SELECT entry FROM items WHERE class = 4 AND subclass = " + subclass + " AND inventorytype = " + slot + " AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC";
  749.  
  750. char * queryC;
  751. queryC = new char[query.length() + 1];
  752. strcpy(queryC, query.c_str());//This is to convert from const char* (.c_str() returns const char) to char*
  753.  
  754. LoadItemsFromQuery( queryC, items, true );
  755.  
  756. delete[] queryC;//Free.
  757. }
  758.  
  759. void LoadItemTables()
  760. {
  761. QueryResult * result;
  762.  
  763. WorldDatabase.Execute("DELETE FROM creature_spawns WHERE entry >= %u AND entry <= (%u + 3) AND (displayid = 29279 or displayid = 29280 or displayid = 29281);", NPC_ID, NPC_ID);//Just clean this up.
  764.  
  765. if( ENABLE_EXTENDED_COSTS )
  766. {
  767. #if ARCEMU==0
  768. result = WorldDatabase.Query("SELECT DISTINCT item, extendedcost FROM vendors WHERE extendedcost > 1");//1 because of a bug with crappy DBs
  769. #else
  770. result = WorldDatabase.Query("SELECT DISTINCT item, extended_cost FROM vendors WHERE extended_cost > 1");//1 because of a bug with crappy DBs
  771. #endif
  772. if( !result )
  773. printf("(Auto Mall): Error loading extended costs.");
  774. else
  775. {
  776. do
  777. {
  778. uint32 id = result->Fetch()[0].GetUInt32();
  779. uint32 ec = result->Fetch()[1].GetUInt32();
  780. if( dbcItemExtendedCost.LookupEntryForced(ec) )
  781. Extended_Cost_List[ id ] = ec;
  782.  
  783. } while (result->NextRow());
  784. delete result;
  785. }
  786. }
  787.  
  788. if( ENABLE_ITEM_BANNING )
  789. {
  790. result = WorldDatabase.Query("SELECT * FROM mall_banned_items");
  791. if( !result )
  792. printf("(Auto Mall): Error loading banned items.");
  793. else
  794. {
  795. do
  796. {
  797. banned_items[ result->Fetch()[0].GetUInt32() ] = true;
  798. } while (result->NextRow());
  799.  
  800. delete result;
  801. }
  802. }
  803.  
  804. if( ENABLE_MALL_MENU )
  805. {
  806. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 15 AND subclass = 5 ORDER BY quality DESC, buyprice DESC", "Mounts", true );//Mounts
  807. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 15 AND (subclass = 2 or description = 'Teaches you how to summon this companion.') and description != '' ORDER BY quality DESC", "Personal Pets", false );//Pets
  808. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 2 AND subclass = 7 AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "One-Handed Swords", true );
  809. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 2 AND subclass = 8 AND requiredlevel >= 71 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Two-Handed Swords", true );
  810. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 2 AND subclass = 4 AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "One-Handed Maces", true );
  811. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 2 AND subclass = 5 AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Two-Handed Maces", true );
  812. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 2 AND subclass = 0 AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "One-Handed Axes", true );
  813. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 2 AND subclass = 1 AND requiredlevel >= 71 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Two-Handed Axes", true );
  814. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 2 AND subclass = 6 AND requiredlevel >= 71 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Polearms", true );
  815. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 2 AND subclass = 10 AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Staves", true );
  816. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 2 AND subclass = 19 AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Wands", true );
  817. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 2 AND subclass = 3 AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Guns", true );
  818. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 2 AND subclass = 2 AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Bows", true );
  819. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 2 AND subclass = 18 AND requiredlevel >= 71 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Crossbows", true );
  820. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 2 AND subclass = 13 AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Fist Weapons", true );
  821. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 2 AND subclass = 16 AND requiredlevel >= 71 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Thrown", true );
  822. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 2 AND subclass = 15 AND requiredlevel >= 71 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Daggers", true );
  823. LoadItemsFromQuery2( "SELECT entry FROM items WHERE containerslots > 16 AND quality >= 2 ORDER BY subclass, containerslots DESC", "Bags", true );
  824.  
  825.  
  826. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 6 ORDER BY quality DESC, RequiredSkillRank DESC", "Alchemy Recipes", true );
  827. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 4 ORDER BY quality DESC, RequiredSkillRank DESC", "Blacksmithing Recipes", true );
  828. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 5 ORDER BY quality DESC, RequiredSkillRank DESC", "Cooking Recipes", true );
  829. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 8 ORDER BY quality DESC, RequiredSkillRank DESC", "Enchanting Recipes", true );
  830. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 3 ORDER BY quality DESC, RequiredSkillRank DESC", "Engineering Recipes", true );
  831. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 2 ORDER BY quality DESC, RequiredSkillRank DESC", "Tailoring Recipes", true );
  832. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 1 ORDER BY quality DESC, RequiredSkillRank DESC", "Leatherworking Recipes", true );
  833. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 10 ORDER BY quality DESC, RequiredSkillRank DESC", "Jewelcrafting Recipes", true );
  834.  
  835. for( uint8 i = 0; i <= armor_PLATE; i++ )
  836. {
  837. armor_struc &armor_local = armor[i];
  838. string strings[4]= {"1", "2", "3", "4"};
  839. string subclass = strings[i];
  840. LoadArmorFromQuery( subclass, "1", &armor_local.head );
  841. LoadArmorFromQuery( subclass, "3", &armor_local.shoulder );
  842. LoadArmorFromQuery( subclass, "5", &armor_local.body );
  843. LoadArmorFromQuery( subclass, "20", &armor_local.body );
  844. LoadArmorFromQuery( subclass, "9", &armor_local.wrist );
  845. LoadArmorFromQuery( subclass, "6", &armor_local.waist );
  846. LoadArmorFromQuery( subclass, "10", &armor_local.hands );
  847. LoadArmorFromQuery( subclass, "7", &armor_local.legs );
  848. LoadArmorFromQuery( subclass, "8", &armor_local.feet );
  849. }
  850.  
  851. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND subclass = 1 AND inventorytype = 16 AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Cloaks", true);
  852. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND subclass = 0 AND inventorytype = 11 AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Rings", true);
  853. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND subclass = 0 AND inventorytype = 12 AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Trinkets", true);
  854. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND subclass = 6 AND inventorytype = 14 AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Shields", true);
  855. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND subclass = 0 AND inventorytype = 23 AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Offhands", true);
  856. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND subclass = 0 AND inventorytype = 2 AND requiredlevel >= 75 AND quality >= 3 ORDER BY quality DESC, itemlevel DESC", "Necklaces", true);
  857. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND inventorytype = 19 ORDER BY quality DESC, itemlevel DESC", "Tabards", false );
  858.  
  859. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND subclass = 7 ORDER BY quality DESC, itemlevel DESC", "Librams", true );
  860. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND subclass = 8 ORDER BY quality DESC, itemlevel DESC", "Idols", true );
  861. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND subclass = 10 ORDER BY quality DESC, itemlevel DESC", "Sigils", true );
  862. LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND subclass = 9 ORDER BY quality DESC, itemlevel DESC", "Totems", true );
  863.  
  864.  
  865.  
  866. //all the items are loaded!! Let's go!
  867.  
  868. uint32 counter2 = 200;
  869. uint32 counter;
  870. for( uint32 i = 0; i < 4; i++ )
  871. {
  872. counter2 += 10;
  873. counter = counter2;
  874. armor_map[ counter++ ] = &armor[i].head;
  875. armor_map[ counter++ ] = &armor[i].shoulder;
  876. armor_map[ counter++ ] = &armor[i].body;
  877. armor_map[ counter++ ] = &armor[i].wrist;
  878. armor_map[ counter++ ] = &armor[i].hands;
  879. armor_map[ counter++ ] = &armor[i].waist;
  880. armor_map[ counter++ ] = &armor[i].legs;
  881. armor_map[ counter++ ] = &armor[i].feet;
  882. }
  883.  
  884. SpellEntry* sp = dbcSpell.LookupEntryForced(43045);
  885. if( sp )
  886. sp->Effect[2] = 0;//Prevent crash.
  887.  
  888. }
  889.  
  890. }
  891.  
  892. class VendorHook : public CreatureAIScript
  893. {
  894. public:
  895. ADD_CREATURE_FACTORY_FUNCTION(VendorHook);
  896.  
  897. VendorHook(CreaturePointer pCreature) : CreatureAIScript(pCreature)
  898. {
  899. CItems[ _unit->GetGUID() ] = new set<uint32>;
  900. CMenusList[ _unit->GetGUID() ] = new set<vector<uint32>*>;
  901. attack_strings[0] = "C'mere, you little...";
  902. attack_strings[1] = "I'll show you!";
  903. attack_strings[2] = "Finally, some action!";
  904.  
  905. bored_strings[0] = "I'm bored...";//Bored messages.
  906. bored_strings[1] = "This is boring!";
  907. bored_strings[2] = "Don't just stand there, do something!";
  908. bored_strings[3] = "Why are you just standing there?";
  909. bored_strings[4] = "Hey, wanna go get some of this? |cff00ff00|TInterface\\icons\\INV_MISC_FIREDANCER_01:48|t|r";
  910. bored_strings[5] = "I'm made for selling, not standing around!";
  911.  
  912. bored_strings[6] = "I'm outta here. Bye!";//Exit messages.
  913. bored_strings[7] = "This is too boring for me. Cya!";
  914. bored_strings[8] = "You can have fun standing there if you want, but I'm gonna go do something else.";
  915.  
  916. last_move = getMSTime();
  917. last_spoke = getMSTime();
  918. x = y = z = 0.0f;
  919. RegisterAIUpdateEvent( 2000 );//Once every 2 seconds is plenty. No high CPU usage. at all. -- creature AI updates much more often than this.
  920. }
  921.  
  922. ~VendorHook()
  923. {
  924. last_move = 0;
  925. last_spoke = 0;
  926. CMenusList[ _unit->GetGUID() ]->clear();
  927. CItems[ _unit->GetGUID() ]->clear();
  928.  
  929. delete CMenusList[ _unit->GetGUID() ];
  930. delete CItems[ _unit->GetGUID() ];
  931.  
  932. CMenusList[ _unit->GetGUID() ] = NULL;
  933. CItems[ _unit->GetGUID() ] = NULL;
  934. plr_items.erase( _unit->GetGUID() );
  935. }
  936.  
  937. void OnDied( UnitPointer killer )
  938. {
  939. #if ARCEMU > 0
  940. for (std::set<PlayerPointer>::iterator itr = _unit->GetInRangePlayerSetBegin(); itr != _unit->GetInRangePlayerSetEnd(); ++itr)
  941. {
  942. #else
  943. for(unordered_set<PlayerPointer>::iterator itr = _unit->GetInRangePlayerSetBegin(); itr != _unit->GetInRangePlayerSetEnd(); ++itr)
  944. {
  945. #endif
  946. if( (*itr)->GetGUID() == _unit->GetUInt64Value( UNIT_FIELD_SUMMONEDBY ) )
  947. {
  948.  
  949. ItemPrototype * ip = ItemPrototypeStorage.LookupEntry(ITEM_ID);
  950.  
  951. #if ARCEMU==0
  952. SpellPointer spell(new Spell((*itr), dbcSpell.LookupEntryForced( ip->Spells[0].Id ), false, NULLAURA));
  953. #else
  954. SpellPointer spell(new Spell((*itr), dbcSpell.LookupEntryForced( ip->Spells[0].Id ), false, NULL));
  955.  
  956. #endif
  957. spell->i_caster = plr_items[_unit->GetGUID()];
  958. SpellCastTargets target(0);
  959. target.m_targetMask |= TARGET_FLAG_UNIT;
  960. target.m_unitTarget = (*itr)->GetGUID();
  961. spell->prepare(&target);
  962.  
  963.  
  964. TO_PLAYER(*itr)->Cooldown_AddItem( ip, 0);//Yay cooldowns!
  965. break;
  966. }
  967. }
  968.  
  969. _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "AHHHHH!");
  970. RemoveAIUpdateEvent();
  971. _unit->SummonExpire();
  972. if( killer->isAlive() )
  973. {
  974. killer->CastSpell( killer, 55420, true);//Fireworks for the winner! yay
  975. #if ARCEMu==0
  976. //Aspire: need to regenerate the bots. arcemu, they regen fine.
  977. killer->SetUInt32Value(UNIT_FIELD_HEALTH, 5000);
  978. killer->SetUInt32Value(UNIT_FIELD_POWER1, 99999);
  979. #endif
  980. }
  981. }
  982.  
  983. void Say_Bored()
  984. {
  985. if( getMSTime() > (last_move + 1000*60*15) && !RandomUInt(20))//Our owner is AFK for more than 15 minutes. Despawn us. (So we don't just keep spamming bored messages.)
  986. {
  987. _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, bored_strings[RandomUInt(2) + 6].c_str());
  988. _unit->SummonExpire();
  989. return;
  990. }
  991. if( getMSTime() < (last_move + 1000*60*7) || getMSTime() < (last_spoke + 1000*60*8) )
  992. return;
  993. if( _unit->CombatStatus.IsInCombat() || !RandomUInt(5))//Random -- to add a little variance.
  994. return;//How can a fighting bot be bored? :P
  995. _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, bored_strings[RandomUInt(5)].c_str());
  996. last_spoke = getMSTime();
  997. }
  998.  
  999. void AIUpdate()
  1000. {
  1001. if( !_unit->GetUInt64Value( UNIT_FIELD_SUMMONEDBY ) && (_unit->GetUInt32Value( UNIT_FIELD_DISPLAYID ) == BOT_BLANK ||_unit->GetUInt32Value( UNIT_FIELD_DISPLAYID ) == BOT_RED || _unit->GetUInt32Value( UNIT_FIELD_DISPLAYID )== BOT_BLUE ) )
  1002. _unit->SummonExpire();//Despawn us if we're a bot but don't have an owner. This is caused by server crashes while bots are out -- the bots remain when the server comes back up, even if their owner's gone.
  1003. if( !_unit->GetUInt64Value( UNIT_FIELD_SUMMONEDBY ) )
  1004. return;
  1005.  
  1006. if( _unit->CombatStatus.IsInCombat() && _unit->GetAIInterface()->GetNextTarget() && _unit->GetAIInterface()->GetNextTarget()->IsPlayer() )
  1007. _unit->CombatStatus.RemoveAttackTarget(_unit->GetAIInterface()->GetNextTarget());
  1008.  
  1009. Say_Bored();
  1010.  
  1011. if( !_unit->CombatStatus.IsInCombat() && _unit->GetUInt32Value( UNIT_FIELD_DISPLAYID ) != BOT_BLANK )
  1012. {
  1013. for (Object::InRangeSet::iterator itr = _unit->GetInRangeSetBegin(); itr != _unit->GetInRangeSetEnd(); ++itr)
  1014. {
  1015. if( (*itr)->IsCreature() && TO_CREATURE(*itr)->GetEntry() >= NPC_ID && TO_CREATURE(*itr)->GetEntry() <= (NPC_ID+3) && ((*itr)->GetUInt32Value( UNIT_FIELD_DISPLAYID ) == BOT_RED || (*itr)->GetUInt32Value( UNIT_FIELD_DISPLAYID ) == BOT_BLUE) && (*itr)->GetUInt32Value( UNIT_FIELD_DISPLAYID ) != _unit->GetUInt32Value( UNIT_FIELD_DISPLAYID ) && _unit->GetDistance2dSq(*itr) < 10.0*10.0 && !TO_CREATURE(*itr)->CombatStatus.IsInCombat() )
  1016. {
  1017. //WE FOUND AN ENEMY BOT. ATTACK!!
  1018. _unit->GetAIInterface()->AttackReaction(TO_CREATURE(*itr), 1, 0);
  1019. TO_CREATURE(*itr)->GetAIInterface()->AttackReaction(_unit, 1, 0);
  1020. TO_CREATURE(*itr)->GetAIInterface()->StopMovement(500);//Make em stop. fix bug.
  1021. _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, attack_strings[RandomUInt(2)].c_str() );
  1022. break;
  1023. }
  1024. }
  1025. }
  1026.  
  1027. if( _unit->CombatStatus.IsInCombat() && (last_spell + 8*1000) < getMSTime() && (RandomUInt(1000) > 650 ) )
  1028. {
  1029. last_spell = getMSTime();
  1030. _unit->CastSpell( _unit->GetAIInterface()->GetNextTarget() , _unit->GetUInt32Value(UNIT_FIELD_DISPLAYID) == BOT_RED ? 49232 : 49236, true);//Yay cast spell! flame shock / frost shock.
  1031. }
  1032.  
  1033. #if ARCEMU > 0
  1034. for (std::set<PlayerPointer>::iterator itr = _unit->GetInRangePlayerSetBegin(); itr != _unit->GetInRangePlayerSetEnd(); ++itr)
  1035. {
  1036. #else
  1037. for(unordered_set<PlayerPointer>::iterator itr = _unit->GetInRangePlayerSetBegin(); itr != _unit->GetInRangePlayerSetEnd(); ++itr)
  1038. {
  1039. #endif
  1040. if( (*itr)->GetGUID() == _unit->GetUInt64Value( UNIT_FIELD_SUMMONEDBY ) )
  1041. {
  1042. if( _unit->GetDistance2dSq(*itr) > 30.0*30.0 )
  1043. break;//Our owner is WAY far away. we may as well despawn.
  1044. #if ARCEMU == 0
  1045. if( (*itr)->IsMounted() && ((*itr)->m_FlyingAura || _unit->GetDistance2dSq(*itr) > 15.0*15.0 ) )//If they're mounted and flying || moving too fast to catch up with em, we need to be deleted.
  1046. break;
  1047. #else
  1048. if( (*itr)->IsMounted() && ((*itr)->flying_aura || _unit->GetDistance2dSq(*itr) > 15.0*15.0 ) )//If they're mounted and flying || moving too fast to catch up with em, we need to be deleted.
  1049. break;
  1050. #endif
  1051. else
  1052. {
  1053. if( TO_PLAYER(*itr)->m_isMoving || (x >= TO_PLAYER(*itr)->GetPositionX() + 0.1 || x <= TO_PLAYER(*itr)->GetPositionX() - 0.1)/*fixes a bug*/ || (y >= TO_PLAYER(*itr)->GetPositionY() + 0.1 || y <= TO_PLAYER(*itr)->GetPositionY() - 0.1) || (z >= TO_PLAYER(*itr)->GetPositionZ() + 0.1 || z <= TO_PLAYER(*itr)->GetPositionZ() - 0.1))
  1054. {
  1055. last_move = getMSTime();
  1056. x = TO_PLAYER(*itr)->GetPositionX();
  1057. y = TO_PLAYER(*itr)->GetPositionY();
  1058. z = TO_PLAYER(*itr)->GetPositionZ();
  1059. }
  1060. return;
  1061. }
  1062. }
  1063. }
  1064. _unit->SummonExpire();//If our owner ain't found, delete us.
  1065. }
  1066.  
  1067. uint32 last_spoke;//
  1068. uint32 last_move;//Keep track of whether or not our owner is idle. If the owner's idle, we say stuff :) (Just to keep it interesting)
  1069. float x,y,z;
  1070. string attack_strings[3];
  1071. string bored_strings[9];
  1072. uint32 last_spell;
  1073. };
  1074.  
  1075. void SetupVendorScript(ScriptMgr * mgr)
  1076. {
  1077. for( uint32 i = 0; i < 4; i++ )
  1078. {
  1079. mgr->register_gossip_script(NPC_ID + i, (GossipScript*) new AutoItemMall() );
  1080. mgr->register_creature_script(NPC_ID + i, &VendorHook::Create);
  1081. }
  1082.  
  1083. mgr->register_item_gossip_script(ITEM_ID, (GossipScript*) new AutoItemMall() );
  1084.  
  1085. LoadItemTables();
  1086.  
  1087. printf("\nAuto Mall Loaded Successfully.\n");
  1088. }
Add Comment
Please, Sign In to add comment