/***************************************************************************
*       FALLEN ANGELS mud is protected by french law of intelectual        *
*                            property. we share freely all we have coded   *
*                            provided this message isn't removed from the  *
*                            files and you respect the name of all the     *
*                            coders,area builders, and all the Diku,Merc,  *
*                            Rom licences.                                 *
*                                                                          *
*                   Thank to : ROM consortium .                            *
*                   Big thank to : Gary Gygax !!!!!!!!!!!!!!               *
*                                                                          *
*       Fallen Angel project by : Loran      ( laurent zilbert )           *
*                                 Silfen or                                *
*                                 Gwendoline ( jerome despret  )           *
*                                                                          *
*       Despret@ecoledoc.lip6.fr ...                                       *
***************************************************************************/

/***************************************************************************
*                                                                          *
*  To use this snipet you must set the following line in the "throw" help  *
*                                                                          *
*    Coded for Fallen Angels by : Zilber laurent,Despret jerome.           *
*                                                                          *
*  And send a mail to say you use it ( feel free to comment ) at :         *
*                                                                          *
*  [despret@ecoledoc.lip6.fr] or/and at [loran@hotmail.com]                *
****************************************************************************/

/***************************************************************************
*                                                                          *
* If you want to put this snipet on your web site you are allowed to but   *
*  the file must remain unchanged and you have to send us a mail at :      *
*                                                                          *
*  [despret@ecoledoc.lip6.fr] or/and at [loran@hotmail.com]                *
*  with the site URL.                                                      *
*                                                                          *
***************************************************************************/


#if defined(macintosh)
#include <types.h>
#include <time.h>
#else
#include <sys/types.h>
#include <sys/time.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "db.h"
#include "recycle.h"
#include "magic.h"

/* command procedures needed */


/***************************************************************************/
/*                                                                         */
/*         One ROOM RANGED ATTACK system ( the throw )                     */
/*                                                                         */
/***************************************************************************/

/* _________________________________________________________________________

  Of course you have to create a gsn_throw and associate it to do_throw then:

  You have to create an ITEM_DART item type it should look like the 
  following example :


#10002
dart~
a strange dart~
You see a little dart here.~
wood~
throwing 0 AO
5 6 pierce 15 'fireball'
0 10 210 P

v0: is the number of dice dammage
v1: is the number of side of each dice
v3: the type of dammage ( same as weapon's ones )

v4: usualy filled with a 0 but hightly powered dart can be filled with
    a spell effect if so this hold the level of the spell.
v5: hold the spell, if you wanna make a clumsy dart fill it with
    a benefit spell.. would you throw a spear that make a heal on
    the victim... dart and flask are't the same on our mud
    flask are more powerful, but dart is more a warrior skill to make
    distant attack however both use throw command... the code make
    the difference between classes using flask and throwing weapon.

_________________________________________________________________________ */





/***************************************************************************

  The throwing code allow now a one room ranged target.
  following things are tested and forbid.
     throw trought a closed door
     targeting a sentinel mob
     targeting a mob that isn't allowed to enter the ch room
     targeting a mob in another area ( specialy for frontier ) 

****************************************************************************/

