/**************************************************************************/
// mix.cpp - mixture code, Kerenos
/***************************************************************************
* The Dawn of Time v1.69r (c)1997-2004 Michael Garratt *
* >> A number of people have contributed to the Dawn codebase, with the *
* majority of code written by Michael Garratt - www.dawnoftime.org *
* >> To use this source code, you must fully comply with the dawn license *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
**************************************************************************/
#include "include.h"
#include "db.h"
void mix_bsort( vn_int array[], sh_int num[], int size );
void empty_container( OBJ_DATA *container );
#define BADMIX_LVNUM 445
#define BADMIX_HVNUM 449
/**************************************************************************/
// semilocalized globals
extern mix_data *mix_list;
/**************************************************************************/
void do_herbalism( char_data *ch, char *argument)
{
mix_data *m;
OBJ_DATA *container;
OBJ_DATA *obj;
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;
// see if they know how to mix herbs in the first place
if ( get_skill( ch, gsn_herbalism ) == 0 )
{
ch->println( "You don't know the first thing about mixing herbs." );
return;
}
if ( IS_NULLSTR( argument ))
{
ch->println( "You must specify a valid cauldron or mortar in which to mix your herbs." );
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 mix herbs in that." );
return;
}
case ITEM_FLASK:
{
ch->println( "You can't mix herbs in that in this way, try using mixflask instead." );
return;
}
case ITEM_MORTAR:
case ITEM_CAULDRON:
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_HERBALISM )
{
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, but they 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 mix the ingredients within %s and have concocted %s.",
container->short_descr, m->rshort );
act( "$n busies $mself and mixes a concoction within $p.", ch, container, NULL, TO_ROOM );
empty_container( container );
obj_to_obj( result, container );
WAIT_STATE( ch, skill_table[gsn_herbalism].beats );
check_improve( ch, gsn_herbalism, 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 mix the ingredients within %s and have concocted %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 mixes a concoction within $p.", ch, container, NULL, TO_ROOM );
WAIT_STATE( ch, skill_table[gsn_herbalism].beats );
check_improve( ch, gsn_herbalism, true, 3 );
empty_container( container );
obj_to_obj( result, container );
}
};
/**************************************************************************/
// mixflask only version of herbalism - Kal, Sept 02
void do_mixflask( char_data *ch, char *argument)
{
mix_data *m;
OBJ_DATA *container;
OBJ_DATA *obj;
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;
if ( IS_NULLSTR( argument )){
ch->println( "Syntax: mixflask <flask> - to mix herbs in a flask.");
ch->println( "This command requires the herbalism skill to use." );
return;
}
// see if they know how to mix herbs in the first place
if ( get_skill( ch, gsn_herbalism ) == 0 )
{
ch->println( "You don't know the first thing about mixing herbs." );
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 mix herbs in that." );
return;
}
case ITEM_MORTAR:
case ITEM_CAULDRON:
{
ch->println( "You can't use mixflask to mix herbs in that, try using herbalism!" );
return;
}
case ITEM_FLASK:
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_HERBALISM )
{
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, but they 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( "Object vnum %d is missing for the %s mix (template object), "
"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 mix the ingredients within %s and have concocted %s.",
container->short_descr, m->rshort );
act( "$n busies $mself and mixes a concoction within $p.", ch, container, NULL, TO_ROOM );
extract_obj(container);
obj_to_char( result, ch);
WAIT_STATE( ch, skill_table[gsn_herbalism].beats );
check_improve( ch, gsn_herbalism, true, 3 );
}
// failed, create a bad result
else
{
OBJ_INDEX_DATA *obj_template;
OBJ_DATA *result;
int badvnum=number_range( BADMIX_LVNUM, BADMIX_HVNUM );
if (( obj_template = get_obj_index(badvnum)) == NULL )
{
ch->printlnf( "Vnum %d (between BADMIX_LVNUM(%d) and BADMIX_HVNUM(%d)) is missing for the %s mix, write a note to realm/admin",
badvnum, BADMIX_LVNUM, BADMIX_HVNUM, m->name );
return;
}
result = create_object( obj_template);
ch->printlnf( "You mix the ingredients within %s and have concocted %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 mixes a concoction within $p.", ch, container, NULL, TO_ROOM );
WAIT_STATE( ch, skill_table[gsn_herbalism].beats );
check_improve( ch, gsn_herbalism, true, 3 );
extract_obj( container );
obj_to_char( result, ch);
}
};
/**************************************************************************/
void empty_container( OBJ_DATA *container )
{
OBJ_DATA *obj;
OBJ_DATA *obj_next;
if ( container->contains == NULL )
return;
for ( obj = container->contains; obj; obj = obj_next )
{
obj_next = obj->next_content;
extract_obj( obj );
}
}
/**************************************************************************/