Snippet – Cooking

Snippet – Cooking

This snippet makes use of the existing mixedit feature of the Dawn of Time Codebase to create a cooking system for crafters. The cooking snippet makes use of the herbalism code. Recipes are built the same way with mixedit. You will need to create item types POT and PAN for players to cook their food in. They’ll also need a fire nearby. Compatible with version R of Dawn of Time.

In mix.cpp, below void do_herbalism add:

void do_cook( char_data *ch, char *argument)
{
	mix_data	*m;
	OBJ_DATA	*container;
	OBJ_DATA	*obj;
	OBJ_DATA		*fire;
	ROOM_INDEX_DATA	*pIndexRoom = ch->in_room;
	vn_int		vnum_elements[6], vtemp = 0;
	sh_int		num_elements[6];
	int			total_elements = 0;
	int			i;
	int			chance;
	int			level;
	bool		mFound = false;
	bool			foundfire = false;

	for ( fire = pIndexRoom->contents; fire; fire = fire->next_content ) {
		if ( fire->pIndexData->vnum == OBJ_VNUM_FIRE ) {
			foundfire = true;
			break;
		}
    }

	if ( !foundfire ) {
		ch->println("There needs to be a fire for you to cook properly.");
		return;
	}


	// see if they know how to cook in the first place
	if ( get_skill( ch, gsn_cook ) == 0 )
	{
		ch->println( "You don't know the first thing about cooking." );
		return;
	}

	if ( IS_NULLSTR( argument ))
	{
		ch->println( "You must specify a valid pot or pan in which to cook your ingredients." );
		return;
	}

	// start off easy, get the container obj
	if (( container = get_obj_carry( ch, argument )) == NULL )
	{
		ch->println( "You are not carrying that." );
		return;
	}

	// determine if it's a valid container
	switch ( container->item_type )
	{
	default:
		{
			ch->println( "You can't cook with that." );
			return;
		}
	case ITEM_CAULDRON:
		{
			ch->println( "You can't cook in a cauldron.\nThose are for making potions." );
			return;
		}
	case ITEM_POT:
	case ITEM_PAN:
		break;
	}

	// check for an empty container to crap out at the earliest point
	if ( container->contains == NULL )
	{
		ch->printlnf( "There is nothing in %s.", container->short_descr );
		return;
	}

	// initialize
	for ( i = 0; i < 5; i++ )
	{
		num_elements[i]  = 0;
		vnum_elements[i] = 0;
	}

	// main counting loop to catalogue all the items in the container
	for ( obj = container->contains; obj; obj = obj->next_content )
	{
		vtemp = obj->pIndexData->vnum;

		for ( i=0; i < 5; i++ )
		{
			// increment count of elements if same object found
			if ( vtemp == vnum_elements[i] )
			{
				num_elements[i]++;
				break;
			}
			else if ( vnum_elements[i] == 0 )
			{
				// found a new unique item
				vnum_elements[i] = vtemp;
				num_elements[i]++;
				total_elements++;
				break;
			}
		}
	}

	// finally catalogued all items in the container, time to sort'em
	mix_bsort( vnum_elements, num_elements, 5 );
	
	// time to compare the catalogued contents vs the mixture dbase
	// by now, both are sorted by this point for easier comparison
	for ( m = mix_list; m; m = m->next )
	{
		if ( m->type == MIXTYPE_COOKING )
		{
			for ( i = 0; i < 5; i++ )
			{
				mFound = false;
				if (!( vnum_elements[i] == m->ingredients[i] 
					&& num_elements[i]  == m->ingredients_num[i] ))
				{
					mFound = false;
					break;
				}
				mFound = true;
			}
		}
		if ( mFound )
			break;
	}

	// if we didn't find a matching mix, ditch all the ingredients
	if ( !mFound )
	{
		ch->println( "You try to combine the ingredients.\nThey yield no useful result." );
		empty_container( container );
		return;
	}

	level = UMAX(1, ch->level - (( 5 - modifier_table[m->difficulty].type ) * 3 ));
	if ( !IS_IMMORTAL(ch) && level > LEVEL_HERO ){
		level = LEVEL_HERO;
	}

	// VESSEL CHECK ?

	// skill check to see if the result will happen or not
	chance = (( get_skill( ch, gsn_herbalism ) - m->difficulty ) + ch->modifiers[STAT_IN] );
	if ( chance >= number_percent() )
	{
		OBJ_INDEX_DATA	*obj_template;
		OBJ_DATA		*result;
		
		// success, let's restring
		if (( obj_template = get_obj_index( m->vnum_template )) == NULL )
		{
			ch->printlnf( "Vnum %d is missing for the %s mix, write a note to realm/admin",
				m->vnum_template, m->name );
			return;
		}

		result = create_object( obj_template);

		replace_string( result->name,		 m->rname );
		replace_string( result->short_descr, m->rshort );
		replace_string( result->description, m->rlong  );

		result->level			= ch->level;
		result->item_type		= m->ritem_type;
		result->wear_flags		= m->rwear;
		
		for ( i = 1; i < 5; i++ ){
			result->value[i]	= m->rvalue[i];
		}
		result->value[0]		= level;

		ch->printlnf( "You cook the ingredients within %s.\nYou have made %s.",
			container->short_descr, m->rshort );
		act( "$n busies $mself and cooks some food within $p.", ch, container, NULL, TO_ROOM );
		empty_container( container );
		obj_to_obj( result, container );
		WAIT_STATE( ch, skill_table[gsn_cook].beats );
		check_improve( ch, gsn_cook, true, 3 );
	}
	// failed, create a bad result
	else
	{
		OBJ_INDEX_DATA	*obj_template;
		OBJ_DATA		*result;

		if (( obj_template = get_obj_index( number_range( BADMIX_LVNUM, BADMIX_HVNUM ))) == NULL )
		{
			ch->printlnf( "Vnum %d (between BADMIX_LVNUM and BADMIX_HVNUM) is missing for the %s mix, write a note to realm/admin",
				m->vnum_template, m->name );
			return;
		}
		result = create_object( obj_template);
		ch->printlnf( "You cook the ingredients within  %s and have made %s.",
			container->short_descr, m->rshort );

		replace_string( result->name,		 m->rname );
		replace_string( result->short_descr, m->rshort );
		replace_string( result->description, m->rlong  );
		result->level= level;

		act( "$n busies $mself and cooks some food within $p.", ch, container, NULL, TO_ROOM );
		WAIT_STATE( ch, skill_table[gsn_cook].beats );
		check_improve( ch, gsn_cook, true, 3 );
		empty_container( container );
		obj_to_obj( result, container );
	}
}