exodus2/
exodus2/area/mobscr/
exodus2/area/mobvoc/
exodus2/bin/
exodus2/clans/
exodus2/gods/
exodus2/player/A/
exodus2/player/B/
exodus2/player/D/
exodus2/player/E/
exodus2/player/L/
exodus2/player/M/
exodus2/player/O/
exodus2/player/R/
exodus2/src/obj/clans/
/****************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,         *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.    *
 *                                                                          *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael           *
 *  Chastain, Michael Quan, and Mitchell Tse.                               *
 *                                                                          *
 *  In order to use any part of this Merc Diku Mud, you must comply with    *
 *  both the original Diku license in 'license.doc' as well the Merc        *
 *  license in 'license.txt'.  In particular, you may not remove either of  *
 *  these copyright notices.                                                *
 *                                                                          *
 *  Much time and thought has gone into this software and you are           *
 *  benefitting.  We hope that you share your changes too.  What goes       *
 *  around, comes around.                                                   *
 ****************************************************************************/


/****************************************************************************
 *       ROM 2.4 is copyright 1993-1998 Russ Taylor                         *
 *       ROM has been brought to you by the ROM consortium                  *
 *           Russ Taylor (rtaylor@hypercube.org)                            *
 *           Gabrielle Taylor (gtaylor@hypercube.org)                       *
 *           Brian Moore (zump@rom.org)                                     *
 *       By using this code, you have agreed to follow the terms of the     *
 *       ROM license, in the file Rom24/doc/rom.license                     *
 ****************************************************************************/

#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/stat.h>
#include "merc.h"
#include "interp.h"
#include "clans/new_clans.h"
#include "clans/new_clans_comm.h"
#include "clans/new_clans_io.h"
#include "clans/new_clans_util.h"
#include "obj_trig.h"

//Iblis - Created 9/29/04 to hold all of the Chaos Jester class skills

/*OBJ_DATA *get_obj_vnum_room args((ROOM_INDEX_DATA* rid, int vnum));
OBJ_DATA *get_obj_vnum_char args((CHAR_DATA* ch, int vnum));
void affect_strip_skills args((CHAR_DATA * ch));
long int level_cost args ((int level));
extern int arearooms args ((CHAR_DATA * ch));
extern int areacount args ((CHAR_DATA * ch));
extern int roomcount args ((CHAR_DATA * ch));*/

int quiver_holding args((OBJ_DATA * obj));
void save_player_box args((OBJ_DATA * pObj));
void show_list_to_char args ((OBJ_DATA * list, CHAR_DATA * ch, bool fShort, bool fShowNothing));

bool can_move_char args ((CHAR_DATA * ch, ROOM_INDEX_DATA * to_room, bool follow, bool show_messages));
void one_hit args ((CHAR_DATA * ch, CHAR_DATA * victim, int dt));
void prevent_escape args ((CHAR_DATA * ch, CHAR_DATA * victim));
int check_entangle args ((CHAR_DATA * ch));
bool check_clasp args((CHAR_DATA *ch));
void one_hit_throw args((CHAR_DATA * ch, CHAR_DATA * victim, int dt, OBJ_DATA * wield));
CHAR_DATA *get_gravity_char_room args((ROOM_INDEX_DATA *rid));
void flick_card args((CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *obj, int sn));
void friend_poof args((CHAR_DATA *ch));
	
 bool check_flicker (CHAR_DATA * ch, CHAR_DATA * victim)
{
  int chance;
  if (!IS_AWAKE (victim))
    return FALSE;

  chance = get_skill (victim, gsn_flicker) / 2;

  if (!can_see (victim, ch))
    {
      if (number_percent () < get_skill (victim, gsn_blindfighting))
        check_improve (victim, gsn_blindfighting, TRUE, 2);

      else
        {
          check_improve (victim, gsn_blindfighting, FALSE, 2);
          chance /= 2;
        }
    }
  // Minax 12-20-02 Dodge depends on skill, not level
  //  if (number_percent () >= chance + victim->level - ch->level)
  if (number_percent () >= chance)
    return FALSE;

  act ("$N flickers out of reality and your weapon passes right through $M.", ch, NULL, victim, TO_CHAR);
  act ("You flicker right out of reality as $n swings at you.", ch, NULL, victim, TO_VICT);
  check_improve (victim, gsn_flicker, TRUE, 6);
  return TRUE;
}

//Warp touch skill
void do_warptouch (CHAR_DATA *ch, char *argument)
{
  int chance;
  CHAR_DATA *victim;
  if ((chance = get_skill(ch,gsn_warp_touch)) < 1)
    {
      send_to_char("Warp speed ahead!\n\r",ch);
      return;
    }
  if (argument[0] == '\0')
    {
      send_to_char("Warptouch whom?\n\r",ch);
      return;
      /*      victim = ch->fighting;dd

      if (victim == NULL)
        {
          send_to_char ("But you aren't fighting anyone!\n\r", ch);
          return;
	  }*/
    }

  if ((victim = get_char_room (ch, argument)) == NULL)
    {
      send_to_char ("They aren't here.\n\r", ch);
      return;
    }
  if (is_safe (ch, victim))
    return;
  if (ch == victim)
  {
	  send_to_char("When you think about you, you touch yourself.\n\r",ch);
	  return;
  }
  if (IS_AFFECTED (ch, AFF_CHARM) && ch->master == victim)
    {
      act ("But $N is your friend!", ch, NULL, victim, TO_CHAR);
      return;
    }
  if (IS_AFFECTED (ch, AFF_CALM) || is_affected (ch, skill_lookup
                                                 ("Quiet Mountain Lake")))
    {
      send_to_char ("You are feeling too peaceful to do that now.\n\r", ch);
      return;
    }
  if (ch->position < POS_FIGHTING)
  {
    send_to_char("Get off your ass, doofus!\n\r",ch);
    return;
  }
  if (ch->fighting != NULL)
  {
    send_to_char("No way!  You are still fighting!\n\r",ch);
    return;
  }
  /*if (ch->hit < 15)
    {
      send_to_char("You do not have enough within you to create a spear.\n\r",ch);
      return;
    }
    else ch->hit -= 15;*/
  if (chance > number_percent ())
    {
      send_to_char("Your hand sizzles with tickling energy that makes you giggle to yourself.\n\r",ch);
      act("You slap $N in the face, sending $M to the ground.",ch,NULL,victim,TO_CHAR);
      act("Sizzling energy courses through your spasming body as $n touches you!",ch,NULL,victim,TO_VICT);
      act("Red and yellow light explodes as $n touches $N!",ch,NULL,victim,TO_NOTVICT);
      damage (ch, victim, adjust_damage(ch->damroll+(ch->perm_stat[STAT_STR]*2)), gsn_warp_touch, number_range(1,DAM_WIND), TRUE);
    }
  else
    {
      send_to_char("Your hand sizzles with tickling energy that makes you giggle to yourself.\n\r",ch);
      act("You attempt to slap $N in the face, miss $m completely.",ch,NULL,victim,TO_CHAR);
      act("$n's hand comes out in an attempt to slap you in the face, but $e misses completely.",ch,NULL,victim,TO_VICT);
      act("$n's hand comes out in an attempt to slap $N in the face, but $e misses completely.",ch,NULL,victim,TO_NOTVICT);
      damage (ch, victim, 0, gsn_warp_touch, number_range(1,DAM_WIND), TRUE);
    }
}

