This lets you exchange tokens for items / item sets, and even exchange marks for tokens! Easy to understand, easy to configure, easy to use :)
Code:
#include "StdAfx.h"
#include "Setup.h"
#define MARKID 90909 //ID for the mark
#define TOKENID 91919 //ID for the token.
#define TRADERATE 5 //This manymarks = 1 token
#define SUCMSG "Enjoy your prize :)" //Message when user gets his prize
#define TOKMSG "You don't have enough tokens to buy this"
#define MRKMSG "You don't have enough marks to get a token"
#define NPCID 87001 //ID of the vendor NPC
class SCRIPT_DECL Coin : public GossipScript
{
public:
void GossipHello(Object * pObject, Player* Plr, bool AutoSend);
void GossipSelectOption(Object * pObject, Player* Plr, uint32 Id, uint32 IntId, const char * Code);
void GossipEnd(Object * pObject, Player* Plr);
void Destroy()
{
delete this;
}
};
void Coin::GossipHello(Object * pObject, Player* Plr, bool AutoSend)
{
//-----------------------------
//Setup Main Categories/Items
//-----------------------------
GossipMenu *Menu;
objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 1, Plr);
Menu->AddItem(0, "Convert 5 Marks for 1 Token", 98);
Menu->AddItem(0, "Category 1", 1);
Menu->AddItem(0, "Category 2", 2);
if(AutoSend)
Menu->SendTo(Plr);
}
bool TradeForCoins(uint32 ItemId, uint8 reqAmt, Player* Plr)
{
if(Plr->GetItemInterface()->GetItemCount(TOKENID, false)>=reqAmt) {
//remove tokens
Plr->GetItemInterface()->RemoveItemAmt(TOKENID, reqAmt);
//add item
Item * pItem = objmgr.CreateItem(ItemId, Plr);
Plr->GetItemInterface()->AddItemToFreeSlot(pItem);
return true;
}else{
//not enough tokens
return false;
}
}
bool TradeMarks(Player* Plr)
{
if(Plr->GetItemInterface()->GetItemCount(MARKID,false)>=TRADERATE){
//remove marks
Plr->GetItemInterface()->RemoveItemAmt(MARKID, TRADERATE);
//add tokens
Item * pItem = objmgr.CreateItem(TOKENID,Plr);
Plr->GetItemInterface()->AddItemToFreeSlot(pItem);
return true;
}else{
//not enough marks to buy a token
return false;
}
}
bool TradeSet(uint32 ItemIdStart, uint32 ItemIdEnd, uint8 reqAmt, Player* Plr)
{
//Assuming ItemIdStart is lower than ItemIdEnd
//Double check your code or else infinite loop will occur
//And we certainly don't want that.
if(Plr->GetItemInterface()->GetItemCount(TOKENID, false) >= reqAmt){
//Remove coin
Plr->GetItemInterface()->RemoveItemAmt(TOKENID, reqAmt);
//Add set
for(int i=ItemIdStart; i<=ItemIdEnd; i++){
Item * pItem = objmgr.CreateItem(i, Plr);
Plr->GetItemInterface()->AddItemToFreeSlot(pItem);
}
return true;
}else{
//Not enough tokens
return false;
}
}
void Coin::GossipSelectOption(Object * pObject, Player* Plr, uint32 Id, uint32 IntId, const char * Code)
{
Creature * pCreature = (pObject->GetTypeId()==TYPEID_UNIT)?((Creature*)pObject):NULL;
if(pCreature==NULL)
return;
GossipMenu * Menu;
switch(IntId)
{
case 0: // Return to start
GossipHello(pCreature, Plr, true);
break;
case 1: //Category 1
objmgr.CreateGossipMenuForPlayer(&Menu, pCreature->GetGUID(), 1, Plr);
Menu->AddItem(5, "First item", 10);
Menu->AddItem(5, "Second item", 11);
Menu->AddItem(5, "Itemset", 12);
Menu->AddItem(0, "[Back]", 99);
Menu->SendTo(Plr);
break;
case 2: //Category 2
objmgr.CreateGossipMenuForPlayer(&Menu, pCreature->GetGUID(), 1, Plr);
Menu->AddItem(5, "First item", 20);
Menu->AddItem(5, "Item set", 21);
Menu->AddItem(0, "[Back]", 99);
Menu->SendTo(Plr);
break;
case 10: //Item 1
if (TradeForCoins(<itemid>, <itemprice>, Plr))
{Plr->BroadcastMessage(SUCMSG);}
else {Plr->BroadcastMessage(TOKMSG);}
objmgr.CreateGossipMenuForPlayer(&Menu, pCreature->GetGUID(), 1, Plr);
Menu->AddItem(0, "[Back]", 1);
Menu->SendTo(Plr);
break;
case 11: //Item 2
if (TradeForCoins(<itemid>, <itemprice>, Plr))
{Plr->BroadcastMessage(SUCMSG);}
else {Plr->BroadcastMessage(TOKMSG);}
objmgr.CreateGossipMenuForPlayer(&Menu, pCreature->GetGUID(), 1, Plr);
Menu->AddItem(0, "[Back]", 1);
Menu->SendTo(Plr);
break;
case 12: //Itemset
if (TradeSet(<itemid>, <itemid>, <itemprice>, Plr))
{Plr->BroadcastMessage(SUCMSG);}
else {Plr->BroadcastMessage(TOKMSG);}
objmgr.CreateGossipMenuForPlayer(&Menu, pCreature->GetGUID(), 1, Plr);
Menu->AddItem(0, "[Back]", 1);
Menu->SendTo(Plr);
break;
case 98: //Convert Marks to Token
if (TradeMarks(Plr))
{Plr->BroadcastMessage("Have fun with your token!");}
else {Plr->BroadcastMessage(MRKMSG);}
objmgr.CreateGossipMenuForPlayer(&Menu, pCreature->GetGUID(), 1, Plr);
Menu->AddItem(0, "[Back]", 1);
Menu->SendTo(Plr);
break;
case 99: //main menu
objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 1, Plr);
Menu->AddItem(0, "Convert 5 Marks for 1 Token", 98);
Menu->AddItem(0, "Category 1", 1);
Menu->AddItem(0, "Category 2", 2);
Menu->SendTo(Plr);
break;
} //end switch
} //end void
void Coin::GossipEnd(Object * pObject, Player* Plr)
{
GossipScript::GossipEnd(pObject, Plr);
}
void SetupCoin(ScriptMgr * mgr)
{
GossipScript * gs = (GossipScript*) new Coin();
mgr->register_gossip_script(NPCID, gs);
}
Don't forget to add the gossip NPC in the database.
If you want it to be portable, you can bind the menu to an item, and have a [Portable Mall], like so:
Code:
#include "StdAfx.h"
#include "Setup.h"
#ifdef WIN32
#pragma warning(disable:4305) // warning C4305: 'argument' : truncation from 'double' to 'float'
#endif
#define MARKID 90909 //ID for the mark
#define TOKENID 91919 //ID for the token.
#define TRADERATE 5 //This much marks = 1 token
#define SUCMSG "Enjoy your prize smile.gif" //Message when user gets his prize
#define TOKMSG "You don't have enough tokens to buy this"
#define MRKMSG "You don't have enough marks to get a token"
//Defining Warper
class SCRIPT_DECL Warper2 : public GossipScript
{
public:
void GossipHello(Object * pObject, Player* Plr, bool AutoSend);
void GossipSelectOption(Object * pObject, Player* Plr, uint32 Id, uint32 IntId, const char * Code);
void GossipEnd(Object * pObject, Player* Plr);
void Destroy()
{
delete this;
}
};
bool TradeForCoins(uint32 ItemId, uint8 reqAmt, Player* Plr)
{
if(Plr->GetItemInterface()->GetItemCount(TOKENID, false)>=reqAmt) {
//remove tokens
Plr->GetItemInterface()->RemoveItemAmt(TOKENID, reqAmt);
//add item
Item * pItem = objmgr.CreateItem(ItemId, Plr);
Plr->GetItemInterface()->AddItemToFreeSlot(pItem);
return true;
}else
{
//not enough tokens
return false;
}
}
bool TradeMarks(Player* Plr)
{
if(Plr->GetItemInterface()->GetItemCount(MARKID,false)>=TRADERATE){
//remove marks
Plr->GetItemInterface()->RemoveItemAmt(MARKID, TRADERATE);
//add tokens
Item * pItem = objmgr.CreateItem(TOKENID,Plr);
Plr->GetItemInterface()->AddItemToFreeSlot(pItem);
return true;
}else{
//not enough marks to buy a token
return false;
}
}
bool TradeSet(uint32 ItemIdStart, uint32 ItemIdEnd, uint8 reqAmt, Player* Plr)
{
//Assuming ItemIdStart is lower than ItemIdEnd
//Double check your code or else infinite loop will occur
//And we certainly don't want that.
if(Plr->GetItemInterface()->GetItemCount(TOKENID, false) >= reqAmt){
//Remove coin
Plr->GetItemInterface()->RemoveItemAmt(TOKENID, reqAmt);
//Add set
for(int i=ItemIdStart; i<=ItemIdEnd; i++){
Item * pItem = objmgr.CreateItem(i, Plr);
Plr->GetItemInterface()->AddItemToFreeSlot(pItem);
}
return true;
}else{
//Not enough tokens
return false;
}
}
void Warper2::GossipHello(Object* pObject, Player * Plr, bool AutoSend)
{
GossipMenu *Menu;
objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 2593, Plr);
Menu->AddItem(0, "Convert 5 Marks to 1 Token", 1);
Menu->AddItem(0, "Tier 7 Sets", 2);
//Menu->AddItem(0, "Tier 7 Parts", 3);
Menu->AddItem(0, "Other Items", 4);
if(AutoSend)
Menu->SendTo(Plr);
};
//Defining Cases
void Warper2::GossipSelectOption(Object* pObject, Player* Plr, uint32 Id, uint32 IntId, const char * Code)
{
GossipMenu * Menu;
switch(IntId)
{
case 1:
if (TradeMarks(Plr))
{Plr->BroadcastMessage("Have fun with your token!");}
else {Plr->BroadcastMessage(MRKMSG);}
objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 2593, Plr);
Menu->SendTo(Plr);
break;
case 2:
objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 2593, Plr);
Menu->AddItem(5, "Rogue - 10 Tokens", 10);
Menu->AddItem(5, "Warrior - 10 Tokens", 11);
Menu->AddItem(5, "Mage - 10 Tokens", 12);
//Menu->AddItem(5, "Shaman", 13);
//Menu->AddItem(5, "Warlock", 14);
//Menu->AddItem(5, "Paladin", 15);
//Menu->AddItem(5, "Priest", 16);
//Menu->AddItem(5, "Hunter", 17);
//Menu->AddItem(5, "Druid", 18);
Menu->SendTo(Plr);
break;
case 3:
objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 2593, Plr);
Menu->AddItem(5, "Rogue", 20);
Menu->AddItem(5, "Warrior", 21);
Menu->AddItem(5, "Mage", 22);
//Menu->AddItem(5, "Shaman", 23);
//Menu->AddItem(5, "Warlock", 24);
//Menu->AddItem(5, "Paladin", 25);
//Menu->AddItem(5, "Priest", 26);
//Menu->AddItem(5, "Hunter", 27);
//Menu->AddItem(5, "Druid", 28);
Menu->SendTo(Plr);
case 4:
objmgr.CreateGossipMenuForPlayer(&Menu, pObject->GetGUID(), 2593, Plr);
Menu->AddItem(5, "Flying Carpet - Flies in Azeroth - 20 Tokens", 31);
Menu->AddItem(5, "Phoenix - Flies in Azeroth - 35 Tokens", 32);
Menu->AddItem(5, "Endless Bag - 36 slots! - 1 Token", 33);
Menu->SendTo(Plr);
break;
case 10:
if (TradeSet(91000, 91007, 10, Plr))
{Plr->BroadcastMessage(SUCMSG);}
else {Plr->BroadcastMessage(TOKMSG);}
Plr->Gossip_Complete();
break;
case 11:
if (TradeSet(92000, 92007, 10, Plr))
{Plr->BroadcastMessage(SUCMSG);}
else {Plr->BroadcastMessage(TOKMSG);}
Plr->Gossip_Complete();
break;
case 12:
if (TradeSet(93000, 93007, 10, Plr))
{Plr->BroadcastMessage(SUCMSG);}
else {Plr->BroadcastMessage(TOKMSG);}
Plr->Gossip_Complete();
break;
case 31:
if (TradeForCoins(98988, 20, Plr))
{Plr->BroadcastMessage(SUCMSG);}
else {Plr->BroadcastMessage(TOKMSG);}
Plr->Gossip_Complete();
break;
case 32:
if (TradeForCoins(90001, 35, Plr))
{Plr->BroadcastMessage(SUCMSG);}
else {Plr->BroadcastMessage(TOKMSG);}
Plr->Gossip_Complete();
break;
case 33:
if (TradeForCoins(90003, 1, Plr))
{Plr->BroadcastMessage(SUCMSG);}
else {Plr->BroadcastMessage(TOKMSG);}
Plr->Gossip_Complete();
break;
}
};
void Warper2::GossipEnd(Object * pObject, Player* Plr)
{
GossipScript::GossipEnd(pObject, Plr);
}
void SetupWarper2(ScriptMgr * mgr)
{
GossipScript * gs = (GossipScript*) new Warper2();
mgr->register_item_gossip_script(60002,gs);
}
Again don't forget to add an item with the entry 60002 (or change the entry in the code) with spell 33208.