void
do_throw (CHAR_DATA * ch, char *argument)
{
  char arg[MAX_INPUT_LENGTH];
  CHAR_DATA *victim;
  OBJ_DATA *obj, *obj_next;
  ROOM_INDEX_DATA *was_in_room;
  EXIT_DATA *pexit;
  char buf[256];
  int damm, damm_type, door, outside;

  outside = 0;			/* used to make mob move */

  one_argument (argument, arg);
  if (arg[0] == '\0' && ch->fighting == NULL)
    {
      send_to_char ("You could throw at them, but no one is there!\n\r", ch);
      return;
    }

  if ((obj = get_eq_char (ch, WEAR_HOLD)) == NULL)
    {
      send_to_char ("You hold nothing in your hand.\n\r", ch);
      return;
    }

/*    if ( obj->item_type != WEAPON_DART )
    {
        send_to_char( "You can throw only a throwing weapon.\n\r", ch );
        return;
    }*/

  if (arg[0] == '\0')
    {
      if (ch->fighting != NULL)
	{
	  victim = ch->fighting;
	}
      else
	{
	  send_to_char ("Throw at whom or what?\n\r", ch);
	  return;
	}
    }
  else
    {
      /* try to use 1 range victim allowance */
      /* look if victim is in the room if note look the suroundings rooms */

      if ((victim = get_char_room (ch, NULL, arg)) == NULL)
	{
	  was_in_room = ch->in_room;

	  for (door = 0; door <= 5 && victim == NULL; door++)
	    {
	      if ((pexit = was_in_room->exit[door]) != NULL
		  && pexit->u1.to_room != NULL
		  && pexit->u1.to_room != was_in_room
		  && !strcmp (pexit->u1.to_room->area->name,
			      was_in_room->area->name))
		{
		  ch->in_room = pexit->u1.to_room;
		  victim = get_char_room (ch, NULL, arg);
		}

	    }

	  ch->in_room = was_in_room;
	  if (victim == NULL)
	    {
	      send_to_char ("You can't find it.\n\r", ch);
	      return;
	    }
	  else
	    {
	      if (IS_SET (pexit->exit_info, EX_CLOSED))
		{
		  send_to_char ("You can't throw through a door !!", ch);
		  return;
		}

	      outside = 1;	/* target was outside of the room */

	      /* forbid target that cannot move back to revenge on
	         the thrower */

	      if (IS_NPC (victim))
		{
		  if (IS_SET (victim->act, ACT_SENTINEL)
		      || IS_SET (ch->in_room->room_flags, ROOM_NO_MOB)
		      || (IS_SET (victim->act, ACT_OUTDOORS)
			  && IS_SET (ch->in_room->room_flags, ROOM_INDOORS))
		      || (IS_SET (victim->act, ACT_INDOORS)
			  && IS_SET (ch->in_room->room_flags, ROOM_INDOORS)))
		    {
		      act ("$N avoids your deadly throw !!!", ch, obj, victim,
			   TO_CHAR);
		      was_in_room = ch->in_room;
		      ch->in_room = victim->in_room;
		      act ("$N avoid $p thrown by $n.", ch, obj, victim,
			   TO_NOTVICT);
		      act ("You avoid $p thrown by $n.", ch, obj, victim,
			   TO_VICT);
		      ch->in_room = was_in_room;
		      extract_obj (obj);
		      return;
		    }
		}
	    }
	}
    }

/* this is a strong attack i recomande this wait state */

  WAIT_STATE (ch, 2);

  sprintf (buf, "You don't have %s to throw.\n\r", obj->short_descr);

/* ITEM THROWING */

  if (obj->item_type != 0)
    {

      /* check if there is a victim */

      if (victim != NULL)
	{
	  act ("$n throw $p at $N.", ch, obj, victim, TO_NOTVICT);
	  act ("You throw $p at $N.", ch, obj, victim, TO_CHAR);
	  act ("$n throws $p at you.", ch, obj, victim, TO_VICT);
	  if (outside)
	    {
	      was_in_room = ch->in_room;
	      ch->in_room = victim->in_room;
	      act ("$n throw $p on $N.", ch, obj, victim, TO_NOTVICT);
	      ch->in_room = was_in_room;
	    }
	}

      /* throw the dices :) */

      if (ch->level < obj->level
	  || number_percent () >= 20 + get_skill (ch,
						  gsn_throw) * 4 / 5 -
	  (10 * outside))
	{
	  /* it is a normal miss */

	  act ("You throw $p aimlessly and miss your target.",
	       ch, obj, NULL, TO_CHAR);
	  act ("$n throws $p aimlessly and misses their target.",
	       ch, obj, NULL, TO_ROOM);

	  check_improve (ch, gsn_throw, FALSE, 2);
	}
      else
	{
	  /* it is a success hit the target */

	  damm = dice (obj->value[0], obj->value[1]);
	  damm_type = TYPE_HIT;
	  damm_type += attack_table[obj->value[2]].damage;

	  damage (ch, victim, damm, damm_type, gsn_throw, TRUE);

	  if ((obj->value[3] != 0)
	      && (obj->value[4] != 0) && (victim->position > POS_DEAD))
	    obj_cast_spell (obj->value[4], obj->value[3], ch, victim, obj);

	  check_improve (ch, gsn_throw, TRUE, 2);
	}


      /* look in the inventory for an object of the same key_word and that is a throwing  */

      for (obj_next = ch->carrying; obj_next != NULL
	   && ((obj_next->item_type != ITEM_DART)
	       || (obj == obj_next)
	       || (strcmp (obj->name, obj_next->name)));
	   obj_next = obj_next->next_content);

      extract_obj (obj);

      /* if found equip the ch with */

      if (obj_next == NULL)
	{
	  send_to_char (buf, ch);
	}
      else
	{
	  wear_obj (ch, obj_next, TRUE);
	}

    }

/* Routine that makes a ranged mob moving 50% 
   to attack the aggressor ..... i m looking for a way
   to make the mob wait a little before doing it         */


  if (outside && (victim != NULL) && (victim->position > POS_STUNNED))
    {
      pexit = victim->in_room->exit[0];

      for (door = 0; door <= 5; door++)
	{

	  pexit = victim->in_room->exit[door];
	  if (pexit != NULL && (pexit->u1.to_room == ch->in_room))
	    break;
	}

      if (door >= 6)
	{
	  bug ("no back way in throw....", 0);
	  return;
	}

      if (IS_NPC (victim) && (number_percent () > 50))
	{
	  if (!IS_SET (ch->act, ACT_SENTINEL)
	      && (pexit = victim->in_room->exit[door]) != NULL
	      && pexit->u1.to_room != NULL
	      && !IS_SET (pexit->exit_info, EX_CLOSED)
	      && !IS_SET (pexit->u1.to_room->room_flags, ROOM_NO_MOB)
	      && (!IS_SET (victim->act, ACT_OUTDOORS)
		  || !IS_SET (pexit->u1.to_room->room_flags, ROOM_INDOORS))
	      && (!IS_SET (victim->act, ACT_INDOORS)
		  || IS_SET (pexit->u1.to_room->room_flags, ROOM_INDOORS))
	      && (IS_NPC (victim))
	      && ((victim->position != POS_FIGHTING)
		  || (victim->fighting == ch)))
	    {

	      if ((victim->position == POS_FIGHTING)
		  && (victim->fighting == ch))
		{
		  stop_fighting (victim, TRUE);
		}

	      move_char (victim, door, FALSE);

	      (victim)->wait = UMAX ((victim)->wait, (8));
	      act ("$N scream and attack $n !!!", ch, NULL, victim,
		   TO_NOTVICT);
	      act ("$N scream and attack You !!!", ch, NULL, victim, TO_CHAR);
	      multi_hit (victim, ch, TYPE_UNDEFINED);
	    }
	}
      else
	{
	  switch (door)
	    {
	    case 0:
	      sprintf (buf, "Something comes flying in from NORTH!!!\n\r");
	      break;
	    case 1:
	      sprintf (buf, "Something comes flying in from EAST!!!\n\r");
	      break;
	    case 2:
	      sprintf (buf, "Something comes flying in from SOUTH!!!\n\r");
	      break;
	    case 3:
	      sprintf (buf, "Something comes flying in from WEST!!!\n\r");
	      break;
	    case 4:
	      sprintf (buf, "Something comes flying in from ABOVE!!!\n\r");
	      break;
	    case 5:
	      sprintf (buf, "Something comes flying in from BELOW!!!\n\r");
	      break;
	    default:
	      sprintf (buf,
		       "Throw ERROR, congratulate Xeric for messing up again.\n\r");
	      break;
	    }
	  send_to_char (buf, victim);
	}
    }

  return;
}