void do_madrush (CHAR_DATA *ch, char *argument)
{
  int chance, dam;
  short s1=0;
  CHAR_DATA *victim;
  if ((chance = get_skill(ch,gsn_mad_rush)) < 1)
    {
      send_to_char("You rush forward like mad!\n\r",ch);
      return;
    }
  if (argument[0] == '\0')
    {
      victim = ch->fighting;
      if (victim == NULL)
        {
          send_to_char ("But you aren't fighting anyone!\n\r", ch);
          return;
        }
    }

  else if ((victim = get_char_room (ch, argument)) == NULL)
    {
      send_to_char ("They aren't here.\n\r", ch);
      return;
    }
  if (is_safe (ch, victim))
    return;
  if (ch == victim)
  {
    send_to_char("You make a mad rush at yourself, but collapse in a heap.\n\r",ch);
    return;
  }
  if (IS_AFFECTED (ch, AFF_CHARM) && ch->master == victim)
    {
      act ("But $N is your friend!", ch, NULL, victim, TO_CHAR);
      return;
    }
  if (IS_AFFECTED (ch, AFF_CALM) || is_affected (ch, skill_lookup
                                                 ("Quiet Mountain Lake")))
    {
      send_to_char ("You are feeling too peaceful to do that now.\n\r", ch);
      return;
    }
  s1=100*(ch->hit/(ch->max_hit*1.0));
  if (ch->move < s1)
    {
      send_to_char("The only sort of rushing you have the energy to do is towards bed.\n\r",ch);
      return;
    }
  else ch->move -= s1;
  WAIT_STATE (ch, skill_table[gsn_mad_rush].beats);
  if (chance > number_percent ())
    {
      act("Having nothing better to do, you rush headfirst into $N.",ch,NULL,victim,TO_CHAR);
      act("Suddenly $n decides to run into you!",ch,NULL,victim,TO_VICT);
      act("$n runs and crashes headfirst into $N!",ch,NULL,victim,TO_NOTVICT);
      dam = ch->max_hit/10.0;
      dam = 150 + ((10 - ch->hit/dam)*10.0);
      damage (ch, victim, adjust_damage(dam), gsn_mad_rush, DAM_BASH, TRUE);
      return;
    }
 else
   {
     act("Having nothing better to do, you rush headfirst into $N.",ch,NULL,victim,TO_CHAR);
     send_to_char("You fall flat on your face!\n\r",ch);
     act("$n falls flat on $s face!",ch,NULL,victim,TO_ROOM);
     /*
     act("You summon your strength to form a spear made of pure ice and throw it at $N.",ch,NULL,victim,TO_CHAR);
     act("$n seems to get a little shorter as $e forms a spear of ice and throw it at $N.",ch,NULL,victim,TO_NOTVICT);
     act("$n seems to get a little shorter as $e forms a spear of ice and throw it at you.",ch,NULL,victim,TO_VICT);*/
     damage (ch, victim, 0, gsn_mad_rush, DAM_BASH, FALSE);
     ch->position = POS_RESTING;
     if (IS_NPC (ch))
       ch->color = 42;
     return;
   }
}


void do_coma (CHAR_DATA * ch, char *argument)
{
  int chance;
  if ((chance = get_skill(ch,gsn_coma)) < 1)
    {
          send_to_char("You can only get that from a hit on the head.",ch);
          return;
    }
  if (ch->race == PC_RACE_SWARM)
    {
      send_to_char("Huh?\n\r",ch);
      return;
    }
  if (is_affected (ch, skill_lookup ("Dance of Shadows")))
    {
      send_to_char ("Your nightmares keep you from slipping into a coma.\n\r", ch);
      return;
    }
  if (is_affected (ch, gsn_fear))
    {
      send_to_char ("You are WAY too scared to slip into a coma right now!\n\r",ch);
      return;
    }
  if (ch->fighting != NULL)
    {
      send_to_char ("You are WAY too busy to slip into a coma now!\n\r", ch);
      return;
    }
  if (chance > number_percent())
{
  switch (ch->position)
    {
    case POS_SLEEPING:
      send_to_char ("You are already sleeping.\n\r", ch);
      break;
    case POS_MOUNTED:
      send_to_char ("You must dismount before you can slip into a coma.\n\r", ch);
      return;
    case POS_RESTING:
    case POS_SITTING:
    case POS_STANDING:
      send_to_char ("You slip into a coma.\n\r", ch);
      act ("$n lies down and stops breathing completely.", ch, NULL, NULL, TO_ROOM);
      ch->position = POS_COMA;
      trip_triggers(ch, OBJ_TRIG_CHAR_POS_CHANGE, NULL, NULL, OT_SPEC_NONE);
      ch->on = NULL; //Can't go comatose on any object
      break;
    case POS_FIGHTING:
      send_to_char ("You are WAY too busy to slip into a coma now!\n\r", ch);
      break;
    }
} else
     send_to_char ("One of the voices incessant yapping prevents you from doing so.\n\r",ch);

  return;
}


