// crafts
	HASH_ITER(hh, craft_table, craft, next_craft) {
		if (GET_CRAFT_TYPE(craft) == CRAFT_TYPE_BUILD && GET_CRAFT_BUILD_TYPE(craft) == vnum) {
			GET_CRAFT_BUILD_TYPE(craft) = NOTHING;
			SET_BIT(GET_CRAFT_FLAGS(craft), CRAFT_IN_DEVELOPMENT);
			save_library_file_for_vnum(DB_BOOT_CRAFT, GET_CRAFT_VNUM(craft));
		}
	}
/**
* Checks for common craft recipe problems and reports them to ch.
*
* @param craft_data *craft The item to audit.
* @param char_data *ch The person to report to.
* @return bool TRUE if any problems were reported; FALSE if all good.
*/
bool audit_craft(craft_data *craft, char_data *ch) {
	bool problem = FALSE;

	if (GET_CRAFT_REQUIRES_OBJ(craft) == NOTHING && GET_CRAFT_ABILITY(craft) == NO_ABIL) {
		olc_audit_msg(ch, GET_CRAFT_VNUM(craft), "Craft requires no object or ability");
		problem = TRUE;
	}
	if (IS_SET(GET_CRAFT_FLAGS(craft), CRAFT_IN_DEVELOPMENT)) {
		olc_audit_msg(ch, GET_CRAFT_VNUM(craft), "IN-DEVELOPMENT");
		problem = TRUE;
	}
	if (!IS_SET(GET_CRAFT_FLAGS(craft), CRAFT_APIARIES | CRAFT_GLASS) && GET_CRAFT_RESOURCES(craft)[0].vnum == NOTHING) {
		olc_audit_msg(ch, GET_CRAFT_VNUM(craft), "Craft requires no resources");
		problem = TRUE;
	}
	if (!IS_SET(GET_CRAFT_FLAGS(craft), CRAFT_SOUP) && (GET_CRAFT_OBJECT(craft) == NOTHING || !obj_proto(GET_CRAFT_OBJECT(craft))) && (GET_CRAFT_BUILD_TYPE(craft) == NOTHING || !building_proto(GET_CRAFT_BUILD_TYPE(craft)))) {
		olc_audit_msg(ch, GET_CRAFT_VNUM(craft), "Craft makes nothing");
		problem = TRUE;
	}
	if (!str_cmp(GET_CRAFT_NAME(craft), "unnamed recipe")) {
		olc_audit_msg(ch, GET_CRAFT_VNUM(craft), "Craft not named");
		problem = TRUE;
	}
	if (GET_CRAFT_TYPE(craft) == CRAFT_TYPE_ERROR) {
		olc_audit_msg(ch, GET_CRAFT_VNUM(craft), "Craft type not set");
		problem = TRUE;
	}
	if (GET_CRAFT_TYPE(craft) != CRAFT_TYPE_BUILD && GET_CRAFT_OBJECT(craft) != NOTHING && GET_CRAFT_OBJECT(craft) != GET_CRAFT_VNUM(craft)) {
		olc_audit_msg(ch, GET_CRAFT_VNUM(craft), "Craft creates item with different vnum");
		problem = TRUE;
	}
	if (GET_CRAFT_TYPE(craft) == CRAFT_TYPE_BUILD && GET_CRAFT_BUILD_TYPE(craft) != NOTHING && GET_CRAFT_BUILD_TYPE(craft) != GET_CRAFT_VNUM(craft)) {
		olc_audit_msg(ch, GET_CRAFT_VNUM(craft), "Craft creates building with different vnum");
		problem = TRUE;
	}
	if (GET_CRAFT_QUANTITY(craft) == 0 && GET_CRAFT_TYPE(craft) != CRAFT_TYPE_BUILD) {
		olc_audit_msg(ch, GET_CRAFT_VNUM(craft), "Craft creates 0 quantity");
		problem = TRUE;
	}
	if (GET_CRAFT_TIME(craft) == 0 && GET_CRAFT_TYPE(craft) != CRAFT_TYPE_BUILD) {
		olc_audit_msg(ch, GET_CRAFT_VNUM(craft), "Craft requires 0 time");
		problem = TRUE;
	}
		
	return problem;
}
/**
* Creates a new craft table entry.
* 
* @param craft_vnum vnum The number to create.
* @return craft_data* The new recipe's prototypes.
*/
craft_data *create_craft_table_entry(craft_vnum vnum) {
	void add_craft_to_table(craft_data *craft);
	
	craft_data *craft;
	
	// sanity
	if (craft_proto(vnum)) {
		log("SYSERR: Attempting to insert craft at existing vnum %d", vnum);
		return craft_proto(vnum);
	}
	
	CREATE(craft, craft_data, 1);
	init_craft(craft);
	GET_CRAFT_VNUM(craft) = vnum;
	add_craft_to_table(craft);

	// save index and craft file now
	save_index(DB_BOOT_CRAFT);
	save_library_file_for_vnum(DB_BOOT_CRAFT, vnum);

	return craft;
}
/**
* WARNING: This function actually deletes a craft recipe.
*
* @param char_data *ch The person doing the deleting.
* @param craft_vnum vnum The vnum to delete.
*/
void olc_delete_craft(char_data *ch, craft_vnum vnum) {
	void cancel_gen_craft(char_data *ch);
	void remove_craft_from_table(craft_data *craft);
	
	craft_data *craft;
	char_data *iter;
	
	if (!(craft = craft_proto(vnum))) {
		msg_to_char(ch, "There is no such craft %d.\r\n", vnum);
		return;
	}
	
	if (HASH_COUNT(craft_table) <= 1) {
		msg_to_char(ch, "You can't delete the last craft.\r\n");
		return;
	}
	
	// find players who are crafting it and stop them (BEFORE removing from table)
	for (iter = character_list; iter; iter = iter->next) {
		if (!IS_NPC(iter) && GET_ACTION(iter) == ACT_GEN_CRAFT && GET_ACTION_VNUM(iter, 0) == GET_CRAFT_VNUM(craft)) {
			msg_to_char(iter, "The craft you were making has been deleted.\r\n");
			cancel_gen_craft(iter);
		}
	}
	
	// remove from table -- nothing else to check here
	remove_craft_from_table(craft);

	// save index and craft file now
	save_index(DB_BOOT_CRAFT);
	save_library_file_for_vnum(DB_BOOT_CRAFT, vnum);
	
	syslog(SYS_OLC, GET_INVIS_LEV(ch), TRUE, "OLC: %s has deleted craft recipe %d", GET_NAME(ch), vnum);
	msg_to_char(ch, "Craft recipe %d deleted.\r\n", vnum);
	
	free_craft(craft);
}