Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Auto Mall
- Description:
- 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.
- The user is then able to purchase the found items.
- Also, the vendor displays a menu of
- This vendor is intended for Level 80 Funservers.
- By Jotox/Classic
- Copyright (c) 2009
- */
- //---------------------------
- //CONFIG!!
- //---------------------------
- //Max item quality allowed to be purchased.
- //Green = 2, Blue = 3, Epic = 4, Legendary = 5, Artifact(GM item) = 6, Heirloom = 7
- #define MAX_QUALITY 4 //Default: Legendaries and above cannot be purchased. Epic and below can.
- //Allow item sets (such as tier 7), conjured items, or quest items to be purchased?
- //0 = Not allowed, 1 = Allowed.
- #define ALLOW_ITEM_SETS 1
- #define ALLOW_CONJURED 0
- #define ALLOW_QUEST 0
- #define ALLOW_FREE 0
- //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.
- //Enable Extended Cost items. Disabling causes extended cost items to be free (unless you add a gold price to them in your database).
- #define ENABLE_EXTENDED_COSTS 1
- //Enable the banning of items via the "mall_banned_items" table.
- #define ENABLE_ITEM_BANNING 1
- //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.
- #define MAX_RESULTS 300
- //Mall menu -- Mounts and armor and weapons and such.
- #define ENABLE_MALL_MENU 1
- //Item Searching -- Enter an item name or ID and it gives you the results
- #define ENABLE_ITEM_SEARCHING 1
- //Enable bot-to-bot interaction for the portable verison of the script (Fighting enemy bots, buffing ally bots)
- #define ENABLE_BOT_FIGHTS 1
- //NPC ID
- #define NPC_ID 993312
- //Item ID (Item version of the vendor)
- #define ITEM_ID 99499
- //Are you on Arcemu? (0 for Aspire, 1 for ArcEmu)
- #define ARCEMU 0
- //---------------------------
- //END CONFIG -- Do not edit below this if you do not know what you're doing.
- //---------------------------
- #include "StdAfx.h"
- #include "Setup.h"
- using namespace std;
- //Arcemu support.
- #if ARCEMU > 0
- typedef Object* ObjectPointer;
- typedef Player* PlayerPointer;
- typedef Unit* UnitPointer;
- typedef Creature* CreaturePointer;
- typedef Item* ItemPointer;
- typedef Spell* SpellPointer;
- #define TO_ITEM(x) static_cast< Item*>(x)
- #define HEARTHSTONE_TOLOWER(x) arcemu_TOLOWER(x)
- enum GossipIcons {
- GOSSIP_ICON_GOSSIP_NORMAL = 0,
- GOSSIP_ICON_GOSSIP_VENDOR = 1,
- GOSSIP_ICON_GOSSIP_FLIGHT = 2,
- GOSSIP_ICON_GOSSIP_TRAINER = 3,
- GOSSIP_ICON_GOSSIP_ENGINEER1 = 4,
- GOSSIP_ICON_GOSSIP_ENGINEER2 = 5,
- GOSSIP_ICON_GOSSIP_AUCTION = 6,
- GOSSIP_ICON_GOSSIP_EXTRA = 7,
- GOSSIP_ICON_GOSSIP_TABARD = 8,
- GOSSIP_ICON_GOSSIP_ARENA = 9,
- GOSSIP_ICON_GOSSIP_COIN = 9,
- };
- #endif
- map< uint64, set<uint32> * > CItems;//List of a set of items for every creature GUID
- map< uint64, set<vector<uint32>*>* > CMenusList;//List of all menus that a creature already has added.
- map< uint32, uint32 > Extended_Cost_List;//List to keep track of extended cost.
- map< uint32, bool > banned_items;//List to keep track of banned items.
- map< uint64, ItemPointer> plr_items;
- #if ENABLE_MALL_MENU > 0
- uint32 counter = 500;
- struct armor_struc {
- vector<uint32> head;
- vector<uint32> shoulder;
- vector<uint32> body;
- vector<uint32> wrist;
- vector<uint32> hands;
- vector<uint32> waist;
- vector<uint32> legs;
- vector<uint32> feet;
- };
- armor_struc armor[4];// Cloth = 0, Leather = 1, Mail = 2, Plate = 3. Total of 4.
- map< string, uint32 > vector_map_map;//the uint32 points to the string's key in vector_map
- map< uint32, vector<uint32> *> vector_map;
- map< uint32, vector<uint32> *> armor_map;
- #define armor_CLOTH 0
- #define armor_LEATHER 1
- #define armor_MAIL 2
- #define armor_PLATE 3
- #endif
- #define BOT_BLUE 29280
- #define BOT_RED 29281
- #define BOT_BLANK 29279
- #define SIDE_HORDE 1
- #define SIDE_ALLIANCE 0
- bool IsCustom( uint32 id )
- {
- return id > 56000;//custom items can't be seen.
- }
- void AddItemsToCreature( CreaturePointer unit, vector<uint32> *items, bool is_menu = true )
- {
- if( is_menu )
- {
- if( !CMenusList[ unit->GetGUID() ] || CMenusList[ unit->GetGUID() ]->find( items ) != CMenusList[ unit->GetGUID() ]->end() )
- return;
- CMenusList[ unit->GetGUID() ]->insert( items );
- }
- for( vector<uint32>::iterator itr = items->begin(); itr != items->end(); itr++ )
- {
- ItemPrototype * curItem = ItemPrototypeStorage.LookupEntry(*itr);
- if( !is_menu && CItems[ unit->GetGUID() ]->find( curItem->ItemId ) != CItems[ unit->GetGUID() ]->end() )
- continue;
- #if ARCEMU > 0
- 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.
- #else
- 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.
- if( Extended_Cost_List[ curItem->ItemId ] )
- {
- CreatureItem ci;
- unit->GetSellItemByItemId( curItem->ItemId , ci);
- ci.extended_cost = dbcItemExtendedCost.LookupEntryForced( Extended_Cost_List[ curItem->ItemId ] );
- }
- #endif
- CItems[ unit->GetGUID() ]->insert( curItem->ItemId );
- }
- }
- void SendItemList( CreaturePointer unit, PlayerPointer plr, vector<uint32> * items )//Sends a Mall window with only the items in the "items" vector
- {
- if( items->size() < 1 )
- return;//.......we shouldn't get here.
- if( !unit || !plr || !plr->IsInWorld() || !plr->GetSession() )
- return;//AHH
- WorldPacket data(((items->size() * 28) + 9)); // allocate
- data.SetOpcode( SMSG_LIST_INVENTORY );
- data << unit->GetGUID();
- data << uint8( 0 ); // placeholder for item count
- uint32 counter = 0;
- ItemPrototype * curItem;
- for( vector<uint32>::iterator itr = items->begin(); itr != items->end(); itr++ )
- {
- curItem = ItemPrototypeStorage.LookupEntry(*itr);
- if(curItem->AllowableClass && !(plr->getClassMask() & curItem->AllowableClass))
- continue;
- if(curItem->AllowableRace && !(plr->getRaceMask() & curItem->AllowableRace))
- continue;
- if(curItem->RequiredSkill && plr->_HasSkillLine(curItem->RequiredSkill) && plr->_GetSkillLineCurrent( curItem->RequiredSkill ) < curItem->RequiredSkillRank )
- continue;//Only show useable recipes.
- data << (counter + 1);//Count
- data << curItem->ItemId;//Item id
- data << curItem->DisplayInfoID;//Display id
- data << int32(-1);//Available amount
- data << curItem->BuyPrice;//Buyprice
- data << int32(-1); // ???
- data << curItem->MaxCount;
- if( Extended_Cost_List[ curItem->ItemId ] )
- data << Extended_Cost_List[ curItem->ItemId ];
- else
- data << uint32(0);//Extended cost
- if( counter == 150 )//15 pages is enough, eh?
- break;
- ++counter;
- }
- const_cast<uint8*>(data.contents())[8] = (uint8)counter; // set count
- if( plr->GetSession() )
- plr->GetSession()->SendPacket( &data );
- if( !counter )
- unit->SendChatMessageToPlayer(15, 0, "I could not find an item available for your race and class.", plr);//Whisper, in universal language.
- }
- bool stringtest( string thing )//Tests whether a string consists SOLELY of numbers or not. returns true if the string is all numbers.
- {
- char str[256];
- 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.
- return str == thing;
- }
- bool TestItem( ItemPrototype * it )
- {
- if( !it )
- return false;
- if( IsCustom(it->ItemId) )
- return false;
- if( !(ALLOW_ITEM_SETS) && it->ItemSet )//item sets
- return false;
- if( ( ( !(ALLOW_FREE) && (!it->BuyPrice) || it->BuyPrice < it->SellPrice) ) && !Extended_Cost_List[ it->ItemId ] )// free / sell for more than bought and no extended cost
- return false;
- if( it->Quality > MAX_QUALITY )//quality
- return false;
- if( (!(ALLOW_QUEST) && it->Flags & ITEM_FLAG_QUEST) || (!(ALLOW_CONJURED) && it->Flags & ITEM_FLAG_CONJURED) )//quest / conjured
- return false;
- if( !(ALLOW_QUEST) && it->QuestId )//Quest again
- return false;
- if( banned_items[ it->ItemId ] )
- return false;
- return true;
- }
- bool TestItemEntry( uint32 entry )
- {
- if( IsCustom(entry) )
- return false;
- return TestItem( ItemPrototypeStorage.LookupEntry(entry) );
- }
- void FindItem( UnitPointer unit, PlayerPointer plr, const char* nameC, vector<uint32> &items )
- {
- string name( nameC );
- int itemid = atoi(name.c_str());
- if( itemid && !(itemid==INT_MIN || itemid==INT_MAX) && stringtest(name) )
- {
- ItemPrototype * it = ItemPrototypeStorage.LookupEntry(itemid);//If it's just an item id, no point in using SQL. eh?
- if( it && TestItem(it) )
- items.push_back(it->ItemId);
- if( !items.size() )
- 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.
- return;
- }
- string x = name;
- HEARTHSTONE_TOLOWER(x);
- while( x.find("%") != string::npos )
- x.erase( x.find("%") );//Remove wildcard characters.
- if(x.length() < 3)
- {
- unit->SendChatMessageToPlayer(15, 0, "Please enter a name 4 or more letters in length.", plr);
- return;
- }
- ItemPrototype * it;
- uint32 count = 0;
- 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 );
- if( !result )
- {
- unit->SendChatMessageToPlayer(15, 0, "I'm sorry, I could not find your item. Please check the name and try again.", plr);
- return;
- }
- do
- {
- uint32 entry = result->Fetch()[0].GetUInt32();
- it = ItemPrototypeStorage.LookupEntry( entry );
- if( !it || !TestItem(it) )
- continue;
- items.push_back(it->ItemId);
- } while (result->NextRow());
- delete result;
- if( !items.size() )
- unit->SendChatMessageToPlayer(15, 0, "I'm sorry, that item is unavailable for purchase.", plr);
- return;
- }
- void HandleRecipes(ObjectPointer pObject, PlayerPointer plr, uint32 Id, uint32 IntId, const char * Code)
- {
- GossipMenu *Menu;
- objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 44333225, plr);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Alchemy Recipes", vector_map_map["Alchemy Recipes"]);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Blacksmithing Recipes", vector_map_map["Blacksmithing Recipes"]);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Cooking Recipes", vector_map_map["Cooking Recipes"]);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Enchanting Recipes", vector_map_map["Enchanting Recipes"]);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Engineering Recipes", vector_map_map["Engineering Recipes"]);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Jewelcrafting Recipes", vector_map_map["Jewelcrafting Recipes"]);
- //Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Inscription Recipes", vector_map_map["Inscription Recipes"]);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Leatherworking Recipes", vector_map_map["Leatherworking Recipes"]);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_TRAINER, "Tailoring Recipes", vector_map_map["Tailoring Recipes"]);
- Menu->AddItem( 7, "[Back]", 1055);
- Menu->SendTo(plr);
- }
- void HandleArmor(ObjectPointer pObject, PlayerPointer plr, uint32 Id, uint32 IntId, const char * Code)
- {
- if( IntId > 200 )
- {
- vector<uint32> *vpointer = armor_map[ IntId ];//Just because references must be initialized.
- AddItemsToCreature( TO_CREATURE(pObject), vpointer );
- SendItemList( TO_CREATURE(pObject), plr, vpointer );//Show the weapons.
- return;
- }
- GossipMenu *Menu;
- objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 44333225, plr);
- uint32 armor_class;
- switch( plr->getClass() )
- {
- case DEATHKNIGHT:
- case WARRIOR:
- case PALADIN:
- armor_class = armor_PLATE;
- break;
- case HUNTER:
- case SHAMAN:
- armor_class = armor_MAIL;
- break;
- case DRUID:
- case ROGUE:
- armor_class = armor_LEATHER;
- break;
- default:
- armor_class = armor_CLOTH;
- }
- Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Helms", 200 + ((armor_class + 1) * 10));
- Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Cloaks", vector_map_map["Cloaks"]);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Shoulders", 200 + ((armor_class + 1) * 10) + 1);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Chestpieces", 200 + ((armor_class + 1) * 10) + 2);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Wristguards", 200 + ((armor_class + 1) * 10) + 3);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Gloves", 200 + ((armor_class + 1) * 10) + 4);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Waistbelts", 200 + ((armor_class + 1) * 10) + 5);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Leggings", 200 + ((armor_class + 1) * 10) + 6);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_FLIGHT, "Boots", 200 + ((armor_class + 1) * 10) + 7);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_AUCTION, "Necklaces", vector_map_map["Necklaces"]);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_AUCTION, "Rings", vector_map_map["Rings"]);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_AUCTION, "Trinkets", vector_map_map["Trinkets"]);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_ARENA, "Shields", vector_map_map["Shields"]);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_ARENA, "Offhands", vector_map_map["Offhands"]);
- Menu->AddItem( GOSSIP_ICON_GOSSIP_TABARD, "Tabards", vector_map_map["Tabards"]);
- switch( plr->getClass() )
- {
- case DEATHKNIGHT:
- Menu->AddItem( GOSSIP_ICON_GOSSIP_AUCTION, "Sigils", vector_map_map["Sigils"]);
- break;
- case DRUID:
- Menu->AddItem( GOSSIP_ICON_GOSSIP_AUCTION, "Idols", vector_map_map["Idols"]);
- break;
- case SHAMAN:
- Menu->AddItem( GOSSIP_ICON_GOSSIP_AUCTION, "Totems", vector_map_map["Totems"]);
- break;
- case PALADIN:
- Menu->AddItem( GOSSIP_ICON_GOSSIP_AUCTION, "Librams", vector_map_map["Librams"]);
- break;
- default:
- break;
- }
- Menu->AddItem( 7, "[Back]", 1055);
- Menu->SendTo(plr);
- }
- void HandleWeapons(ObjectPointer pObject, PlayerPointer plr, uint32 Id, uint32 IntId, const char * Code)
- {
- GossipMenu *Menu;
- objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 44333225, plr);
- Menu->AddItem( 9, "Two-Handed Swords", vector_map_map["Two-Handed Swords"]);
- Menu->AddItem( 9, "Two-Handed Maces", vector_map_map["Two-Handed Maces"]);
- Menu->AddItem( 9, "Two-Handed Axes", vector_map_map["Two-Handed Axes"]);
- Menu->AddItem( 9, "Polearms", vector_map_map["Polearms"]);
- Menu->AddItem( 9, "Staves", vector_map_map["Staves"]);
- Menu->AddItem( 6, "One-Handed Swords", vector_map_map["One-Handed Swords"]);
- Menu->AddItem( 6, "One-Handed Maces", vector_map_map["One-Handed Maces"]);
- Menu->AddItem( 6, "One-Handed Axes", vector_map_map["One-Handed Axes"]);
- Menu->AddItem( 6, "Daggers", vector_map_map["Daggers"]);
- Menu->AddItem( 6, "Fist Weapons", vector_map_map["Fist Weapons"]);
- Menu->AddItem( 2, "Guns", vector_map_map["Guns"]);
- Menu->AddItem( 2, "Bows", vector_map_map["Bows"]);
- Menu->AddItem( 2, "Crossbows", vector_map_map["Crossbows"]);
- Menu->AddItem( 2, "Wands", vector_map_map["Wands"]);
- Menu->AddItem( 2, "Thrown",vector_map_map["Thrown"]);
- Menu->AddItem( 7, "[Back]", 1055);
- Menu->SendTo(plr);
- }
- CreaturePointer make_creature( PlayerPointer plr )
- {
- float angle = -(3.14159265) / 3;
- CreatureProto * proto = CreatureProtoStorage.LookupEntry( NPC_ID + RandomUInt(3) );
- CreatureInfo * info = CreatureNameStorage.LookupEntry( NPC_ID + RandomUInt(3) );
- LocationVector v = plr->GetPositionNC();
- float m_followAngle = angle + v.o;
- float x = v.x +(3*(cosf(m_followAngle)));
- float y = v.y +(3*(sinf(m_followAngle)));
- CreaturePointer p = plr->GetMapMgr()->CreateCreature(NPC_ID);
- p->SetInstanceID(plr->GetMapMgr()->GetInstanceID());
- p->Load(proto, x, y, v.z, angle);//Fix falling thru ground bug.
- p->SetZoneId(plr->GetZoneId());
- p->GetAIInterface()->Init(p,AITYPE_PET,MOVEMENTTYPE_NONE,plr);
- p->GetAIInterface()->SetUnitToFollow(plr);
- p->GetAIInterface()->SetUnitToFollowAngle(angle);
- p->GetAIInterface()->SetFollowDistance(3.0f);
- p->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,35);//Players will see them as green, even though they're actually neutral.
- p->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9);
- p->SetUInt32Value(UNIT_FIELD_DISPLAYID, BOT_BLANK );
- p->SetFloatValue( OBJECT_FIELD_SCALE_X, 1.1f );//To make him a reasonable size. Otherwise he would be 0.7f
- p->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, plr->GetGUID() );
- //p->SetUInt64Value( UNIT_FIELD_CREATEDBY, plr->GetGUID() );
- //p->SetUInt64Value(UNIT_FIELD_CBY, plr->GetGUID());
- p->SetUInt32Value( UNIT_FIELD_HEALTH, 5000 );//Set combat stats. For pet combat :D
- p->SetUInt32Value( UNIT_FIELD_MAXHEALTH, 5000 );
- p->SetUInt32Value( UNIT_FIELD_BASEATTACKTIME, 2000 + RandomUInt(100) );
- p->SetFloatValue( UNIT_FIELD_MINDAMAGE, 100 );
- p->SetFloatValue( UNIT_FIELD_MAXDAMAGE, 700 );
- for( uint32 i = 0; i < 9; i++ )
- p->SetUInt32Value( UNIT_FIELD_RESISTANCES + i, 0 );//the stationary version has all resistances 666, so let's set this to 0.
- p->PushToWorld(plr->GetMapMgr());
- p->GetAIInterface()->MoveTo( v.x +(2.9*(cosf(m_followAngle))), v.y +(2.9*(sinf(m_followAngle))), v.z, angle);//Hackkkk
- #if ARCEMU == 0
- plr->m_SummonSlots[ 6 ] = p;
- #endif
- return p;
- }
- class SCRIPT_DECL AutoItemMall : public GossipScript
- {
- public:
- void GossipHello(ObjectPointer pObject, PlayerPointer plr, bool AutoSend)
- {
- if( pObject->GetTypeId() == TYPEID_ITEM )
- {
- if( !plr->Cooldown_CanCast(ItemPrototypeStorage.LookupEntry(ITEM_ID), 0) || !plr->Cooldown_CanCast(ItemPrototypeStorage.LookupEntry(ITEM_ID), 1) )
- {
- if( plr->GetSession() )
- plr->GetSession()->SendNotification("Your bot is still recharging!");
- return;
- }
- for (Object::InRangeSet::iterator itr = plr->GetInRangeSetBegin(); itr != plr->GetInRangeSetEnd(); ++itr)
- {
- if( (*itr)->IsCreature() && TO_CREATURE(*itr)->GetEntry() >= NPC_ID && TO_CREATURE(*itr)->GetEntry() <= (NPC_ID+3) && (*itr)->GetUInt64Value( UNIT_FIELD_SUMMONEDBY ) == plr->GetGUID() )
- {
- if( TO_CREATURE(*itr)->CombatStatus.IsInCombat() )
- {
- 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!"};
- TO_CREATURE(*itr)->SendChatMessageToPlayer(15, 0, strings[RandomUInt(2)].c_str(), plr);
- return;
- }
- TO_CREATURE(*itr)->SendChatMessageToPlayer(15, 0, "Goodbye!", plr);
- TO_CREATURE(*itr)->SummonExpire();
- ItemPrototype * ip = ItemPrototypeStorage.LookupEntry(ITEM_ID);
- plr->Cooldown_AddItem( ip, 1);//Yay cooldowns!
- return;
- }
- }//Despawn existing vendors, if found.
- CreaturePointer VendorPersonal = make_creature( plr );
- plr_items[ VendorPersonal->GetGUID() ] = TO_ITEM(pObject);
- VendorPersonal->SendChatMessageToPlayer(15, 0, "Thank you for summoning me! I'm your personal vendor, here for your assistance!", plr);
- return;
- }
- if( TO_CREATURE(pObject)->CombatStatus.IsInCombat() )
- return;
- if( pObject->GetUInt64Value( UNIT_FIELD_SUMMONEDBY ) > 0 && pObject->GetUInt64Value( UNIT_FIELD_SUMMONEDBY ) != plr->GetGUID() )
- {
- string strings[3] = {"You don't own me!", "My master says not to talk to strangers...", "I only talk to my master!"};
- TO_UNIT(pObject)->SendChatMessageToPlayer(15, 0, strings[RandomUInt(2)].c_str(), plr);
- return;
- }
- GossipMenu *Menu;
- objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 44333225, plr);
- if( ENABLE_ITEM_SEARCHING )
- {
- #if ARCEMU == 0
- Menu->AddItem( 1, "Search for an item to purchase.", 1, true);
- #else
- Menu->AddItem( 1, "Search for an item to purchase.", 1, 1);
- #endif
- }
- #if ENABLE_MALL_MENU > 0
- Menu->AddItem( 9, "Weapons", 100);
- Menu->AddItem( 9, "Armor", 200);
- Menu->AddItem( 3, "Professions", 334);
- Menu->AddItem( 2, "Mounts", vector_map_map["Mounts"]);
- Menu->AddItem( 2, "Personal Pets", vector_map_map["Personal Pets"]);
- Menu->AddItem( 1, "Bags", vector_map_map["Bags"]);
- #endif
- if( ENABLE_ITEM_SEARCHING )
- Menu->AddItem( 0, "How does this Mall work?", 99);
- #if ENABLE_BOT_FIGHTS > 0
- 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.
- Menu->AddItem( 9, "|cffff0000Let Me Fight!", 69);
- if( pObject->GetUInt64Value( UNIT_FIELD_SUMMONEDBY )==plr->GetGUID() && pObject->GetUInt32Value(UNIT_FIELD_DISPLAYID) == BOT_RED )//We're a red bot.
- Menu->AddItem( 9, "|cff0099FFSwitch Fuels!", 70);
- if( pObject->GetUInt64Value( UNIT_FIELD_SUMMONEDBY )==plr->GetGUID() && pObject->GetUInt32Value(UNIT_FIELD_DISPLAYID) == BOT_BLUE )//We're a blue bot! :O
- Menu->AddItem( 9, "|cffff0000Switch Fuels!", 71);
- #endif
- if(AutoSend)
- Menu->SendTo(plr);
- }
- void GossipSelectOption(ObjectPointer pObject, PlayerPointer plr, uint32 Id, uint32 IntId, const char * Code)
- {
- if( TO_CREATURE(pObject)->CombatStatus.IsInCombat() )
- {
- TO_UNIT(pObject)->SendChatMessageToPlayer(15, 0, "Can't you see I'm busy right now?", plr);
- plr->Gossip_Complete();
- return;
- }
- if( IntId >= 500 && IntId < 1000 )
- {
- vector<uint32> *vpointer = vector_map[ IntId ];
- AddItemsToCreature( TO_CREATURE(pObject), vpointer );
- SendItemList( TO_CREATURE(pObject), plr, vpointer );//Show them.
- return;
- }
- if( IntId >= 100 && IntId < 200 )
- {
- HandleWeapons( pObject, plr, Id, IntId, Code );
- return;
- }
- else if( IntId >= 200 && IntId < 300 )
- {
- HandleArmor( pObject, plr, Id, IntId, Code );
- return;
- }
- switch (IntId)
- {
- case 69:
- case 70:
- case 71:
- {
- plr->Gossip_Complete();
- string message = "";
- uint32 new_model;
- if( pObject->GetUInt32Value( UNIT_FIELD_DISPLAYID) == BOT_BLUE )
- new_model = BOT_RED;
- if( pObject->GetUInt32Value( UNIT_FIELD_DISPLAYID) == BOT_RED )
- new_model = BOT_BLUE;
- if( pObject->GetUInt32Value( UNIT_FIELD_DISPLAYID) == BOT_BLANK )
- {
- new_model = RandomUInt(1) ? BOT_RED : BOT_BLUE;
- message = "Time to kick some ass!";
- }
- pObject->SetUInt32Value( UNIT_FIELD_DISPLAYID, new_model );
- if( message != "" )
- TO_UNIT(pObject)->SendChatMessageToPlayer(15, 0, message.c_str(), plr);
- TO_UNIT(pObject)->CastSpell(TO_UNIT(pObject), pObject->GetUInt32Value( UNIT_FIELD_DISPLAYID) == BOT_BLUE ? 36881 : 43045, true);
- #if ARCEMU==0
- //Something screwed up with aspire AI
- 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.
- TO_UNIT(pObject)->_setFaction();
- 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)
- #endif
- }break;
- case 334://Random numbers. lol. whatever.
- {
- HandleRecipes( pObject, plr, Id, IntId, Code );
- }break;
- case 1055://Back
- {
- GossipHello(pObject, plr, true);
- }break;
- case 99://Help pl0x
- {
- TO_UNIT(pObject)->SendChatMessageToPlayer(15, 0, "This vendor is an \"All-In-One\" mall vendor.", plr);
- 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);
- GossipHello(pObject, plr, true);
- }break;
- case 1://We're looking for an item.
- {
- vector<uint32> items;
- FindItem(TO_UNIT(pObject), plr, Code, items);
- if( !items.size() )
- {
- GossipHello(pObject, plr, true);
- return;
- }
- 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
- SendItemList( TO_CREATURE(pObject), plr, &items );//Show him the list of items.
- items.clear();
- }break;
- }
- }
- void GossipEnd(ObjectPointer pObject, PlayerPointer Plr)
- {
- 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.
- Plr->CleanupGossipMenu();
- }
- void Destroy()
- {
- delete this;
- }
- };
- void LoadItemsFromQuery( char* query, vector<uint32> *items, bool test )
- {
- if( !query || query == "" )
- return;
- QueryResult* result = WorldDatabase.Query(query);
- if( !result )
- printf("\n(Auto Mall): Note: Query: %s was empty (Ignore this if you're not a developer).\n", query);
- else
- {
- items->reserve(result->GetRowCount());//Optimization.
- do
- {
- uint32 id = result->Fetch()[0].GetUInt32();
- if( IsCustom(id) )
- continue;
- if( !test || TestItemEntry( id ) )
- items->push_back( id );
- } while (result->NextRow());
- delete result;
- }
- }
- void LoadItemsFromQuery2( char* query, string label, bool test )
- {
- vector_map[counter] = new vector<uint32>;
- LoadItemsFromQuery(query, vector_map[counter], test);
- vector_map_map[label] = counter;
- counter++;
- }
- void LoadArmorFromQuery( string subclass, string slot, vector<uint32> * items )
- {
- 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";
- char * queryC;
- queryC = new char[query.length() + 1];
- strcpy(queryC, query.c_str());//This is to convert from const char* (.c_str() returns const char) to char*
- LoadItemsFromQuery( queryC, items, true );
- delete[] queryC;//Free.
- }
- void LoadItemTables()
- {
- QueryResult * result;
- 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.
- if( ENABLE_EXTENDED_COSTS )
- {
- #if ARCEMU==0
- result = WorldDatabase.Query("SELECT DISTINCT item, extendedcost FROM vendors WHERE extendedcost > 1");//1 because of a bug with crappy DBs
- #else
- result = WorldDatabase.Query("SELECT DISTINCT item, extended_cost FROM vendors WHERE extended_cost > 1");//1 because of a bug with crappy DBs
- #endif
- if( !result )
- printf("(Auto Mall): Error loading extended costs.");
- else
- {
- do
- {
- uint32 id = result->Fetch()[0].GetUInt32();
- uint32 ec = result->Fetch()[1].GetUInt32();
- if( dbcItemExtendedCost.LookupEntryForced(ec) )
- Extended_Cost_List[ id ] = ec;
- } while (result->NextRow());
- delete result;
- }
- }
- if( ENABLE_ITEM_BANNING )
- {
- result = WorldDatabase.Query("SELECT * FROM mall_banned_items");
- if( !result )
- printf("(Auto Mall): Error loading banned items.");
- else
- {
- do
- {
- banned_items[ result->Fetch()[0].GetUInt32() ] = true;
- } while (result->NextRow());
- delete result;
- }
- }
- if( ENABLE_MALL_MENU )
- {
- LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 15 AND subclass = 5 ORDER BY quality DESC, buyprice DESC", "Mounts", true );//Mounts
- 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
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- 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 );
- LoadItemsFromQuery2( "SELECT entry FROM items WHERE containerslots > 16 AND quality >= 2 ORDER BY subclass, containerslots DESC", "Bags", true );
- LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 6 ORDER BY quality DESC, RequiredSkillRank DESC", "Alchemy Recipes", true );
- LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 4 ORDER BY quality DESC, RequiredSkillRank DESC", "Blacksmithing Recipes", true );
- LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 5 ORDER BY quality DESC, RequiredSkillRank DESC", "Cooking Recipes", true );
- LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 8 ORDER BY quality DESC, RequiredSkillRank DESC", "Enchanting Recipes", true );
- LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 3 ORDER BY quality DESC, RequiredSkillRank DESC", "Engineering Recipes", true );
- LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 2 ORDER BY quality DESC, RequiredSkillRank DESC", "Tailoring Recipes", true );
- LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 1 ORDER BY quality DESC, RequiredSkillRank DESC", "Leatherworking Recipes", true );
- LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 9 AND subclass = 10 ORDER BY quality DESC, RequiredSkillRank DESC", "Jewelcrafting Recipes", true );
- for( uint8 i = 0; i <= armor_PLATE; i++ )
- {
- armor_struc &armor_local = armor[i];
- string strings[4]= {"1", "2", "3", "4"};
- string subclass = strings[i];
- LoadArmorFromQuery( subclass, "1", &armor_local.head );
- LoadArmorFromQuery( subclass, "3", &armor_local.shoulder );
- LoadArmorFromQuery( subclass, "5", &armor_local.body );
- LoadArmorFromQuery( subclass, "20", &armor_local.body );
- LoadArmorFromQuery( subclass, "9", &armor_local.wrist );
- LoadArmorFromQuery( subclass, "6", &armor_local.waist );
- LoadArmorFromQuery( subclass, "10", &armor_local.hands );
- LoadArmorFromQuery( subclass, "7", &armor_local.legs );
- LoadArmorFromQuery( subclass, "8", &armor_local.feet );
- }
- 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);
- 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);
- 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);
- 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);
- 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);
- 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);
- LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND inventorytype = 19 ORDER BY quality DESC, itemlevel DESC", "Tabards", false );
- LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND subclass = 7 ORDER BY quality DESC, itemlevel DESC", "Librams", true );
- LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND subclass = 8 ORDER BY quality DESC, itemlevel DESC", "Idols", true );
- LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND subclass = 10 ORDER BY quality DESC, itemlevel DESC", "Sigils", true );
- LoadItemsFromQuery2( "SELECT entry FROM items WHERE class = 4 AND subclass = 9 ORDER BY quality DESC, itemlevel DESC", "Totems", true );
- //all the items are loaded!! Let's go!
- uint32 counter2 = 200;
- uint32 counter;
- for( uint32 i = 0; i < 4; i++ )
- {
- counter2 += 10;
- counter = counter2;
- armor_map[ counter++ ] = &armor[i].head;
- armor_map[ counter++ ] = &armor[i].shoulder;
- armor_map[ counter++ ] = &armor[i].body;
- armor_map[ counter++ ] = &armor[i].wrist;
- armor_map[ counter++ ] = &armor[i].hands;
- armor_map[ counter++ ] = &armor[i].waist;
- armor_map[ counter++ ] = &armor[i].legs;
- armor_map[ counter++ ] = &armor[i].feet;
- }
- SpellEntry* sp = dbcSpell.LookupEntryForced(43045);
- if( sp )
- sp->Effect[2] = 0;//Prevent crash.
- }
- }
- class VendorHook : public CreatureAIScript
- {
- public:
- ADD_CREATURE_FACTORY_FUNCTION(VendorHook);
- VendorHook(CreaturePointer pCreature) : CreatureAIScript(pCreature)
- {
- CItems[ _unit->GetGUID() ] = new set<uint32>;
- CMenusList[ _unit->GetGUID() ] = new set<vector<uint32>*>;
- attack_strings[0] = "C'mere, you little...";
- attack_strings[1] = "I'll show you!";
- attack_strings[2] = "Finally, some action!";
- bored_strings[0] = "I'm bored...";//Bored messages.
- bored_strings[1] = "This is boring!";
- bored_strings[2] = "Don't just stand there, do something!";
- bored_strings[3] = "Why are you just standing there?";
- bored_strings[4] = "Hey, wanna go get some of this? |cff00ff00|TInterface\\icons\\INV_MISC_FIREDANCER_01:48|t|r";
- bored_strings[5] = "I'm made for selling, not standing around!";
- bored_strings[6] = "I'm outta here. Bye!";//Exit messages.
- bored_strings[7] = "This is too boring for me. Cya!";
- bored_strings[8] = "You can have fun standing there if you want, but I'm gonna go do something else.";
- last_move = getMSTime();
- last_spoke = getMSTime();
- x = y = z = 0.0f;
- RegisterAIUpdateEvent( 2000 );//Once every 2 seconds is plenty. No high CPU usage. at all. -- creature AI updates much more often than this.
- }
- ~VendorHook()
- {
- last_move = 0;
- last_spoke = 0;
- CMenusList[ _unit->GetGUID() ]->clear();
- CItems[ _unit->GetGUID() ]->clear();
- delete CMenusList[ _unit->GetGUID() ];
- delete CItems[ _unit->GetGUID() ];
- CMenusList[ _unit->GetGUID() ] = NULL;
- CItems[ _unit->GetGUID() ] = NULL;
- plr_items.erase( _unit->GetGUID() );
- }
- void OnDied( UnitPointer killer )
- {
- #if ARCEMU > 0
- for (std::set<PlayerPointer>::iterator itr = _unit->GetInRangePlayerSetBegin(); itr != _unit->GetInRangePlayerSetEnd(); ++itr)
- {
- #else
- for(unordered_set<PlayerPointer>::iterator itr = _unit->GetInRangePlayerSetBegin(); itr != _unit->GetInRangePlayerSetEnd(); ++itr)
- {
- #endif
- if( (*itr)->GetGUID() == _unit->GetUInt64Value( UNIT_FIELD_SUMMONEDBY ) )
- {
- ItemPrototype * ip = ItemPrototypeStorage.LookupEntry(ITEM_ID);
- #if ARCEMU==0
- SpellPointer spell(new Spell((*itr), dbcSpell.LookupEntryForced( ip->Spells[0].Id ), false, NULLAURA));
- #else
- SpellPointer spell(new Spell((*itr), dbcSpell.LookupEntryForced( ip->Spells[0].Id ), false, NULL));
- #endif
- spell->i_caster = plr_items[_unit->GetGUID()];
- SpellCastTargets target(0);
- target.m_targetMask |= TARGET_FLAG_UNIT;
- target.m_unitTarget = (*itr)->GetGUID();
- spell->prepare(&target);
- TO_PLAYER(*itr)->Cooldown_AddItem( ip, 0);//Yay cooldowns!
- break;
- }
- }
- _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, "AHHHHH!");
- RemoveAIUpdateEvent();
- _unit->SummonExpire();
- if( killer->isAlive() )
- {
- killer->CastSpell( killer, 55420, true);//Fireworks for the winner! yay
- #if ARCEMu==0
- //Aspire: need to regenerate the bots. arcemu, they regen fine.
- killer->SetUInt32Value(UNIT_FIELD_HEALTH, 5000);
- killer->SetUInt32Value(UNIT_FIELD_POWER1, 99999);
- #endif
- }
- }
- void Say_Bored()
- {
- 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.)
- {
- _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, bored_strings[RandomUInt(2) + 6].c_str());
- _unit->SummonExpire();
- return;
- }
- if( getMSTime() < (last_move + 1000*60*7) || getMSTime() < (last_spoke + 1000*60*8) )
- return;
- if( _unit->CombatStatus.IsInCombat() || !RandomUInt(5))//Random -- to add a little variance.
- return;//How can a fighting bot be bored? :P
- _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, bored_strings[RandomUInt(5)].c_str());
- last_spoke = getMSTime();
- }
- void AIUpdate()
- {
- 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 ) )
- _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.
- if( !_unit->GetUInt64Value( UNIT_FIELD_SUMMONEDBY ) )
- return;
- if( _unit->CombatStatus.IsInCombat() && _unit->GetAIInterface()->GetNextTarget() && _unit->GetAIInterface()->GetNextTarget()->IsPlayer() )
- _unit->CombatStatus.RemoveAttackTarget(_unit->GetAIInterface()->GetNextTarget());
- Say_Bored();
- if( !_unit->CombatStatus.IsInCombat() && _unit->GetUInt32Value( UNIT_FIELD_DISPLAYID ) != BOT_BLANK )
- {
- for (Object::InRangeSet::iterator itr = _unit->GetInRangeSetBegin(); itr != _unit->GetInRangeSetEnd(); ++itr)
- {
- 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() )
- {
- //WE FOUND AN ENEMY BOT. ATTACK!!
- _unit->GetAIInterface()->AttackReaction(TO_CREATURE(*itr), 1, 0);
- TO_CREATURE(*itr)->GetAIInterface()->AttackReaction(_unit, 1, 0);
- TO_CREATURE(*itr)->GetAIInterface()->StopMovement(500);//Make em stop. fix bug.
- _unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, attack_strings[RandomUInt(2)].c_str() );
- break;
- }
- }
- }
- if( _unit->CombatStatus.IsInCombat() && (last_spell + 8*1000) < getMSTime() && (RandomUInt(1000) > 650 ) )
- {
- last_spell = getMSTime();
- _unit->CastSpell( _unit->GetAIInterface()->GetNextTarget() , _unit->GetUInt32Value(UNIT_FIELD_DISPLAYID) == BOT_RED ? 49232 : 49236, true);//Yay cast spell! flame shock / frost shock.
- }
- #if ARCEMU > 0
- for (std::set<PlayerPointer>::iterator itr = _unit->GetInRangePlayerSetBegin(); itr != _unit->GetInRangePlayerSetEnd(); ++itr)
- {
- #else
- for(unordered_set<PlayerPointer>::iterator itr = _unit->GetInRangePlayerSetBegin(); itr != _unit->GetInRangePlayerSetEnd(); ++itr)
- {
- #endif
- if( (*itr)->GetGUID() == _unit->GetUInt64Value( UNIT_FIELD_SUMMONEDBY ) )
- {
- if( _unit->GetDistance2dSq(*itr) > 30.0*30.0 )
- break;//Our owner is WAY far away. we may as well despawn.
- #if ARCEMU == 0
- 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.
- break;
- #else
- 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.
- break;
- #endif
- else
- {
- 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))
- {
- last_move = getMSTime();
- x = TO_PLAYER(*itr)->GetPositionX();
- y = TO_PLAYER(*itr)->GetPositionY();
- z = TO_PLAYER(*itr)->GetPositionZ();
- }
- return;
- }
- }
- }
- _unit->SummonExpire();//If our owner ain't found, delete us.
- }
- uint32 last_spoke;//
- 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)
- float x,y,z;
- string attack_strings[3];
- string bored_strings[9];
- uint32 last_spell;
- };
- void SetupVendorScript(ScriptMgr * mgr)
- {
- for( uint32 i = 0; i < 4; i++ )
- {
- mgr->register_gossip_script(NPC_ID + i, (GossipScript*) new AutoItemMall() );
- mgr->register_creature_script(NPC_ID + i, &VendorHook::Create);
- }
- mgr->register_item_gossip_script(ITEM_ID, (GossipScript*) new AutoItemMall() );
- LoadItemTables();
- printf("\nAuto Mall Loaded Successfully.\n");
- }
Add Comment
Please, Sign In to add comment