PDA

View Full Version : Zone project, command.cpp, set_adventure_points


KhanhDescending
09-09-2007, 05:05 AM
Noticed that the #setadventurepoints command wasn't working correctly, so thought I'd take a shot at fixing it. Compiled and built, then ran EQEmu using the new zone.exe. Tested in-game, and appears to work correctly. You can assign X points to a particular theme (1 thru 5). Or choose theme 0, and then X points will be distributed across all themes.

void command_set_adventure_points(Client *c, const Seperator *sep)
{
Client *t=c;

if(c->GetTarget() && c->GetTarget()->IsClient())
t=c->GetTarget()->CastToClient();

if(!sep->arg[2][0])
{
c->Message(0, "Usage: #setadventurepoints [points] [theme]");
return;
}

c->Message(0, "Updating adventure points for %s", t->GetName());
t->UpdateLDoNPoints(atoi(sep->arg[1]),atoi(sep->arg[2]));
}

Basically, the command now expects 2 arguments instead of 1. And the call to UpdateLDoNPoints will pass these arguments. Previously, it was passing (0,1) which always assigned 0 points to the LGuk theme. Essentially doing nothing at all.

John Adams
09-09-2007, 08:01 AM
Very cool, thanks for this. While you're digging around, you want to figure out how to make those points "spendable" on Adventure Merchants? Maybe it's already there, but I could never assign points (or hadn't gotten to make a script to do it yet).

What do you think?

KhanhDescending
09-10-2007, 03:59 PM
Actually, yes. Need to modify method/procedure Client::Handle_OP_AdventureMerchantPurchase (located in the client_packet.cpp file in the Zone project)

I'm fairly certain the switch statement I added is rather unnecessary. After testing this in EQ, it appears either the client or another piece of code is already verifying the player has enough points, of the right type, to purchase the item. This statement...

if(!UpdateLDoNPoints(requiredpts,item->LDoNTheme))
return;

...appears to be the key, since it now passes the LDONTheme as the second parameter.

Here's the full code for the procedure, including what I modified.

void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app)
{
if (app->size != sizeof(Adventure_Purchase_Struct))
{
LogFile->write(EQEMuLog::Error, "OP size error: OP_AdventureMerchantPurchase expected:%i got:%i", sizeof(Adventure_Purchase_Struct), app->size);
return;
}

Adventure_Purchase_Struct* aps = (Adventure_Purchase_Struct*)app->pBuffer;
/*
Get item apc->itemid (can check NPC if thats necessary), ldon point theme check only if theme is not 0 (I am not sure what 1-5 are though for themes)
if(ldon_points_available >= item ldonpointcost)
{
give item (67 00 00 00 for the packettype using opcode 0x02c5)
ldon_points_available -= ldonpointcost;
}
*/
int32 merchantid = 0;
Mob* tmp = entity_list.GetMob(aps->npcid);
if (tmp == 0 || !tmp->IsNPC() || tmp->GetClass() != ADVENTUREMERCHANT)
return;

//you have to be somewhat close to them to be properly using them
if(DistNoRoot(*tmp) > USE_NPC_RANGE2)
return;

merchantid = tmp->CastToNPC()->MerchantType;

const Item_Struct* item = NULL;
bool found = false;
std::list<MerchantList> merlist = zone->merchanttable[merchantid];
std::list<MerchantList>::const_iterator itr;

for(itr = merlist.begin();itr != merlist.end();itr++){
MerchantList ml = *itr;
item = database.GetItem(ml.item);
if(!item)
continue;
if(item->ID == aps->itemid) { //This check to make sure that the item is actually on the NPC, people attempt to inject packets to get items summoned...
found = true;
break;
}
}

if (!item || !found) {
Message(13, "Error: The item you purchased does not exist!");
return;
}

// Determine if there are sufficient points to buy the item

bool CanAfford = true;
switch(sint32(item->LDoNTheme))
{
case 0: { // handle generic points (theme=0)
if(m_pp.ldon_points_available < sint32(item->LDoNPrice))
CanAfford = false;
break;
}
case 1: {
if(m_pp.ldon_points_guk < sint32(item->LDoNPrice))
CanAfford = false;
break;
}
case 2: {
if(m_pp.ldon_points_mir < sint32(item->LDoNPrice))
CanAfford = false;
break;
}
case 3: {
if(m_pp.ldon_points_mmc < sint32(item->LDoNPrice))
CanAfford = false;
break;
}
case 4: {
if(m_pp.ldon_points_ruj < sint32(item->LDoNPrice))
CanAfford = false;
break;
}
case 5: {
if(m_pp.ldon_points_tak < sint32(item->LDoNPrice))
CanAfford = false;
break;
}
}

if(CanAfford = false) {
Message(13, "You cannot afford that item.");
return;
}

sint32 requiredpts = (sint32)item->LDoNPrice*-1;
if(!UpdateLDoNPoints(requiredpts,item->LDoNTheme))
return;

sint8 charges=1;
if(item->MaxCharges != 0)
charges = item->MaxCharges;
SummonItem(aps->itemid, charges);
}

The last piece of the puzzle is selling LDoN-type items back to the Adventure Merchant. There is currently no existing method/procedure for this. So I've started toying with writing one from scratch. I'm not very familiar with EQEmu code, especially how opcodes are recognized and handled. So I can't guarantee any success with it.

I'm running a small server for friends and family, so my goal is to modify the loot tables so that "adventure tokens" can drop randomly from various named NPCs in the game. These "tokens" would be an item in the Items database table, and have an associated LDoN price. If you managed to loot them, you could then turn around and redeem them at an Adventure Merchant for points. Eventually accumulating enough points to buy augments or other equipment. Modifying the database is easy enough, but it all depends on the ability to sell items back to an Adventure Merchant.

With the LDoN zones and quests sitting in various stages of development, this is the only semi-fair way I could think of for obtaining LDoN gear...

If I come up with anything, I'll post it here for you.

gernblan
09-11-2007, 09:49 AM
This needs to be in the source tree, pronto!

GREAT job!