//Iblis - Vanish skill
void do_vanish (CHAR_DATA *ch, char *argument)
{
  AFFECT_DATA af;
  int chance;
  if ((chance = get_skill(ch,gsn_vanish)) < 1)
    {
      send_to_char("You close your eyes and the world vanishes!\n\r",ch);
      return;
    }
  if (ch->move < 100)
    {
     send_to_char("You cannot muster the strength to vanish.\n\r",ch);
      return;
    }
  else ch->move -= ch->move*.95;
  if (IS_AFFECTED (ch, AFF_INVISIBLE))
    {
        send_to_char ("Your are already invisible.\n\r", ch);
      return;
    }
  if (chance > number_percent())
    {
      af.where = TO_AFFECTS;
      af.type = gsn_vanish;
      af.level = ch->level;
      af.duration = 40 + ch->perm_stat[STAT_WIS];
      af.location = 0;
      af.modifier = 0;
      af.bitvector = AFF_INVISIBLE;
      af.permaff = FALSE;
      af.composition = FALSE;
      af.comp_name = str_dup ("");
      affect_to_char (ch, &af);
      send_to_char("You slap your hands across your eyes and pretend that you are invisible.\n\r",ch);
      act ("$n crawls into $s navel and vanishes!",ch,NULL,NULL,TO_ROOM);
      WAIT_STATE (ch, skill_table[gsn_vanish].beats);
      return;
    }

    WAIT_STATE (ch, skill_table[gsn_vanish].beats);
    send_to_char("You slap your hands across your eyes, but you can't help peeking so it does no good.\n\r",ch);
}


void do_persuade (CHAR_DATA *ch, char *argument)
{
  int chance, amount,amount2;
  char buf[MAX_STRING_LENGTH];
  CHAR_DATA *victim;
  if ((chance = get_skill(ch,gsn_persuade)) < 1)
    {
      send_to_char("You couldn't persuade a starving man to eat.\n\r",ch);
      return;
    }

  if ((victim = get_char_room (ch, argument)) == NULL)
    {
      send_to_char ("They aren't here.\n\r", ch);
      return;
    }
  if (is_safe (ch, victim))
    return;
  if (chance > number_percent() && get_curr_stat(ch,STAT_CHA) > get_curr_stat(victim,STAT_CHA))
    {
      act("You persuade $N to give you the money that should have been yours in the first place.",ch,NULL,victim,TO_CHAR);
      if (ch->race != PC_RACE_SIDHE && ch->race != PC_RACE_LITAN)
      {
        switch (number_range(1,8))
	  {
	  case 1: do_say(ch,"Give me your money because: I deserve to be rich");break;
	  case 2: do_say(ch,"Give me your money because: I need them");break;
	  case 3: do_say(ch,"Give me your money because: I'm such a nice person");break;
	  case 4: do_say(ch,"Give me your money because: I'm better than you");break;
	  case 5: do_say(ch,"Give me your money, or else!");break;
	  case 6: do_say(ch,"Some extra money would be nice right about now");break;
	  case 7: do_say(ch,"I'm here to collect the tax for king Athanmere");break;
	  case 8: do_say(ch,"You owe me money. You know, from that time at the place?");break;
	  }
      }
      act("$n persuades $N to give $m money.",ch,NULL,victim,TO_NOTVICT);
      WAIT_STATE(ch,skill_table[gsn_persuade].beats);
      if (get_curr_stat(ch,STAT_CHA) > 10)
        chance = number_range(10,get_curr_stat(ch,STAT_CHA));
      else chance = number_range(get_curr_stat(ch,STAT_CHA),10);
      amount = victim->silver * (chance/100.0);
      ch->silver += amount;
      victim->silver -= amount;
      amount2 = victim->gold * (chance/100.0);
      ch->gold += amount2;
      victim->gold -= amount2;
      sprintf(buf,"You give $n %d gold and %d silver.",amount2,amount);
      act(buf,ch,NULL,victim,TO_VICT);
    }
  else
    {
      act("You try to persuade $N to give you money but you don't do that by slapping them in the face.",ch,NULL,victim,TO_CHAR);
      act("$n slaps you in the face, and you don't take it very well.",ch,NULL,victim,TO_VICT);
      act("$n slaps $N in the face.",ch,NULL,victim,TO_NOTVICT);
      damage(ch,victim,0,gsn_persuade,DAM_UNIQUE,FALSE);
      WAIT_STATE(ch,skill_table[gsn_persuade].beats);
    }
}

//Iblis - Mad Dance skill
void do_maddance (CHAR_DATA *ch, char *argument)
{
  AFFECT_DATA af;
  int chance;
  //  CHAR_DATA *victim;
  if ((chance = get_skill(ch,gsn_mad_dance)) < 1)
    {
      send_to_char("You dances like a madman, but only succeed in making people think you're mad.\n\r",ch);
      return;
    }
  if (is_affected(ch,skill_lookup("spider body")))
  {
    send_to_char("Spiders can't dance.  Spiders can't walk.  The only thing about them is the way they talk.\n\r",ch);
    return;
  }
  if (ch->mana < ch->max_mana*.25 || ch->move < ch->max_move*((80 - ch->perm_stat[STAT_CON])/100.0) || ch->move < ch->max_move*.50)
    {
      send_to_char("You are too exhausted to dance.\n\r",ch);
      return;
    }
  ch->mana -= ch->max_mana*.25;
  ch->move -= ch->max_move*((80 - ch->perm_stat[STAT_CON])/100.0);
  if (is_affected (ch, gsn_mad_dance))
    {
      send_to_char ("Your are already affected by a mad dance.\n\r", ch);
      return;
    }
  if (chance > number_percent())
    {
      af.where = TO_SKILL;
      af.type = gsn_mad_dance;
      af.level = ch->level;
      af.duration = ch->perm_stat[STAT_DEX];
      af.location = gsn_second_attack;
      af.modifier = 100;
      af.bitvector = 0;
      af.permaff = FALSE;
      af.composition = FALSE;
      af.comp_name = str_dup ("");
      affect_to_char (ch, &af);
      af.location = gsn_third_attack;
      affect_to_char(ch, &af);
      send_to_char("You start dancing and notice the envious stares of everyone else.\n\r",ch);
      act("You look at $n incredulously as $e starts dancing like a madman with two left feet.",ch,NULL,NULL,TO_ROOM);
      WAIT_STATE (ch, skill_table[gsn_mad_dance].beats);
      return;
    }

  WAIT_STATE (ch, skill_table[gsn_mad_dance].beats);
  send_to_char("You start dancing, but after kicking yourself in the ass a few times you stop.\n\r",ch);
  act("You look at $n incredulously as $e starts kicking $mself in the ass.",ch,NULL,NULL,TO_ROOM);
}

