LOP/
LOP/area/
LOP/boards/
LOP/channels/
LOP/clans/
LOP/color/
LOP/councils/
LOP/deity/
LOP/src/specials/
/*****************************************************************************
 * DikuMUD (C) 1990, 1991 by:                                                *
 *   Sebastian Hammer, Michael Seifert, Hans Henrik Staefeldt, Tom Madsen,   *
 *   and Katja Nyboe.                                                        *
 *---------------------------------------------------------------------------*
 * MERC 2.1 (C) 1992, 1993 by:                                               *
 *   Michael Chastain, Michael Quan, and Mitchell Tse.                       *
 *---------------------------------------------------------------------------*
 * SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by: Derek Snider.                    *
 *   Team: Thoric, Altrag, Blodkai, Narn, Haus, Scryn, Rennard, Swordbearer, *
 *         gorog, Grishnakh, Nivek, Tricops, and Fireblade.                  *
 *---------------------------------------------------------------------------*
 * SMAUG 1.7 FUSS by: Samson and others of the SMAUG community.              *
 *                    Their contributions are greatly appreciated.           *
 *---------------------------------------------------------------------------*
 * LoP (C) 2006, 2007, 2008, 2009 by: the LoP team.                          *
 *---------------------------------------------------------------------------*
 *			Specific object creation module			     *
 *****************************************************************************/

#include <stdio.h>
#include "h/mud.h"

void oprog_scrap_trigger( CHAR_DATA *ch, OBJ_DATA *obj );
void handle_mwreset( OBJ_DATA *corpse );

/* Make a trap. */
OBJ_DATA *make_trap( int v0, int v1, int v2, int v3 )
{
   OBJ_DATA *trap;

   if( !( trap = create_object( get_obj_index( OBJ_VNUM_TRAP ), 0 ) ) )
   {
      bug( "%s: couldn't create object vnum %d", __FUNCTION__, OBJ_VNUM_TRAP );
      return NULL;
   }
   trap->timer = 0;
   trap->value[0] = v0;
   trap->value[1] = v1;
   trap->value[2] = v2;
   trap->value[3] = v3;
   return trap;
}

/* Turn an object into scraps. */
void make_scraps( OBJ_DATA *obj )
{
   char buf[MSL];
   OBJ_DATA *scraps;
   CHAR_DATA *ch = NULL;

   separate_obj( obj );
   if( !( scraps = create_object( get_obj_index( OBJ_VNUM_SCRAPS ), 0 ) ) )
   {
      bug( "%s: couldn't create object vnum %d", __FUNCTION__, OBJ_VNUM_SCRAPS );
      return;
   }
   scraps->timer = number_range( 5, 15 );

   /* don't make scraps of scraps of scraps of ... */
   if( obj->pIndexData->vnum == OBJ_VNUM_SCRAPS )
   {
      STRSET( scraps->short_descr, "some debris" );
      STRSET( scraps->description, "Bits of debris lie on the ground here." );
   }
   else
   {
      if( obj->short_descr )
      {
         if( scraps->short_descr )
         {
            snprintf( buf, sizeof( buf ), scraps->short_descr, obj->short_descr );
            STRSET( scraps->short_descr, buf );
         }
         else
            scraps->short_descr = STRALLOC( obj->short_descr );
         if( scraps->description )
         {
            snprintf( buf, sizeof( buf ), scraps->description, obj->short_descr );
            STRSET( scraps->description, buf );
         }
         else
            scraps->description = STRALLOC( obj->short_descr );
      }
   }

   if( obj->carried_by )
   {
      ch = obj->carried_by;
      act( AT_OBJECT, "$p falls to the ground in scraps!", obj->carried_by, obj, NULL, TO_CHAR );
      obj_to_room( scraps, obj->carried_by->in_room );
   }
   else if( obj->in_room )
   {
      if( ( ch = obj->in_room->first_person ) )
      {
         act( AT_OBJECT, "$p is reduced to little more than scraps.", ch, obj, NULL, TO_ROOM );
         act( AT_OBJECT, "$p is reduced to little more than scraps.", ch, obj, NULL, TO_CHAR );
      }
      obj_to_room( scraps, obj->in_room );
   }
   if( ( obj->item_type == ITEM_CONTAINER || obj->item_type == ITEM_KEYRING
   || obj->item_type == ITEM_QUIVER || obj->item_type == ITEM_CORPSE_PC ) && obj->first_content )
   {
      if( ch && ch->in_room )
      {
         act( AT_OBJECT, "The contents of $p fall to the ground.", ch, obj, NULL, TO_ROOM );
         act( AT_OBJECT, "The contents of $p fall to the ground.", ch, obj, NULL, TO_CHAR );
      }
      if( obj->carried_by )
         empty_obj( obj, NULL, obj->carried_by->in_room );
      else if( obj->in_room )
         empty_obj( obj, NULL, obj->in_room );
      else if( obj->in_obj )
         empty_obj( obj, obj->in_obj, NULL );
   }
   oprog_scrap_trigger( ch, obj );
   extract_obj( obj );
}

