Tradeskills.cpp
Code:
void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac) {
//get our packet ready, gotta send one no matter what...
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RecipeAutoCombine, sizeof(RecipeAutoCombine_Struct));
RecipeAutoCombine_Struct *outp = (RecipeAutoCombine_Struct *)outapp->pBuffer;
outp->object_type = rac->object_type;
outp->some_id = rac->some_id;
outp->unknown1 = rac->unknown1;
outp->recipe_id = rac->recipe_id;
outp->reply_code = 0xFFFFFFF5; //default fail.
<! SkillType tskill = Object::TypeToSkill(rac->object_type);
<! if(tskill == TradeskillUnknown) {
<! LogFile->write(EQEMuLog::Error, "Unknown container type for HandleAutoCombine: %d\n", rac->object_type);
<! user->QueuePacket(outapp);
<! safe_delete(outapp);
<! return;
<! }
<!
//ask the database for the recipe to make sure it exists...
DBTradeskillRecipe_Struct spec;
<! if (!database.GetTradeRecipe(rac->recipe_id, rac->object_type, tskill, &spec)) {
>! if (!database.GetTradeRecipe(rac->recipe_id, rac->object_type, rac->some_id, &spec)) {
LogFile->write(EQEMuLog::Error, "Unknown recipe for HandleAutoCombine: %u\n", rac->recipe_id);
user->QueuePacket(outapp);
safe_delete(outapp);
return;
}
char errbuf[MYSQL_ERRMSG_SIZE];
MYSQL_RES *result;
MYSQL_ROW row;
char *query = 0;
uint32 qlen = 0;
uint8 qcount = 0;
//pull the list of components
qlen = MakeAnyLenString(&query, "SELECT tre.item_id,tre.componentcount "
" FROM tradeskill_recipe_entries AS tre "
" WHERE tre.componentcount > 0 AND tre.recipe_id=%u", rac->recipe_id);
if (!database.RunQuery(query, qlen, errbuf, &result)) {
LogFile->write(EQEMuLog::Error, "Error in HandleAutoCombine query '%s': %s", query, errbuf);
safe_delete_array(query);
user->QueuePacket(outapp);
safe_delete(outapp);
return;
}
safe_delete_array(query);
qcount = mysql_num_rows(result);
if(qcount < 1) {
LogFile->write(EQEMuLog::Error, "Error in HandleAutoCombine: no components returned");
user->QueuePacket(outapp);
safe_delete(outapp);
return;
}
if(qcount > 10) {
LogFile->write(EQEMuLog::Error, "Error in HandleAutoCombine: too many components returned (%u)", qcount);
user->QueuePacket(outapp);
safe_delete(outapp);
return;
}
uint32 items[10];
memset(items, 0, sizeof(items));
uint8 counts[10];
memset(counts, 0, sizeof(counts));
//search for all the crap in their inventory
Inventory& user_inv = user->GetInv();
uint8 count = 0;
uint8 needcount = 0;
uint8 r,k;
for(r = 0; r < qcount; r++) {
row = mysql_fetch_row(result);
uint32 item = (uint32)atoi(row[0]);
uint8 num = (uint8) atoi(row[1]);
needcount += num;
//because a HasItem on items with num > 1 only returns the
//last-most slot... the results of this are useless to us
//when we go to delete them because we cannot assume it is in a single stack.
if(user_inv.HasItem(item, num, invWherePersonal) != SLOT_INVALID)
count += num;
//dont start deleting anything until we have found it all.
items[r] = item;
counts[r] = num;
}
mysql_free_result(result);
//make sure we found it all...
if(count != needcount) {
user->QueuePacket(outapp);
safe_delete(outapp);
return;
}
//now we know they have everything...
//remove all the items from the players inventory, with updates...
sint16 slot;
for(r = 0; r < qcount; r++) {
if(items[r] == 0 || counts[r] == 0)
continue; //skip empties, could prolly break here
//we have to loop here to delete 1 at a time in case its in multiple stacks.
for(k = 0; k < counts[r]; k++) {
slot = user_inv.HasItem(items[r], 1, invWherePersonal);
if(slot == SLOT_INVALID) {
//WTF... I just checked this above, but just to be sure...
//we cant undo the previous deletes without a lot of work.
//so just call it quits, this shouldent ever happen anyways.
user->QueuePacket(outapp);
safe_delete(outapp);
return;
}
user->DeleteItemInInventory(slot, 1, true);
}
}
//otherwise, we found it all...
outp->reply_code = 0x00000000; //success for finding it...
user->QueuePacket(outapp);
//DumpPacket(outapp);
safe_delete(outapp);
//now actually try to make something...
<! bool success = user->TradeskillExecute(&spec, tskill);
!> bool success = user->TradeskillExecute(&spec);
//TODO: find in-pack containers in inventory, make sure they are really
//there, and then use that slot to handle replace_container too.
if(success && spec.replace_container) {
// user->DeleteItemInInventory(in_combine->container_slot, 0, true);
}
}
Removed code that determines tradeskill from combiner type as it is no longer relevant
changed function call to GetTradeRecipe to pass some_id instead of tradeskill
changed function call to TradeskillExecute to remove tradeskill from parameter list as it is now included in spec