View Single Post
  #9  
Old 05-25-2007, 10:58 AM
Darkonig
Hill Giant
 
Join Date: Dec 2006
Posts: 102
Default

Code:
bool ZoneDatabase::GetTradeRecipe(const ItemInst* container, uint8 c_type, uint32 some_id, 
	DBTradeskillRecipe_Struct *spec)
{
	char errbuf[MYSQL_ERRMSG_SIZE];
    MYSQL_RES *result;
    MYSQL_ROW row;
    char *query = 0;
	char buf2[2048];
	
	uint32 sum = 0;
	uint32 count = 0;
	uint32 qcount = 0;
	uint32 qlen = 0;

	// make where clause segment for container(s)
	char containers[30];
	if (some_id == 0) {
		// world combiner so no item number
		snprintf(containers,29, "= %u", c_type);
	} else {
		// container in inventory
		snprintf(containers,29, "in (%u,%u)", c_type, some_id);
	}

	buf2[0] = '\0';
	
	//Could prolly watch for stacks in this loop and handle them properly...
	//just increment sum and count accordingly
	bool first = true;
	uint8 i;
	char *pos = buf2;
	for (i=0; i<10; i++) {
		const ItemInst* inst = container->GetItem(i);
		if (inst) {
			const Item_Struct* item = GetItem(inst->GetItem()->ID);
			if (item) {
				if(first) {
					pos += snprintf(pos, 19, "%d", item->ID);
					first = false;
				} else {
					pos += snprintf(pos, 19, ",%d", item->ID);
				}
				sum += item->ID;
				count++;
			}
		}
	}
	*pos = '\0';
	
	if(count < 1) {
		return(false);	//no items == no recipe
	}
	
	qlen = MakeAnyLenString(&query, "SELECT tre.recipe_id "
	" FROM tradeskill_recipe_entries AS tre"
	" WHERE ( tre.item_id IN(%s) AND tre.componentcount>0 )"
	"  OR ( tre.item_id %s AND tre.iscontainer=1 )"
	" GROUP BY tre.recipe_id HAVING sum(tre.componentcount) = %u"
	"  AND sum(tre.item_id * tre.componentcount) = %u", buf2, containers, count, sum);
	
	if (!RunQuery(query, qlen, errbuf, &result)) {
		LogFile->write(EQEMuLog::Error, "Error in GetTradeRecipe search, query: %s", query);
		safe_delete_array(query);
		LogFile->write(EQEMuLog::Error, "Error in GetTradeRecipe search, error: %s", errbuf);
		return(false);
	}
	safe_delete_array(query);
	
	qcount = mysql_num_rows(result);
	if(qcount > 1) {
		//multiple recipes, partial match... do an extra query to get it exact.
		//this happens when combining components for a smaller recipe
		//which is completely contained within another recipe
		
		first = true;
		pos = buf2;
		for (i = 0; i < qcount; i++) {
			row = mysql_fetch_row(result);
			uint32 recipeid = (uint32) atoi(row[0]);
			if(first) {
				pos += snprintf(pos, 19, "%u", recipeid);
				first = false;
			} else {
				pos += snprintf(pos, 19, ",%u", recipeid);
			}
			//length sanity check on buf2
			if(pos > (buf2 + 2020))
				break;
		}
		
		qlen = MakeAnyLenString(&query, "SELECT tre.recipe_id"
		" FROM tradeskill_recipe_entries AS tre"
		" WHERE tre.recipe_id IN (%s)"
		" GROUP BY tre.recipe_id HAVING sum(tre.componentcount) = %u"
		"  AND sum(tre.item_id * tre.componentcount) = %u", buf2, count, sum);
		
		if (!RunQuery(query, qlen, errbuf, &result)) {
			LogFile->write(EQEMuLog::Error, "Error in GetTradeRecipe, re-query: %s", query);
			safe_delete_array(query);
			LogFile->write(EQEMuLog::Error, "Error in GetTradeRecipe, error: %s", errbuf);
			return(false);
		}
		safe_delete_array(query);
	
		qcount = mysql_num_rows(result);
	}
	if (qcount != 1) {
		if(qcount > 1) {
			LogFile->write(EQEMuLog::Error, "Combine error: Recipe is not unique!");
		}
		//else, just not found i guess..
		return(false);
	}
	
	row = mysql_fetch_row(result);
	uint32 recipe_id = (uint32)atoi(row[0]);
	mysql_free_result(result);
	
	return(GetTradeRecipe(recipe_id, c_type, some_id, spec));
}
Code:
bool ZoneDatabase::GetTradeRecipe(uint32 recipe_id, uint8 c_type, uint32 some_id, 
	DBTradeskillRecipe_Struct *spec)
{	
	char errbuf[MYSQL_ERRMSG_SIZE];
    MYSQL_RES *result;
    MYSQL_ROW row;
    char *query = 0;
	
	uint32 qcount = 0;
	uint32 qlen;

	// make where clause segment for container(s)
	char containers[30];
	if (some_id == 0) {
		// world combiner so no item number
		snprintf(containers,29, "= %u", c_type);
	} else {
		// container in inventory
		snprintf(containers,29, "in (%u,%u)", c_type, some_id);
	}
	
	qlen = MakeAnyLenString(&query, "SELECT tr.id, tr.tradeskill, tr.skillneeded,"
	" tr.trivial, tr.nofail, tr.replace_container"
	" FROM tradeskill_recipe AS tr inner join tradeskill_recipe_entries as tre"
	" ON tr.id = tre.recipe_id"
	" WHERE tr.id = %lu AND tre.item_id %s"
	" GROUP BY tr.id", recipe_id, containers);
		
	if (!RunQuery(query, qlen, errbuf, &result)) {
		LogFile->write(EQEMuLog::Error, "Error in GetTradeRecipe, query: %s", query);
		safe_delete_array(query);
		LogFile->write(EQEMuLog::Error, "Error in GetTradeRecipe, error: %s", errbuf);
		return(false);
	}
	safe_delete_array(query);
	
	qcount = mysql_num_rows(result);
	if(qcount != 1) {
		//just not found i guess..
		return(false);
	}
	
	row = mysql_fetch_row(result);
	spec->tradeskill			= (SkillType)atoi(row[1]);
	spec->skill_needed		= (sint16)atoi(row[2]);
	spec->trivial			= (uint16)atoi(row[3]);
	spec->nofail			= atoi(row[4]) ? true : false;
	spec->replace_container	= atoi(row[5]) ? true : false;
	mysql_free_result(result);
	
	//Pull the on-success items...
	qlen = MakeAnyLenString(&query, "SELECT item_id,successcount FROM tradeskill_recipe_entries"
	 " WHERE successcount>0 AND componentcount=0 AND recipe_id=%u", recipe_id);
	 
	if (!RunQuery(query, qlen, errbuf, &result)) {
		LogFile->write(EQEMuLog::Error, "Error in GetTradeRecept success query '%s': %s", query, errbuf);
		safe_delete_array(query);
		return(false);
	}
	safe_delete_array(query);
	
	qcount = mysql_num_rows(result);
	if(qcount < 1) {
		LogFile->write(EQEMuLog::Error, "Error in GetTradeRecept success: no success items returned");
		return(false);
	}
	uint8 r;
	spec->onsuccess.clear();
	for(r = 0; r < qcount; r++) {
		row = mysql_fetch_row(result);
		/*if(r == 0) {
			*product1_id	= (uint32)atoi(row[0]);
			*productcount	= (uint32)atoi(row[1]);
		} else if(r == 1) {
			*product2_id	= (uint32)atoi(row[0]);
		} else {
			LogFile->write(EQEMuLog::Warning, "Warning: recipe returned more than 2 products, not yet supported.");
		}*/
		uint32 item = (uint32)atoi(row[0]);
		uint8 num = (uint8) atoi(row[1]);
		spec->onsuccess.push_back(pair<uint32,uint8>::pair(item, num));
	}
	mysql_free_result(result);
	
	
	//Pull the on-fail items...
	qlen = MakeAnyLenString(&query, "SELECT item_id,failcount FROM tradeskill_recipe_entries"
	 " WHERE failcount>0 AND componentcount=0 AND recipe_id=%u", recipe_id);

	spec->onfail.clear();
	if (RunQuery(query, qlen, errbuf, &result)) {
		
		qcount = mysql_num_rows(result);
		uint8 r;
		for(r = 0; r < qcount; r++) {
			row = mysql_fetch_row(result);
			/*if(r == 0) {
				*failproduct_id	= (uint32)atoi(row[0]);
			} else {
				LogFile->write(EQEMuLog::Warning, "Warning: recipe returned more than 1 fail product, not yet supported.");
			}*/
			uint32 item = (uint32)atoi(row[0]);
			uint8 num = (uint8) atoi(row[1]);
			spec->onfail.push_back(pair<uint32,uint8>::pair(item, num));
		}
		mysql_free_result(result);
	}
	safe_delete_array(query);
	
	return(true);
}
Reply With Quote