/* Make a corpse out of a character. */
OBJ_DATA *make_corpse( CHAR_DATA *ch, CHAR_DATA *killer )
{
   char buf[MSL], *name;
   OBJ_DATA *corpse, *obj, *obj_next;
   int bill = 0, rest = 0;

   if( is_npc( ch ) )
   {
      name = ch->short_descr;
      if( !( corpse = create_object( get_obj_index( OBJ_VNUM_CORPSE_NPC ), 0 ) ) )
      {
         bug( "%s: couldn't create object vnum %d", __FUNCTION__, OBJ_VNUM_CORPSE_NPC );
         return NULL;
      }
      handle_mwreset( corpse );
      corpse->timer = 6;
      bill = ch->bgold;
      ch->bgold = 0;
      rest = ch->gold;
      ch->gold = 0;
      obj_to_obj( create_money( rest, bill ), corpse );

      corpse->cost = ( -( int )ch->pIndexData->vnum );
      corpse->value[2] = corpse->timer;
   }
   else
   {
      name = ch->name;
      if( !( corpse = create_object( get_obj_index( OBJ_VNUM_CORPSE_PC ), 0 ) ) )
      {
         bug( "%s: couldn't create object vnum %d", __FUNCTION__, OBJ_VNUM_CORPSE_PC );
         return NULL;
      }
      if( in_arena( ch ) )
         corpse->timer = 0;
      else
         corpse->timer = 40;
      corpse->value[2] = ( int )( corpse->timer / 8 );
      corpse->value[4] = ch->level;
      if( can_pkill( ch ) && sysdata.pk_loot )
         xSET_BIT( corpse->extra_flags, ITEM_CLANCORPSE );
      /*
       * Pkill corpses get save timers, in ticks (approx 70 seconds)
       * This should be anough for the killer to type 'get all corpse'. 
       */
      if( !is_npc( ch ) && !is_npc( killer ) && ch != killer )
         corpse->value[3] = 1;
      else
         corpse->value[3] = 0;
   }

   if( can_pkill( ch ) && can_pkill( killer ) && ch != killer )
   {
      snprintf( buf, sizeof( buf ), "%s", killer->name );
      STRSET( corpse->action_desc, buf );
   }

   snprintf( buf, sizeof( buf ), "corpse %s", name );
   STRSET( corpse->name, buf );

   if( corpse->short_descr )
   {
      snprintf( buf, sizeof( buf ), corpse->short_descr, name );
      STRSET( corpse->short_descr, buf );
   }
   else
      corpse->short_descr = STRALLOC( name );

   if( corpse->description )
   {
      snprintf( buf, sizeof( buf ), corpse->description, name );
      STRSET( corpse->description, buf );
   }
   else
      corpse->description = STRALLOC( name );

   for( obj = ch->first_carrying; obj; obj = obj_next )
   {
      obj_next = obj->next_content;
      obj_from_char( obj );
      if( is_obj_stat( obj, ITEM_INVENTORY ) || is_obj_stat( obj, ITEM_DEATHROT ) )
         extract_obj( obj );
      else
      {
         if( is_obj_stat( obj, ITEM_PIERCED ) )
            xREMOVE_BIT( obj->extra_flags, ITEM_PIERCED );
         if( is_obj_stat( obj, ITEM_LODGED ) )
            xREMOVE_BIT( obj->extra_flags, ITEM_LODGED );
         obj_to_obj( obj, corpse );
      }
   }

   return obj_to_room( corpse, ch->in_room );
}

