Not sure which switch statement you are referring to so will post each of the modified methods.
Code:
// Perform tradeskill combine
// complete tradeskill rewrite by father nitwit, 8/2004
void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Object *worldo)
{
if (!user || !in_combine) {
LogFile->write(EQEMuLog::Error, "Client or NewCombine_Struct not set in Object::HandleCombine");
return;
}
Inventory& user_inv = user->GetInv();
PlayerProfile_Struct& user_pp = user->GetPP();
ItemInst* container = NULL;
ItemInst* inst = NULL;
uint8 c_type = 0xE8;
uint32 some_id = 0;
bool worldcontainer=false;
if (in_combine->container_slot == SLOT_WORLDCONTAINER) {
if(!worldo) {
user->Message(13, "Error: Server is not aware of the tradeskill container you are attempting to use");
return;
}
inst = worldo->m_inst;
c_type = worldo->m_type;
worldcontainer=true;
}
else {
inst = user_inv.GetItem(in_combine->container_slot);
if (inst) {
const Item_Struct* item = inst->GetItem();
if (item && inst->IsType(ItemClassContainer)) {
c_type = item->BagType;
some_id = item->ID;
}
}
}
if (!inst || !inst->IsType(ItemClassContainer)) {
user->Message(13, "Error: Server does not recognize specified tradeskill container");
return;
}
container = inst;
DBTradeskillRecipe_Struct spec;
if (!database.GetTradeRecipe(container, c_type, some_id, &spec)) {
user->Message_StringID(4,TRADESKILL_NOCOMBINE);
EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0);
user->QueuePacket(outapp);
safe_delete(outapp);
return;
}
switch (spec.tradeskill)
{
case ALCHEMY:
if (user_pp.class_ != SHAMAN)
user->Message(13, "This tradeskill can only be performed by a shaman.");
else if (user_pp.level < MIN_LEVEL_ALCHEMY)
user->Message(13, "You cannot perform alchemy until you reach level %i.", MIN_LEVEL_ALCHEMY);
return;
break;
case TINKERING:
if (user_pp.race != GNOME)
user->Message(13, "Only gnomes can tinker.");
return;
break;
case MAKE_POISON:
if (user_pp.class_ != ROGUE)
user->Message(13, "Only rogues can mix poisons.");
return;
break;
}
//do the check and send results...
bool success = user->TradeskillExecute(&spec);
// Send acknowledgement packets to client
EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0);
user->QueuePacket(outapp);
safe_delete(outapp);
//now clean out the containers.
if(worldcontainer){
container->Clear();
outapp = new EQApplicationPacket(OP_ClearObject,0);
user->QueuePacket(outapp);
safe_delete(outapp);
database.DeleteWorldContainer(worldo->m_id, zone->GetZoneID());
if(success && spec.replace_container) {
//should report this error, but we dont have the recipe ID, so its not very useful
LogFile->write(EQEMuLog::Error, "Replace container combine executed in a world container.");
}
} else{
for (uint8 i=0; i<10; i++){
const ItemInst* inst = container->GetItem(i);
if (inst) {
user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot,i),0,true);
}
}
container->Clear();
if(success && spec.replace_container) {
user->DeleteItemInInventory(in_combine->container_slot, 0, true);
}
}
}
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.
//ask the database for the recipe to make sure it exists...
DBTradeskillRecipe_Struct 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);
//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);
}
}
|