#include <ctype.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include "define.h"
#include "struct.h"
/*
* DRINK ROUTINES
*/
void do_drink( char_data* ch, char* argument )
{
obj_data* obj;
if( !strncasecmp( argument, "from ", 5 ) )
argument += 5;
if( *argument == '\0' ) {
if( ( obj = find_type( *ch->array,
ITEM_FOUNTAIN ) ) == NULL ) {
send( ch, "Drink what?\n\r" );
return;
}
obj->selected = 1;
}
else {
if( ( obj = one_object( ch, argument,
"drink", &ch->contents, ch->array ) ) == NULL )
return;
}
include_empty = FALSE;
include_liquid = FALSE;
drink( ch, obj );
include_empty = TRUE;
include_liquid = TRUE;
}
bool drink( char_data* ch, obj_data* obj )
{
content_array* where;
int amount;
int liquid;
int alcohol;
int spell;
if( obj->pIndexData->item_type != ITEM_FOUNTAIN
&& obj->pIndexData->item_type != ITEM_DRINK_CON ) {
send( ch, "You can't drink from %s.\n\r", obj );
return FALSE;
}
if( obj->value[1] == 0 ) {
send( ch, "%s is already empty.\n\r", obj );
return FALSE;
}
if( ch->species == NULL && ch->pcdata->condition[ COND_THIRST ] > 40 ) {
send( ch, "You do not feel thirsty.\n\r" );
return FALSE;
}
if( ( liquid = obj->value[2] ) >= table_max[ TABLE_LIQUID ]
|| liquid < 0 ) {
bug( "Do_drink: bad liquid number. (Obj# %d, Liq# %d)",
obj->pIndexData->vnum, liquid );
liquid = obj->value[2] = 0;
}
amount = min( number_range( 20, 40 ),
( obj->value[1] == -1 ? 70 : obj->value[1] ) );
alcohol = amount*liquid_table[liquid].alcohol/10;
send( ch, "You drink %s%s from %s.\n\r",
obj->value[1] == amount ? "the last drops of " : "",
liquid_name( obj ), obj );
send_seen( ch, "%s drinks %s from %s.\n\r",
ch, liquid_name( obj ), obj );
if( ch->pcdata != NULL ) {
ch->pcdata->condition[ COND_ALCOHOL ] += (alcohol+1)/2;
gain_drunk( ch, alcohol/2 );
}
gain_condition( ch, COND_FULL, amount*liquid_table[liquid].hunger/10 );
gain_condition( ch, COND_THIRST, amount*liquid_table[liquid].thirst/10 );
if( obj->value[1] != -1 ) {
where = obj->array;
obj = (obj_data*) obj->From( 1 );
if( ( obj->value[1] -= amount ) == 0 )
remove_bit( obj->extra_flags, OFLAG_KNOWN_LIQUID );
obj->To( where );
}
if( ( spell = liquid_table[liquid].spell ) == -1 )
return FALSE;
if( spell < SPELL_FIRST || spell >= WEAPON_FIRST ) {
bug( "Do_drink: Liquid with non-spell skill." );
return FALSE;
}
( *spell_table[spell-SPELL_FIRST].function )( NULL, ch, NULL, 10, -1 );
return TRUE;
}
/*
* FILL
*/
thing_data* cant_fill( thing_data* thing, char_data*, thing_data* )
{
obj_data* obj = object( thing );
return( obj == NULL || obj->pIndexData->item_type != ITEM_DRINK_CON
? NULL : obj );
}
thing_data* already_full( thing_data* thing, char_data*, thing_data* )
{
obj_data* obj = (obj_data*) thing;
return( obj->value[1] >= obj->value[0] ? NULL : obj );
}
thing_data* fill( thing_data* t1, char_data*, thing_data* t2 )
{
obj_data* obj = (obj_data*) t1;
obj_data* fountain = (obj_data*) t2;
content_array* where = obj->array;
obj = (obj_data*) obj->From( obj->selected );
if( obj->value[1] == 0 || obj->value[2] == fountain->value[2] )
obj->value[2] = fountain->value[2];
else
obj->value[2] = 9;
if( fountain->pIndexData->item_type == ITEM_FOUNTAIN
|| fountain->value[1] == -1 ) {
obj->value[1] = obj->value[0];
}
else if( fountain->value[1]
< obj->selected*( obj->value[0]-obj->value[1] ) ) {
obj->value[1] += fountain->value[1]/obj->selected;
fountain->value[1] = 0;
}
else {
fountain->value[1] -= obj->selected*(obj->value[0]-obj->value[1]);
obj->value[1] = obj->value[0];
}
obj->To( where );
return obj;
}
void do_fill( char_data* ch, char* argument )
{
char arg [ MAX_INPUT_LENGTH ];
thing_array* array;
obj_data* fountain;
content_array* where;
if( count( argument ) == 1 ) {
if( ( fountain = find_type( *ch->array, ITEM_FOUNTAIN ) ) == NULL ) {
send( ch, "You see nothing obvious to fill from.\n\r" );
return;
}
}
else {
if( !two_argument( argument, "from", arg ) ) {
send( ch, "Syntax: Fill <object> [from] <container>.\n\r" );
return;
}
if( ( fountain = one_object( ch, argument,
"fill", &ch->contents, &ch->wearing, ch->array ) ) == NULL )
return;
if( fountain->pIndexData->item_type != ITEM_DRINK_CON
&& fountain->pIndexData->item_type != ITEM_FOUNTAIN ) {
send( ch, "%s isn't something you can fill from.\n\r", fountain );
return;
}
if( fountain->pIndexData->item_type == ITEM_DRINK_CON
&& fountain->value[1] == 0 ) {
include_empty = FALSE;
send( ch, "%s is empty.\n\r", fountain );
include_empty = TRUE;
return;
}
argument = arg;
}
where = fountain->array;
fountain = (obj_data*) fountain->From( 1 );
fountain->To( where );
if( ( array = several_things( ch, argument,
"fill", &ch->contents ) ) == NULL )
return;
if( fountain->pIndexData->item_type == ITEM_DRINK_CON
&& fountain->value[0] != -1
&& ( array->size != 1 || array->list[0]->selected != 1 ) ) {
send( ch, "Due to the rabid complexity of limited liquid and multiple\
containers you may\n\ronly fill one container at a time from non-infinite\
sources.\n\r" );
return;
}
thing_array subset [ 4 ];
thing_func* func [ 4 ] = { cant_fill, same, already_full,
fill };
sort_objects( ch, *array, fountain, 4, subset, func );
page_priv( ch, NULL, empty_string );
page_priv( ch, &subset[0], "can't fill" );
page_priv( ch, &subset[1], "Filling", NULL, "from itself is impossible" );
page_priv( ch, &subset[2], NULL, NULL, "is already full",
"are already full" );
page_publ( ch, &subset[3], "fill", fountain, "from" );
delete array;
}
bool react_filled( char_data* ch, obj_data* obj, int liquid )
{
int spell;
if( ( spell = liquid_table[liquid].spell ) == -1 )
return FALSE;
if( spell < SPELL_FIRST || spell >= WEAPON_FIRST ) {
bug( "Do_fill: Liquid with non-spell skill." );
return FALSE;
}
return( *spell_table[spell-SPELL_FIRST].function )( NULL, ch, obj, 10, -4 );
}
/*
* EMPTY ROUTINES
*/
thing_data* not_container( thing_data* thing, char_data*, thing_data* )
{
obj_data* obj = object( thing );
return( obj->pIndexData->item_type == ITEM_DRINK_CON
? obj : NULL );
}
thing_data* already_empty( thing_data* thing, char_data*, thing_data* )
{
obj_data* obj = object( thing );
return( obj->value[1] != 0 ? thing : NULL );
}
thing_data* fountain( thing_data* thing, char_data*, thing_data* )
{
obj_data* obj = object( thing );
return( obj->value[0] != -1 ? thing : NULL );
}
thing_data* empty_con( thing_data* thing, char_data*, thing_data* )
{
obj_data* obj = object( thing );
content_array* where = obj->array;
obj = (obj_data*) obj->From( obj->selected );
obj->value[1] = 0;
obj->To( where );
return obj;
}
void do_empty( char_data* ch, char* argument )
{
thing_array* array;
thing_array subset [ 4 ];
thing_func* func [ 4 ] = { not_container, already_empty,
fountain, empty_con };
if( ( array = several_things( ch, argument,
"empty", &ch->contents ) ) == NULL )
return;
sort_objects( ch, *array, NULL, 4, subset, func );
include_empty = FALSE;
page_priv( ch, NULL, empty_string );
page_priv( ch, &subset[0], "emptying", NULL, "doesn't make sense" );
page_priv( ch, &subset[1], NULL, NULL,
"is already empty", "are already empty" );
page_priv( ch, &subset[2], "can't empty" );
page_publ( ch, &subset[3], "empty" );
include_empty = TRUE;
consolidate( subset[3] );
delete array;
}