void make_blood( CHAR_DATA *ch )
{
   OBJ_DATA *obj;

   if( !( obj = create_object( get_obj_index( OBJ_VNUM_BLOOD ), 0 ) ) )
   {
      bug( "%s: couldn't create object vnum %d", __FUNCTION__, OBJ_VNUM_BLOOD );
      return;
   }
   obj->timer = number_range( 2, 4 );
   obj->value[1] = number_range( 3, UMIN( 5, ch->level ) );
   obj_to_room( obj, ch->in_room );
}

void make_bloodstain( ROOM_INDEX_DATA *room )
{
   OBJ_DATA *obj;

   if( !room )
   {
      bug( "%s: NULL room", __FUNCTION__ );
      return;
   }
   if( !( obj = create_object( get_obj_index( OBJ_VNUM_BLOODSTAIN ), 0 ) ) )
   {
      bug( "%s: couldn't create object vnum %d", __FUNCTION__, OBJ_VNUM_BLOODSTAIN );
      return;
   }
   obj->timer = number_range( 1, 3 );
   obj_to_room( obj, room );
}

void set_money( OBJ_DATA *obj, int bamount, int amount )
{
   char buf[MSL], *bignum;

   bignum = show_big_nums( bamount, amount );

   if( obj->pIndexData->short_descr )
   {
      snprintf( buf, sizeof( buf ), obj->pIndexData->short_descr, bignum );
      STRSET( obj->short_descr, buf );
   }
   else
   {
      snprintf( buf, sizeof( buf ), "%s gold coins", bignum );
      obj->short_descr = STRALLOC( buf );
   }

   if( obj->pIndexData->description )
   {
      snprintf( buf, sizeof( buf ), obj->pIndexData->description, bignum );
      STRSET( obj->description, buf );
   }
   else
   {
      snprintf( buf, sizeof( buf ), "%s gold coins", bignum );
      obj->description = STRALLOC( buf );
   }

   obj->value[0] = amount;
   obj->value[1] = bamount;
}

/* make some coinage */
OBJ_DATA *create_money( int amount, int bill )
{
   OBJ_DATA *obj;

   if( amount == 0 && bill == 0 ) /* No point in creating nothing */
      return NULL;

   if( amount < 0 || bill < 0 )
   {
      bug( "%s: negative money (Billions)%d (Reset)%d.", __FUNCTION__, bill, amount );
      amount = 1;
   }

   if( amount == 1 && bill == 0 )
   {
      if( !( obj = create_object( get_obj_index( OBJ_VNUM_MONEY_ONE ), 0 ) ) )
      {
         bug( "%s: couldn't create object vnum %d", __FUNCTION__, OBJ_VNUM_MONEY_ONE );
         return NULL;
      }
   }
   else
   {
      if( !( obj = create_object( get_obj_index( OBJ_VNUM_MONEY_SOME ), 0 ) ) )
      {
         bug( "%s: couldn't create object vnum %d", __FUNCTION__, OBJ_VNUM_MONEY_SOME );
         return NULL;
      }

      while( amount >= 1000000000 )
      {
         amount -= 1000000000;
         bill++;
      }

      set_money( obj, bill, amount );
   }

   return obj;
}