//Iblis - Fire Dance skill
void do_firedance (CHAR_DATA *ch, char *argument)
{
  AFFECT_DATA af;
  int chance;
  //  CHAR_DATA *victim;
  if ((chance = get_skill(ch,gsn_fire_dance)) < 1)
    {
      send_to_char("You dances fast and furiously, but the only thing on fire is people's feet as they run quickly away.\n\r",ch);
      return;
    }
  if (is_affected(ch,skill_lookup("spider body")))
    {
      send_to_char("Spiders can't dance.  Spiders can't walk.  The only thing about them is the way they talk.\n\r",ch);
      return;
    }
  if (ch->mana < ch->max_mana*.30 || ch->move < ch->max_move*((50 - ch->perm_stat[STAT_CON])/100.0) || ch->move < ch->max_move*.50)
    {
      send_to_char("You are too exhausted to dance.\n\r",ch);
      return;
    }
  ch->mana -= ch->max_mana*.30;
  ch->move -= ch->max_move*((50 - ch->perm_stat[STAT_CON])/100.0);
  if (is_affected (ch, gsn_fire_dance))
    {
      send_to_char ("Your are already affected by a fire dance.\n\r", ch);
      return;
    }
  if (chance > number_percent())
    {
      af.where = TO_AFFECTS;
      af.type = gsn_fire_dance;
      af.level = ch->level;
      af.duration = ch->perm_stat[STAT_DEX];
      af.location = APPLY_NONE;
      af.modifier = 0;
      af.bitvector = 0;
      af.permaff = FALSE;
      af.composition = FALSE;
      af.comp_name = str_dup ("");
      affect_to_char (ch, &af);
      send_to_char("As you start dancing, multicolored flames envelop your hands.\n\r",ch);
      act("As $n starts dancing, $s hands light up with multicolored fire!",ch,NULL,NULL,TO_ROOM);
      WAIT_STATE (ch, skill_table[gsn_fire_dance].beats);
      return;
    }
  WAIT_STATE (ch, skill_table[gsn_fire_dance].beats);
  send_to_char("You start dancing, and your ass catches on fire! You shake your booty until it stops.\n\r",ch);
  act("You look at $n incredulously as smoke starts coming from $s ass.",ch,NULL,NULL,TO_ROOM);
}


void do_escape (CHAR_DATA *ch, char *argument)
{
  ROOM_INDEX_DATA *pRoomIndex;
  int chance, counter=0;
  if ((chance = get_skill(ch,gsn_escape)) < 1 || ch->fighting == NULL)
    {
      send_to_char("You escape into the world you currently exist.\n\r",ch);
      return;
    }
  if (!is_affected(ch,skill_lookup("spider body")))
    {
      send_to_char("You don't have enough legs to escape!\n\r",ch);
      return;
    }
  if (ch->hit < 60 - ch->perm_stat[STAT_CON])
    {
      send_to_char("You can't pull off an escape and live.\n\r",ch);
      return;
    }
  if (ch->position < POS_FIGHTING)
    {
      send_to_char("You need to escape your ass from the ground first.\n\r",ch);
      return;
    }
  if (is_affected(ch,skill_lookup("demonic possession")))
    {
      send_to_char("The demonic being inside you does not want to flee.\n\r",ch);
      return;
    }
  if (!check_web (ch))
    return;
  if (!check_entangle (ch))
    return;
  if (!check_clasp (ch))
    return;
  if (((!IS_NPC (ch->fighting) && ch->fighting->pcdata->prevent_escape) 
			   || IS_SET(ch->fighting->act2,ACT_MONK))
           && number_percent () < (get_skill (ch->fighting, gsn_prevent_escape)* .60))
   {
     prevent_escape (ch->fighting, ch);
     return;
   }
  ch->hit -= 60 - ch->perm_stat[STAT_CON];
  if (chance > number_percent() && !IS_SET (ch->in_room->room_flags, ROOM_NO_RECALL) 
      && !IS_SET (ch->in_room->race_flags, ROOM_NOTRANSPORT) && ch->in_room)
    {
      WAIT_STATE (ch, skill_table[gsn_escape].beats);
      send_to_char("Using your eight legs, you run away from battle faster than anyone ever has before.\n\r",ch);
      act("$n scuttles away on his spider legs, giggling and bumping into people.",ch,NULL,NULL,TO_ROOM);
      pRoomIndex = get_random_room (ch);
      while (IS_SET (pRoomIndex->room_flags, ROOM_ARENA)
	     || IS_SET (pRoomIndex->room_flags, ROOM_SILENT)
	     || IS_SET (pRoomIndex->room_flags, ROOM_NOMAGIC)
         || pRoomIndex->area->construct
         || pRoomIndex->sector_type == SECT_WATER_OCEAN
	     || IS_SET (pRoomIndex->race_flags, ROOM_NOTRANSPORT)
	     || IS_SET (pRoomIndex->race_flags, ROOM_NOTELEPORT)
	     || (IS_SET(pRoomIndex->area->area_flags,AREA_IMP_ONLY) && get_trust(ch) < MAX_LEVEL)
	     || (pRoomIndex->vnum >= ROOM_VNUM_PLAYER_START && pRoomIndex->vnum <= ROOM_VNUM_PLAYER_END)
	     || (pRoomIndex->area != ch->in_room->area)
	     || !can_move_char(ch,pRoomIndex,FALSE,FALSE)
	     ) 
	{
	  pRoomIndex = get_random_room (ch);
	  if (++counter > 10000)
	    {
	      send_to_char("You try to escape through the ground, but alas, it is not bending to your will.\n\r",ch);
	      act("$n spins around in circles a few times then dives furiously at the ground, rising with a strange look on $s face.",ch,NULL,NULL,TO_ROOM);
	      return;
	    }
	}
       stop_fighting (ch, TRUE);
        // Shinowlan 8/30/98 -- Check person fled from to see if we
        // need to clear their pending output.  This was put in
        // to deal with kai, flee, reenter abuse.
	if (ch->fighting)
	{
	  if (!IS_NPC (ch->fighting) && (ch->fighting->wait > 0))
	  {
	    ch->fighting->desc->inbuf[0] = '\0';    //clear queued input
  	  }
	}
      char_from_room(ch);
      char_to_room(ch,pRoomIndex);
    }
  else
    {
      send_to_char("You try to escape through the ground, but alas, it is not bending to your will.\n\r",ch);
      act("$n spins around in circles a few times then dives furiously at the ground, rising with a strange look on $s face.",ch,NULL,NULL,TO_ROOM);
      WAIT_STATE (ch, skill_table[gsn_escape].beats);
    }
}

void death_spasms(CHAR_DATA *ch)
{
  AFFECT_DATA af;
  af.where = TO_AFFECTS;
  af.type = gsn_death_spasms;
  af.level = ch->level;
  af.duration = 1;
  af.modifier = -20;
  af.location = APPLY_AC;
  if (!IS_SET(ch->affected_by,AFF_HASTE))
    af.bitvector = AFF_HASTE;
  else af.bitvector = 0;
  af.permaff = FALSE;
  af.composition = FALSE;
  af.comp_name = str_dup ("");
  affect_to_char (ch, &af);
  af.bitvector = 0;
  af.location = APPLY_DAMROLL;
  af.modifier = get_skill(ch,gsn_death_spasms)/10.0;
  affect_to_char (ch, &af);
  af.location = APPLY_HITROLL;
  affect_to_char (ch, &af);
  send_to_char ("You feel a rush of strength as sweet death draws closer.\n\r", ch);
  act ("$n fights back with renewed energy!",ch,NULL,NULL,TO_ROOM);
}

void do_flick (CHAR_DATA * ch, char *argument)
{
  CHAR_DATA *victim = NULL;
  char flicking_card[MAX_INPUT_LENGTH];
  OBJ_DATA *obj, *tobj;
  short  chance, hands = 0;
  chance = get_skill (ch, gsn_flick);
  if (chance <= 0)
    {
      send_to_char ("You flick everyone off.\n\r", ch);
      return;
    }
  argument = one_argument (argument, flicking_card);
  if (flicking_card[0] == '\0')
    {
      send_to_char ("Flock what card at whom?\n\r", ch);
      return;
    }
  if ((obj = get_obj_carry (ch, flicking_card)) == NULL)
    {
      send_to_char ("You don't seem to be carrying that card.\n\r", ch);
      return;
    }
  if (is_affected (ch, gsn_fear))
    {
      send_to_char ("You are way too scared to consider attacking anyone.\n\r", ch);
      return;
    }
  if (IS_AFFECTED (ch, AFF_CALM) || is_affected (ch, skill_lookup
                                                 ("Quiet Mountain Lake")))
    {
      send_to_char ("You are feeling too peaceful to do that now.\n\r", ch);
      return;
    }
  if (obj->item_type != ITEM_CARD)
    {
      act ("$p is not a card.", ch, obj, NULL, TO_CHAR);
      return;
    }
  for (tobj = ch->carrying; tobj; tobj = tobj->next_content)
    {
      if ((tobj->wear_loc == WEAR_WIELD_R)
          || (tobj->wear_loc == WEAR_WIELD_L) || (tobj->wear_loc ==
                                                  WEAR_HOLD)
          || (tobj->wear_loc == WEAR_SHIELD))
        {
          if ((tobj->item_type == ITEM_WEAPON
               && (IS_WEAPON_STAT (tobj, WEAPON_TWO_HANDS) && ch->size < SIZE_LARGE))
              || (tobj->item_type == ITEM_INSTRUMENT
                  && IS_SET (tobj->value[0], A)))
            hands += 2;

          else
            hands++;
        }
    }
  if (hands > 1)
    {
      act ("You have no free hand with which to flick $p.", ch, obj,
           NULL, TO_CHAR);
      return;
    }
  if (IS_SET (ch->in_room->room_flags, ROOM_SAFE))
    {
      send_to_char ("You cannot flick a card in a safe room.\n\r", ch);
      return;
    }
  if (argument[0] == '\0')
    {
      if (ch->fighting != NULL)
        victim = ch->fighting;
      else
        {
          send_to_char ("Flick what at whom?\n\r", ch);
          return;
        }
    }
  else victim = get_char_room (ch, argument);

  if (victim == NULL)
    {
      send_to_char ("They aren't here.\n\r", ch);
      return;
    }
  if (victim->in_room)
    {
      CHAR_DATA *tmp_vict = get_gravity_char_room(victim->in_room);
      if (tmp_vict)
        victim = tmp_vict;
    }
  if (victim == ch || is_affected(ch,gsn_gravity))
    {
      send_to_char ("You can't flick a card at yourself.\n\r", ch);
      return;
    }
  if (is_safe (ch, victim))
    return;
  WAIT_STATE (ch, skill_table[gsn_flick].beats);
  act ("With a snap of $s wrist, $n flicks a card at you.", ch, obj, victim, TO_VICT);
  act ("With a snap of $s wrist, $n flicks a card at $N.", ch, obj, victim, TO_NOTVICT);
  act ("You flick $p at $N.", ch, obj, victim, TO_CHAR);
  flick_card(ch,victim,obj,gsn_flick);
}


void flick_card(CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *obj, int sn)
{
  int chance;
  chance = get_skill (ch, gsn_flick);
  obj_from_char (obj);
  if (!IS_NPC(ch))
    save_char_obj (ch);
      if (victim->in_room->sector_type == SECT_UNDERWATER)
	{
	  act ("$p floats into the murky depths of the water.", ch, obj,
	       NULL, TO_CHAR);
	  obj_to_room (obj, victim->in_room);
	  act ("$p floats gently into the water.", victim, obj, NULL, TO_ROOM);
	  return;
	}
      if (ch->in_room->sector_type == SECT_UNDERWATER)
	{
	  act ("$p floats into the murky depths of the water.", ch, obj,
	       NULL, TO_CHAR);
	  obj_to_room (obj, ch->in_room);
	  act ("$p floats gently into the water.", ch, obj, NULL, TO_ROOM);
	  return;
	}
      if (is_affected (victim, gsn_mirror))
	{
	  obj_to_room (obj, victim->in_room);
      act
        ("$p bounces off of your invisible mirror and clatters to the ground.",
         victim, obj, NULL, TO_CHAR);
      act
        ("$p bounces off of an invisible mirror and clatters to the ground.",
         victim, obj, victim, TO_NOTVICT);
      return;
	}
      chance += get_curr_stat (ch, STAT_DEX) / 3;
      chance -= get_curr_stat (victim, STAT_DEX) / 5;
      chance += victim->size;

      //chance += GET_AC (victim, AC_PIERCE) / 4;
      if (IS_NPC (victim))
	chance += GET_AC (victim, AC_PIERCE) / 5;

  else
    chance += GET_AC (victim, AC_PIERCE) / 6;
      if (IS_SET (ch->off_flags, OFF_FAST) || IS_AFFECTED (ch, AFF_HASTE))
	chance += 5;
      if (IS_SET (victim->off_flags, OFF_FAST) || IS_AFFECTED (victim, AFF_HASTE))
	chance -= 20;

      //  chance += (ch->level - victim->level);
      if (number_percent () < chance)
	{
	  if (!IS_AWAKE (victim))
	    victim->position = POS_RESTING;
	  if (victim && !IS_NPC(victim))
	    save_char_obj (victim);
 	  if (sn == gsn_flick && number_percent() >= 50)
	    obj_to_char(obj,victim);
	  one_hit_throw (ch, victim, sn, obj);
	  if (ch->fighting == NULL)
	    {
	      if (ch->mount != NULL && ch->mount->riders != NULL)
		ch->position = POS_MOUNTED;

          else
            ch->position = POS_STANDING;
	    }
	  if (victim->fighting == NULL)
	    {
	      if (victim->mount != NULL && victim->mount->riders != NULL)
		victim->position = POS_MOUNTED;

          else
            victim->position = POS_STANDING;
	    }
	}
      else 
      {
	act("Your flick missed $N.",ch,NULL,victim,TO_CHAR);
	act("$n's flick misses $N.",ch,NULL,victim,TO_NOTVICT);
	act("$n's flick misses you.",ch,NULL,victim,TO_VICT);
	obj_to_room(obj,ch->in_room);
        if ((get_curr_stat (ch, STAT_DEX) < 21
              || get_curr_stat (ch, STAT_CHA) < 14) && number_percent () <= 25)
        {
           damage (ch, victim, 0, gsn_flick, DAM_NONE, FALSE);
        }
//        update_aggressor (ch, victim);
      }
}

void do_shuffle(CHAR_DATA *ch, char* argument)
{
  OBJ_DATA *obj, *obj_next, *tobj;
  CHAR_DATA *rch;
  int counter=0,max,total=0,counter2=0,hands=0,chance;
  if ((chance = get_skill(ch,gsn_shuffle)) < 1)
    {
      if (ch->sex == SEX_MALE)
	{
	  send_to_char("You reach down and shuffle your twig and berries around.  It feels kind of good!\n\r",ch);
	  act("$n reaches down and shuffles $s twig and berries around.  A smile appears on $s face.",ch,NULL,NULL,TO_ROOM);
	  return;
	}
      //Damn women, I can't think of an interesting message for them
      send_to_char("You reach up and shuffle your hair around, trying to look available to any onlookers.\n\r",ch);
      act("$n reaches up and shuffles $s hair around, trying to look available to any onlookers.",ch,NULL,NULL,TO_ROOM);
      return;
    }

  if (ch->move < 200-(ch->perm_stat[STAT_DEX]*2))
    {
      send_to_char("You're too tired to shuffle your cards right now.\n\r",ch);
      return;
    }

  if (is_affected (ch, gsn_fear))
    {
      send_to_char ("You are way too scared to consider attacking anyone.\n\r", ch);
      return;
    }
  if (IS_AFFECTED (ch, AFF_CALM) || is_affected (ch, skill_lookup
                                                 ("Quiet Mountain Lake")))
    {
      send_to_char ("You are feeling too peaceful to do that now.\n\r", ch);
      return;
    }
  for (tobj = ch->carrying; tobj; tobj = tobj->next_content)
    {
      if ((tobj->wear_loc == WEAR_WIELD_R)
          || (tobj->wear_loc == WEAR_WIELD_L) || (tobj->wear_loc ==
                                                  WEAR_HOLD)
          || (tobj->wear_loc == WEAR_SHIELD))
        {
          if ((tobj->item_type == ITEM_WEAPON
               && (IS_WEAPON_STAT (tobj, WEAPON_TWO_HANDS) && ch->size < SIZE_LARGE))
              || (tobj->item_type == ITEM_INSTRUMENT
                  && IS_SET (tobj->value[0], A)))
            hands += 2;

          else
            hands++;
        }
    }
  if (hands > 1)
    {
      act ("You have no free hand with which to shuffle.", ch,NULL,NULL, TO_CHAR);
      return;
    }

  max = number_range(5,10);
  max *= (chance/100.0);
  if (max < 1)
    {
      send_to_char("Alas, your skill at shuffling is so poor you actually shuffle your deck without spilling any cards.\n\r",ch);
      return;
    }
  WAIT_STATE (ch, skill_table[gsn_shuffle].beats);
  send_to_char("You try to shuffle your deck but fail! Cards fly in every direction!\n\r",ch);
  act("`bFace contorted in concentration, $n tries to shuffle $n deck but ends up sending cards flying in every direction!``",ch,NULL,NULL,TO_ROOM);
  for (obj = ch->carrying;obj != NULL && counter <= max;obj = obj_next)
    {
      obj_next = obj->next_content;
      if (obj->item_type != ITEM_CARD)
	continue;
      total = 0;
      for (rch = ch->in_room->people;rch != NULL;rch = rch->next_in_room)
	{
  	  if (rch == ch)
	    continue;
	  if (is_safe_spell(ch,rch,FALSE))
	    continue;
	  if (is_same_group(ch,rch))
   	    continue;
	  ++total;
	}
      total = number_range(1,total);
      counter2 = 0;
      for (rch = ch->in_room->people;rch != NULL;rch = rch->next_in_room)
        {
  	  if (rch == ch)
	    continue;
          if (is_safe_spell(ch,rch,FALSE))
            continue;
 	  if (is_same_group(ch,rch))
            continue;
          if (++counter2 == total)
	    {
	      flick_card(ch,rch,obj,gsn_shuffle);
	      ++counter;
	      break;
	    }
        }
    }
}


void do_luckythrow (CHAR_DATA * ch, char *argument)
{
  char arg[MAX_INPUT_LENGTH];
  CHAR_DATA *victim;
  int chance;
  one_argument (argument, arg);
  if ((chance = get_skill (ch, gsn_lucky_throw)) == 0)
    {
      send_to_char ("You throw your arms into the air.  That wasn't very lucky.\n\r", ch);
      return;
    }
  victim = ch->fighting;
  if (victim == NULL)
    {
      send_to_char ("But you aren't in combat!\n\r",ch);
      return;
    }
  if (ch->mana < 80-ch->perm_stat[STAT_DEX])
    {
      send_to_char ("You throw your arms up in despair.  You don't have enough strength to be lucky.\n\r",ch);
      return;
    }
  ch->mana -= 80-ch->perm_stat[STAT_DEX];

  if ((get_eq_char(ch,WEAR_WIELD_R) != NULL && !(get_eq_char(ch,WEAR_WIELD_R)->value[0] == WEAPON_DICE))
        || (get_eq_char(ch,WEAR_WIELD_L) != NULL && !(get_eq_char(ch,WEAR_WIELD_L)->value[0] == WEAPON_DICE)))
  {
	  send_to_char("You must be wielding dice for this to work.\n\r",ch);
	  return;
  }

  WAIT_STATE(ch,skill_table[gsn_lucky_throw].beats);
  if (chance > number_percent())
    {
      one_hit(ch,victim,-1);
      one_hit(ch,victim,-1);
      one_hit(ch,victim,-1);
    }
  else send_to_char("Your luck SUCKS!\n\r",ch);

}

void do_friend(CHAR_DATA *ch, char* argument)
{
  CHAR_DATA* mob;
    char buf[MAX_STRING_LENGTH];
  if (IS_NPC(ch))
    return;
  if (ch->class != PC_CLASS_CHAOS_JESTER)
    {
      send_to_char("You attempt to will a friend into existence, but you can't seem to do it.\n\r",ch);
      return;
    }
  if (ch->in_room->area->nplayer > 1)
    {
      send_to_char("Does your imaginary friend even really exist? Others do not seem to think so.\n\r",ch);
      return;
    }
  if (ch->pcdata->familiar)
    {
      familiar_poof(ch);
      return;
    }
  mob = create_mobile(get_mob_index(MOB_VNUM_IMAGINARY_FRIEND));
  mob->perm_stat[STAT_STR] = ch->perm_stat[STAT_STR]-3;
  mob->perm_stat[STAT_INT] = ch->perm_stat[STAT_INT]-3;
  mob->perm_stat[STAT_WIS] = ch->perm_stat[STAT_WIS]-3;
  mob->perm_stat[STAT_DEX] = ch->perm_stat[STAT_DEX]-3;
  mob->perm_stat[STAT_CON] = ch->perm_stat[STAT_CON]-3;
  mob->perm_stat[STAT_CHA] = ch->perm_stat[STAT_CHA]-3;
  mob->mod_stat[STAT_STR] = 0;
  mob->mod_stat[STAT_INT] = 0;
  mob->mod_stat[STAT_WIS] = 0;
  mob->mod_stat[STAT_DEX] = 0;
  mob->mod_stat[STAT_CON] = 0;
  mob->mod_stat[STAT_CHA] = 0;
  act("Your imaginary friend appears, honks your nose, and then giggles a little.",ch,NULL,NULL,TO_ALL);
  sprintf (buf, "%s %s", mob->name, ch->pcdata->familiar_name);
  free_string (mob->name);
  mob->name = str_dup (buf);
  if (str_cmp(ch->pcdata->familiar_name,""))
    sprintf (buf, "Your friend %s", ch->pcdata->familiar_name);
  else sprintf (buf, "Your friend");
  free_string (mob->short_descr);
  mob->short_descr = str_dup(buf);
  mob->exp = ch->pcdata->familiar_exp;
  mob->max_hit = ch->pcdata->familiar_max_hit;
  mob->hit = ch->pcdata->familiar_max_hit/2;
  mob->max_mana = ch->pcdata->familiar_max_mana;
  mob->mana = ch->pcdata->familiar_max_mana;
  mob->max_move = ch->pcdata->familiar_max_move;
  mob->move = ch->pcdata->familiar_max_move;
  mob->level = ch->pcdata->familiar_level;
  //  sprintf (buf, "%s %s", mob->name, ch->pcdata->familiar_name);
  // free_string (mob->name);
  // mob->name = str_dup (buf);
  mob->afkmsg = str_dup (ch->name);
  SET_BIT(mob->act2,ACT_FAMILIAR);
  SET_BIT(mob->affected_by,AFF_CHARM);
  if (mob->level >= 90)
	  mob->number_of_attacks = 3;
  else if (mob->level >= 45)
	  mob->number_of_attacks = 2;
  else mob->number_of_attacks = 1;
  mob->hitroll = mob->level/10 * 10;
  mob->damroll = mob->level/10 * 7;
  char_to_room(mob,ch->in_room);
  add_follower (mob, ch);
  ch->pcdata->familiar = mob;
  mob->leader = ch;
}

void familiar_poof(CHAR_DATA *ch)
{
  OBJ_DATA *obj,*obj_next;
  if (!ch->pcdata->familiar)
  {
	  log_string("Familiar poof called on with no familiar -> ");
          log_string(ch->name);
	  return;
  }
  if (!ch->pcdata->familiar->in_room)
  {
	  log_string("Familiar poof called on familiar not in room for -> ");
          log_string(ch->name);
	  return;
  }
      for (obj = ch->pcdata->familiar->carrying; obj; obj = obj_next)
	{
	  obj_next = obj->next_content;
	  unequip_char (ch->pcdata->familiar, obj);
	  obj_from_char (obj);
	  obj_to_room (obj,ch->pcdata->familiar->in_room);
	  act ("$p falls to the ground", ch->pcdata->familiar, obj, NULL, TO_ALL);
	}
  
  extract_char(ch->pcdata->familiar,TRUE);
  ch->pcdata->familiar = NULL;
}

void do_box(CHAR_DATA *ch, char *argument)
{
  OBJ_DATA *box=NULL, *obj=NULL;
  char arg[MAX_STRING_LENGTH];
  if (ch->class != PC_CLASS_CHAOS_JESTER || IS_NPC(ch))
    {
      send_to_char("Huh?\n\r",ch);
      return;
  }
  if (argument[0] == '\0')
    {
      send_to_char("Syntax: box look\n\r            get/put OBJ\n\r",ch);
      return;
    }
  argument = one_argument(argument,arg);
  box = get_obj_vnum_room(get_room_index(ROOM_VNUM_SWITCHED_LIMBO),OBJ_VNUM_CJ_SHARED_BOX);
  if (box == NULL)
    {
      send_to_char("No box for you!\n\r",ch);
      return;
    }
  if (!str_cmp(arg,"get"))
    {
      obj = get_obj_list (ch, argument, box->contains);
      if (obj == NULL)
	{
	  act ("You see nothing like that in the $p.", ch, box, NULL,
	       TO_CHAR);
	  return;
	}
      get_obj (ch, obj, box);
      trap_check(ch,"object",NULL,box);
      //Iblis - 3/11/04 - Antiduping Code
      if (!IS_NPC(ch))
	save_char_obj (ch);
      return;
    }
  if (!str_cmp(arg,"put"))
    {
      if ((obj = get_obj_carry (ch, argument)) == NULL)
        {
          send_to_char ("You do not have that item.\n\r", ch);
          return;
        }
      if (obj == box)
        {
          send_to_char ("You can't fold it into itself.\n\r", ch);
          return;
        }
      // Adeon 7/18/03 -- cant put nosave stuff in containers
      if (IS_OBJ_STAT (obj, ITEM_NOSAVE))
        {
          send_to_char ("Strong magic forces prevent you...\n\r", ch);
          return;
        }
      if (!can_drop_obj (ch, obj))
        {
          send_to_char ("You can't let go of it.\n\r", ch);
          return;
        }
      if (WEIGHT_MULT (obj) != 100 || obj->item_type == ITEM_QUIVER || WEIGHT_MULTP (obj) != 100)
        {
          send_to_char
            ("You have a feeling that would be a bad idea.\n\r", ch);
          return;
        }
      if (box->item_type == ITEM_QUIVER)
        {
          if (obj->item_type != ITEM_WEAPON || obj->value[0] != WEAPON_ARROW)
            {
              send_to_char ("Quivers can only hold arrows.\n\r", ch);
              return;
            }
          if (box->value[0] <= quiver_holding (box))
            {
              send_to_char ("That quiver is full.\n\r", ch);
              return;
            }
        }
      if (box->item_type != ITEM_CLAN_DONATION
          && box->item_type != ITEM_NEWCLANS_DBOX
          && box->item_type != ITEM_PLAYER_DONATION
          && box->item_type != ITEM_QUIVER)
        {
          if (get_obj_weight (obj) +
              get_true_weight (box) > (box->value[0] *
                                             10) || get_obj_weight (obj)
              > (box->value[3] * 10))
            {
              send_to_char ("It won't fit.\n\r", ch);
              return;
            }
        }

      obj_from_char (obj);
      obj_to_obj (obj, box);
      if (box != NULL && box->item_type == ITEM_PLAYER_DONATION)
        save_player_box (box);
      //Iblis - 3/11/04 - Antiduping Code
      if (!IS_NPC(ch))
        save_char_obj (ch);
      act ("$n puts $p in $P.", ch, obj, box, TO_ROOM);
      act ("You put $p in $P.", ch, obj, box, TO_CHAR);
    
      trip_triggers(ch, OBJ_TRIG_PUT, obj, NULL, OT_SPEC_NONE);
      trap_check(ch,"object",NULL,box);
      return;
    }
  if (!str_cmp(arg,"look"))
    {
      act ("$p holds:", ch, box, NULL, TO_CHAR);
      show_list_to_char (box->contains, ch, TRUE, TRUE);
      return;
    }
  do_box(ch,"");
}

void do_friendxp (CHAR_DATA * ch, char *argument)
{
  if (IS_NPC(ch) || ch->class != PC_CLASS_CHAOS_JESTER)
  {
    send_to_char("Huh?\n\r",ch);	  
    return;
  }
      // we have a mob thing
      if (ch->pcdata->all_xp_familiar)
        {
          send_to_char ("Your familiar will now only get 50% of the xp.\n\r", ch);
	  ch->pcdata->all_xp_familiar = FALSE;
          //REMOVE_BIT (ch->imm_flags, IMM_SUMMON);
        }

      else
        {
          send_to_char ("Your familiar will now get 100% of the xp.\n\r", ch);
	  ch->pcdata->all_xp_familiar = TRUE;
	  //          SET_BIT (ch->imm_flags, IMM_SUMMON);
        }
    
}