kbk/kbk3/
kbk/kbk3/area/
kbk/kbk3/player/
#include "include.h"

// Track.c

/*
 * Modified by Baxter for Rom24bx (20-Feb-97)
 * deadland.ada.com.tr 9000 (195.142.130.3)
 * Track (Hunt) skill for warriors and thieves.
 */

/*
 * SillyMUD Distribution V1.1b             (c) 1993 SillyMUD Developement
 * See license.doc for distribution terms.   SillyMUD is based on DIKUMUD
 *
 * Modifications by Rip in attempt to port to merc 2.1
 */

/*
 * Modified by Turtle for Merc22 (07-Nov-94)
 *
 * I got this one from ftp.atinc.com:/pub/mud/outgoing/track.merc21.tar.gz.
 * It cointained 5 files: README, hash.c, hash.h, skills.c, and skills.h.
 * I combined the *.c and *.h files in this hunt.c, which should compile
 * without any warnings or errors.
 */

/*
 * Some systems don't have bcopy and bzero functions in their linked libraries.
 * If compilation fails due to missing of either of these functions,
 * define NO_BCOPY or NO_BZERO accordingly.                 -- Turtle 31-Jan-95
 */

//void bcopy(register char *s1,register char *s2,int len);
//void bzero(register char *sp,int len);

struct hash_link
{
  int			key;
  struct hash_link	*next;
  void			*data;
};

struct hash_header
{
  int			rec_size;
  int			table_size;
  int			*keylist, klistsize, klistlen; /* this is really lame,
							  AMAZINGLY lame */
  struct hash_link	**buckets;
};

#define WORLD_SIZE	30000
#define	HASH_KEY(ht,key)((((unsigned int)(key))*17)%(ht)->table_size)



struct hunting_data
{
  char			*name;
  struct char_data	**victim;
};

struct room_q
{
  int		room_nr;
  struct room_q	*next_q;
};

struct nodes
{
  int	visited;
  int	ancestor;
};

#define IS_DIR		(get_room_index(q_head->room_nr)->exit[i])
#define GO_OK		(!IS_SET( IS_DIR->exit_info, EX_CLOSED ))
#define GO_OK_SMARTER	1



#if defined( NO_BCOPY )
void bcopy(register char *s1,register char *s2,int len)
{
  while( len-- ) *(s2++) = *(s1++);
}
#endif

#if defined( NO_BZERO )
void bzero(register char *sp,int len)
{
  while( len-- ) *(sp++) = '\0';
}
#endif



void init_hash_table(struct hash_header	*ht,int rec_size,int table_size)
{
  ht->rec_size	= rec_size;
  ht->table_size= table_size;
  ht->buckets	= (void*)calloc(sizeof(struct hash_link**),table_size);
  ht->keylist	= (void*)malloc(sizeof(ht->keylist)*(ht->klistsize=128));
  ht->klistlen	= 0;
}

void init_world(ROOM_INDEX_DATA *room_db[])
{
  /* zero out the world */
  bzero((char *)room_db,sizeof(ROOM_INDEX_DATA *)*WORLD_SIZE);
}

void destroy_hash_table(struct hash_header *ht,void (*gman)())
{
  int			i;
  struct hash_link	*scan,*temp;

  for(i=0;i<ht->table_size;i++)
    for(scan=ht->buckets[i];scan;)
      {
	temp = scan->next;
	(*gman)(scan->data);
	free(scan);
	scan = temp;
      }
  free(ht->buckets);
  free(ht->keylist);
}

void _hash_enter(struct hash_header *ht,int key,void *data)
{
  /* precondition: there is no entry for <key> yet */
  struct hash_link	*temp;
  int			i;

  temp		= (struct hash_link *)malloc(sizeof(struct hash_link));
  temp->key	= key;
  temp->next	= ht->buckets[HASH_KEY(ht,key)];
  temp->data	= data;
  ht->buckets[HASH_KEY(ht,key)] = temp;
  if(ht->klistlen>=ht->klistsize)
    {
      ht->keylist = (void*)realloc(ht->keylist,sizeof(*ht->keylist)*
				   (ht->klistsize*=2));
    }
  for(i=ht->klistlen;i>=0;i--)
    {
      if(ht->keylist[i-1]<key)
	{
	  ht->keylist[i] = key;
	  break;
	}
      ht->keylist[i] = ht->keylist[i-1];
    }
  ht->klistlen++;
}

ROOM_INDEX_DATA *room_find(ROOM_INDEX_DATA *room_db[],int key)
{
  return((key<WORLD_SIZE&&key>-1)?room_db[key]:0);
}

void *hash_find(struct hash_header *ht,int key)
{
  struct hash_link *scan;

  scan = ht->buckets[HASH_KEY(ht,key)];

  while(scan && scan->key!=key)
    scan = scan->next;

  return scan ? scan->data : NULL;
}

int room_enter(ROOM_INDEX_DATA *rb[],int key,ROOM_INDEX_DATA *rm)
{
  ROOM_INDEX_DATA *temp;

  temp = room_find(rb,key);
  if(temp) return(0);

  rb[key] = rm;
  return(1);
}

int hash_enter(struct hash_header *ht,int key,void *data)
{
  void *temp;

  temp = hash_find(ht,key);
  if(temp) return 0;

  _hash_enter(ht,key,data);
  return 1;
}

ROOM_INDEX_DATA *room_find_or_create(ROOM_INDEX_DATA *rb[],int key)
{
  ROOM_INDEX_DATA *rv;

  rv = room_find(rb,key);
  if(rv) return rv;

  rv = (ROOM_INDEX_DATA *)malloc(sizeof(ROOM_INDEX_DATA));
  rb[key] = rv;

  return rv;
}

void *hash_find_or_create(struct hash_header *ht,int key)
{
  void *rval;

  rval = hash_find(ht, key);
  if(rval) return rval;

  rval = (void*)malloc(ht->rec_size);
  _hash_enter(ht,key,rval);

  return rval;
}

int room_remove(ROOM_INDEX_DATA *rb[],int key)
{
  ROOM_INDEX_DATA *tmp;

  tmp = room_find(rb,key);
  if(tmp)
    {
      rb[key] = 0;
      free(tmp);
    }
  return(0);
}

void *hash_remove(struct hash_header *ht,int key)
{
  struct hash_link **scan;

  scan = ht->buckets+HASH_KEY(ht,key);

  while(*scan && (*scan)->key!=key)
    scan = &(*scan)->next;

  if(*scan)
    {
      int		i;
      struct hash_link	*temp, *aux;

      temp	= (*scan)->data;
      aux	= *scan;
      *scan	= aux->next;
      free(aux);

      for(i=0;i<ht->klistlen;i++)
	if(ht->keylist[i]==key)
	  break;

      if(i<ht->klistlen)
	{
	  bcopy((char *)ht->keylist+i+1,(char *)ht->keylist+i,(ht->klistlen-i)
		*sizeof(*ht->keylist));
	  ht->klistlen--;
	}

      return temp;
    }

  return NULL;
}

void room_iterate(ROOM_INDEX_DATA *rb[],void (*func)(),void *cdata)
{
  register int i;

  for(i=0;i<WORLD_SIZE;i++)
    {
      ROOM_INDEX_DATA *temp;

      temp = room_find(rb,i);
      if(temp) (*func)(i,temp,cdata);
    }
}

void hash_iterate(struct hash_header *ht,void (*func)(),void *cdata)
{
  int i;

  for(i=0;i<ht->klistlen;i++)
    {
      void		*temp;
      register int	key;

      key = ht->keylist[i];
      temp = hash_find(ht,key);
      (*func)(key,temp,cdata);
      if(ht->keylist[i]!=key) /* They must have deleted this room */
	i--;		      /* Hit this slot again. */
    }
}



int exit_ok( EXIT_DATA *pexit )
{
  ROOM_INDEX_DATA *to_room;

  if ( ( pexit == NULL )
  ||   ( to_room = pexit->u1.to_room ) == NULL )
    return 0;

  return 1;
}

void donothing()
{
  return;
}

int find_path( int in_room_vnum, int out_room_vnum, CHAR_DATA *ch,
	       int depth, int in_zone )
{
  struct room_q		*tmp_q, *q_head, *q_tail;
  struct hash_header	x_room;
  int			i, tmp_room, count=0, thru_doors;
  ROOM_INDEX_DATA	*herep;
  ROOM_INDEX_DATA	*startp;
  EXIT_DATA		*exitp;

  if ( depth <0 )
    {
      thru_doors = TRUE;
      depth = -depth;
    }
  else
    {
      thru_doors = FALSE;
    }

  startp = get_room_index( in_room_vnum );

  init_hash_table( &x_room, sizeof(int), 2048 );
  hash_enter( &x_room, in_room_vnum, (void *) - 1 );

  /* initialize queue */
  q_head = (struct room_q *) malloc(sizeof(struct room_q));
  q_tail = q_head;
  q_tail->room_nr = in_room_vnum;
  q_tail->next_q = 0;

  while(q_head)
    {
      herep = get_room_index( q_head->room_nr );
      /* for each room test all directions */
      if( herep->area == startp->area || !in_zone )
	{
	  /* only look in this zone...
	     saves cpu time and  makes world safer for players  */
	  for( i = 0; i <= 5; i++ )
	    {
	      exitp = herep->exit[i];
	      if( exit_ok(exitp) && ( thru_doors ? GO_OK_SMARTER : GO_OK ) )
		{
		  /* next room */
		  tmp_room = herep->exit[i]->u1.to_room->vnum;
		  if( tmp_room != out_room_vnum )
		    {
		      /* shall we add room to queue ?
			 count determines total breadth and depth */
		      if( !hash_find( &x_room, tmp_room )
			 && ( count < depth ) )
			/* && !IS_SET( RM_FLAGS(tmp_room), DEATH ) ) */
			{
			  count++;
			  /* mark room as visted and put on queue */

			  tmp_q = (struct room_q *)
			    malloc(sizeof(struct room_q));
			  tmp_q->room_nr = tmp_room;
			  tmp_q->next_q = 0;
			  q_tail->next_q = tmp_q;
			  q_tail = tmp_q;

			  /* ancestor for first layer is the direction */
			  hash_enter( &x_room, tmp_room,
				     ((int)hash_find(&x_room,q_head->room_nr)
				      == -1) ? (void*)(i+1)
				     : hash_find(&x_room,q_head->room_nr));
			}
		    }
		  else
		    {
		      /* have reached our goal so free queue */
		      tmp_room = q_head->room_nr;
		      for(;q_head;q_head = tmp_q)
			{
			  tmp_q = q_head->next_q;
			  free(q_head);
			}
		      /* return direction if first layer */
		      if ((int)hash_find(&x_room,tmp_room)==-1)
			{
			  if (x_room.buckets)
			    {
			      /* junk left over from a previous track */
			      destroy_hash_table(&x_room, donothing);
			    }
			  return(i);
			}
		      else
			{
			  /* else return the ancestor */
			  int i;

			  i = (int)hash_find(&x_room,tmp_room);
			  if (x_room.buckets)
			    {
			      /* junk left over from a previous track */
			      destroy_hash_table(&x_room, donothing);
			    }
			  return( -1+i);
			}
		    }
		}
	    }
	}

      /* free queue head and point to next entry */
      tmp_q = q_head->next_q;
      free(q_head);
      q_head = tmp_q;
    }

  /* couldn't find path */
  if( x_room.buckets )
    {
      /* junk left over from a previous track */
      destroy_hash_table( &x_room, donothing );
    }
  return -1;
}



void do_acadian_track( CHAR_DATA *ch, char *argument )
{
  char buf[MAX_STRING_LENGTH];
  char arg[MAX_STRING_LENGTH];
  CHAR_DATA *victim;
  int direction;
  bool fArea;

  one_argument( argument, arg );

  if (IS_NPC(ch)
  ||  ch->level < skill_table[gsn_track].skill_level[ch->class])
  {
	send_to_char("Huh?\n\r",ch);
	return;
  }

  if( arg[0] == '\0' )
    {
      send_to_char( "Whom are you trying to track?\n\r", ch );
      return;
    }


  victim = get_char_world( ch, arg );
  fArea = ( get_trust(ch) < MAX_LEVEL );


  if( victim == NULL )
    {
      send_to_char("They aren't in the land.\n\r", ch );
      return;
    }

  if( ch->in_room == victim->in_room )
    {
      act( "$N is here!", ch, NULL, victim, TO_CHAR );
      return;
    }


  act( "$n carefully sniffs the air.", ch, NULL, NULL, TO_ROOM );
  //WAIT_STATE( ch, skill_table[gsn_track].beats );
  direction = find_path( ch->in_room->vnum, victim->in_room->vnum,
			ch, -40000, fArea );

  if( direction == -1 )
    {
      act( "You couldn't find a path to $N from here.",
	  ch, NULL, victim, TO_CHAR );
      return;
    }

  if( direction < 0 || direction > 5 )
    {
      send_to_char( "Hmm... Something seems to be wrong.\n\r", ch );
      return;
    }

  /*
   * Give a random direction if the player misses the die roll.
   */
  /*if( ( IS_NPC (ch) && number_percent () > 75)
     || (!IS_NPC (ch) && number_percent () >
	 ch->pcdata->learned[gsn_track] ) )
    {
      do
	{
	  direction = number_door();
	}
      while( ( ch->in_room->exit[direction] == NULL )
	    || ( ch->in_room->exit[direction]->u1.to_room == NULL) );
    }*/

  /*
   * Display the results of the search.
   */
  sprintf( buf, "$N is %s from here.", dir_name[direction] );
  act( buf, ch, NULL, victim, TO_CHAR );
  //check_improve(ch,gsn_track,TRUE,1);
  return;
}

DECLARE_DO_FUN(do_look);

void do_siphon( CHAR_DATA *ch, char *argument )
{
  char buf[MAX_STRING_LENGTH];
  char arg[MAX_STRING_LENGTH];
  char * name;
  char * last_name;
  int hit = 0, dam = 0;
  OBJ_DATA *corpse;
  OBJ_DATA *drained_corpse;
  OBJ_DATA *obj; 		// Shit in the corpse
  OBJ_DATA *obj_next;
  AFFECT_DATA af;
  AFFECT_DATA *paf;
  AFFECT_DATA *paf_next;

  one_argument(argument, arg);

  corpse = get_obj_list( ch, arg, ch->in_room->contents );

  if (IS_NPC(ch)
  ||  ch->level < skill_table[gsn_siphon].skill_level[ch->class])
  {
  	send_to_char("Huh?\n\r",ch);
  	return;
  }

  if (corpse == NULL)
  {
	  send_to_char("You don't see that here.\n\r", ch );
	  return;
  }

  if (corpse->pIndexData->vnum != OBJ_VNUM_CORPSE_PC)
  {
	  send_to_char("You can't siphon energy from that.\n\r", ch );
	  return;
  }

  if (strcmp(corpse->talked,ch->name))
  {
	  send_to_char("You can only drain your own kills.\n\r", ch );
	  return;
  }

  if (is_affected(ch, gsn_siphon))
  {
	  for ( paf = ch->affected; paf != NULL; paf = paf_next )
	  {
	  	paf_next = paf->next;
	  	if ( paf->type == gsn_siphon ) {
	  		switch (paf->location)
	  		{
	  		default: break;
	  		case APPLY_HITROLL: hit = paf->modifier; affect_remove( ch, paf ); break;
	  		case APPLY_DAMROLL: dam = paf->modifier; affect_remove( ch, paf ); break;
	  		}
	  	}
	  }

	  if (ch->level < 20)
	  {
		  hit += 1;
		  dam += 1;
	  }else if (ch->level < 30){
		  hit += 2;
		  dam += 2;
	  }else if (ch->level < 40){
		  hit += 3;
		  dam += 3;
	  }
	  else if (ch->level < 50){
		  hit += 4;
		  dam += 4;
	  }else{
		  hit += 5;
		  dam += 5;
	  }

	  init_affect(&af);
	  af.aftype 		= AFT_SKILL;
	  af.where     		= TO_AFFECTS;
	  af.type 	 		= gsn_siphon;
	  af.level	 		= ch->level;
	  af.duration       = -1;
	  af.modifier  		= hit;
	  af.bitvector 		= 0;
	  af.location  		= APPLY_HITROLL;
	  affect_to_char(ch,&af);
	  af.modifier		= dam;
	  af.location  		= APPLY_DAMROLL;
	  affect_to_char(ch,&af);

	  drained_corpse = create_object(get_obj_index(OBJ_VNUM_SIPHON_CORPSE),0);

	  for (obj = corpse->contains; obj != NULL; obj = obj_next)
	  {
	   	obj_next = obj->next_content;
	   	obj_from_obj(obj);
	   	obj_to_obj(obj,drained_corpse);
      }
	  name = corpse->short_descr;

	  last_name = name;
	  last_name = one_argument(last_name,name);
	  last_name = one_argument(last_name,name);
	  last_name = one_argument(last_name,name);
	  name = last_name;

	  sprintf(buf,"the drained and lifeless corpse of %s",name);
	  free_string(drained_corpse->short_descr);
	  drained_corpse->short_descr = str_dup(buf);
	  sprintf(buf,"The drained and lifeless corpse of %s is lying here.",name);
	  free_string(drained_corpse->description);
      drained_corpse->description = str_dup(buf);
	  extract_obj( corpse );
	  obj_to_room( drained_corpse, ch->in_room );

	  sprintf( buf, "$n magically siphons the life force from the corpse of %s.",
	  name );
	  act( buf, ch, NULL, NULL, TO_ROOM );
	  send_to_char("You feel more powerful as you siphon the life force from the corpse.\n\r",
	  ch );
	  check_improve(ch,gsn_siphon,TRUE,4);
	  WAIT_STATE(ch,skill_table[gsn_siphon].beats);
	  return;
  }
  else
  {
	  init_affect(&af);
	  af.aftype 		= AFT_SKILL;
	  af.where     		= TO_AFFECTS;
	  af.type 	 		= gsn_siphon;
	  af.level	 		= ch->level;
	  af.duration       = -1;
	  af.modifier  		= 2;
	  af.bitvector 		= 0;
	  af.location  		= APPLY_HITROLL;
	  affect_to_char(ch,&af);
	  af.modifier		= 2;
	  af.location  		= APPLY_DAMROLL;
	  affect_to_char(ch,&af);

	  drained_corpse = create_object(get_obj_index(OBJ_VNUM_SIPHON_CORPSE),0);

	  for (obj = corpse->contains; obj != NULL; obj = obj_next)
	  {
	  	obj_next = obj->next_content;
	  	obj_from_obj(obj);
	  	obj_to_obj(obj,drained_corpse);
      }

	  name = corpse->short_descr;

	  last_name = name;
	  last_name = one_argument(last_name,name);
	  last_name = one_argument(last_name,name);
	  last_name = one_argument(last_name,name);
	  name = last_name;

	  sprintf(buf,"the drained and lifeless corpse of %s",name);
	  free_string(drained_corpse->short_descr);
	  drained_corpse->short_descr = str_dup(buf);
	  sprintf(buf,"The drained and lifeless corpse of %s is lying here.",name);
	  free_string(drained_corpse->description);
      drained_corpse->description = str_dup(buf);
	  extract_obj( corpse );
	  obj_to_room( drained_corpse, ch->in_room );

	  sprintf( buf, "$n magically siphons the life force from the corpse of %s.",
	  name );
	  act( buf, ch, NULL, NULL, TO_ROOM );
	  send_to_char("You feel more powerful as you siphon the life force from the corpse.\n\r",
	  ch );
	  check_improve(ch,gsn_siphon,TRUE,4);
	  WAIT_STATE(ch,skill_table[gsn_siphon].beats);
	  return;
  }
}

void do_shadowform( CHAR_DATA *ch, char *argument )
{
	AFFECT_DATA af;
	char buf[MAX_STRING_LENGTH];
	char arg[MAX_STRING_LENGTH];
	int chance;

	argument = one_argument(argument,arg);

	if ((chance = get_skill(ch,gsn_cloak_form)) == 0
	|| ch->level < skill_table[gsn_cloak_form].skill_level[ch->class])
	{
		send_to_char("Huh?\n\r",ch);
	    return;
	}

	if (is_affected(ch,gsn_cloak_form))
	{
	    if(is_affected(ch, gsn_cloak_form))
	    {
		affect_strip(ch,gsn_cloak_form);
	    }
	    if(ch->original_name)
	    {
		free_string(ch->name);
		ch->name=str_dup(ch->original_name);
		free_string(ch->original_name);
		ch->original_name=NULL;
	    }
	    if (str_cmp(arg,"auto") )
	    send_to_char("You throw your cloak to the side, exposing yourself.\n\r",ch);

	    return;
	  }

	if (number_percent() < get_skill(ch,gsn_cloak_form))
	{
      init_affect(&af);
	  af.where    = TO_AFFECTS;
      af.aftype   = AFT_POWER;
	  af.type     = gsn_cloak_form;
 	  af.level    = ch->level;
	  af.location = APPLY_NONE;
	  af.modifier = 0;
	  af.bitvector = AFF_SNEAK;
	  af.duration = -1;
	  affect_to_char( ch, &af );
	  if(!(ch->original_name)) {
	 	free_string(ch->original_name);
		ch->original_name=str_dup(ch->name);
		free_string(ch->name);
		sprintf(buf, "a cloaked rider");
		ch->name=str_dup(buf);
	  }
	  af.location = APPLY_HIT;
	  af.modifier = ch->level*2;
	  affect_to_char(ch,&af);
	  af.location = APPLY_AC;
	  af.modifier = -ch->level;
	  affect_to_char(ch,&af);
	  check_improve(ch,gsn_cloak_form,TRUE,6);
	  send_to_char("You cloak your presence.\n\r",ch);
	  return;
	}
	else
	{
	  check_improve(ch,gsn_cloak_form, FALSE,3);
	  send_to_char("You fail to cloak yourself.\n\r",ch);
	  return;
	}
}

void do_steed( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *steed;
	CHAR_DATA *mob;
	AFFECT_DATA af;
	char arg[MAX_STRING_LENGTH];
	int chance, i;

	one_argument(argument,arg);

	if ((chance = get_skill(ch,gsn_steed)) == 0
	|| ch->level < skill_table[gsn_steed].skill_level[ch->class])
	{
		send_to_char("Huh?\n\r",ch);
	    return;
	}

	if (is_affected(ch, gsn_steed))
	{
		send_to_char("You can't summon the power to call forth another mount.\n\r", ch);
		return;
	}

	for (mob = char_list; mob != NULL; mob = mob->next)
	{
		if (IS_NPC(mob) && IS_AFFECTED(mob,AFF_CHARM)
	    && (mob->master == ch)
	    && ( (mob->pIndexData->vnum == MOB_VNUM_BLACK_STEED)
	    || (mob->pIndexData->vnum == MOB_VNUM_RED_STEED)
	    || (mob->pIndexData->vnum == MOB_VNUM_BLUE_STEED)
	    || (mob->pIndexData->vnum == MOB_VNUM_GREEN_STEED) ) )
	    break;
    }

    if (mob != NULL)
    {
		send_to_char("You've already got a mount.\n\r", ch);
		return;
	}

	if (!strcmp(arg, "black" ))
	{
		steed = create_mobile(get_mob_index(MOB_VNUM_BLACK_STEED) );

		for (i = 0; i < 4; i++)
		{
			steed->armor[i] -= (3*ch->level);
	   	}

	   	steed->max_hit = ch->max_hit*2;
		steed->hit 	   = ch->max_hit*2;
		steed->damroll = (ch->level/3);
		steed->hitroll = (ch->level/3);

		char_to_room(steed,ch->in_room);
		steed->level = ch->level;
		act("A thunderous roar is heard as a massive dragon steed lands beside $n!"
		,ch,0,steed,TO_ROOM);
		act("A massive dragon lands beside you!",ch,0,steed,TO_CHAR);
		ch->mana -= 50;
		SET_BIT(steed->affected_by,AFF_CHARM);
        steed->leader = ch;
	    steed->master = ch;

		init_affect(&af);
		af.where 	 = TO_AFFECTS;
		af.type 	 = gsn_steed;
		af.aftype    = AFT_SKILL;
		af.level 	 = ch->level;
		af.duration  = 24;
		af.location  = 0;
		af.modifier  = 0;
		af.bitvector = 0;
		affect_to_char(ch,&af);
		do_mount(ch,arg);
    	return;
	}
	else if (!strcmp(arg, "red" ))
	{
		steed = create_mobile(get_mob_index(MOB_VNUM_RED_STEED) );

		for (i = 0; i < 4; i++)
		{
			steed->armor[i] -= (3*ch->level);
	   	}

	   	steed->max_hit = ch->max_hit;
		steed->hit 	   = ch->max_hit;
		steed->damroll = (ch->level/1.5);
		steed->hitroll = (ch->level/1.5);

		char_to_room(steed,ch->in_room);
		steed->level = ch->level;
		act("A thunderous roar is heard as a massive dragon steed lands beside $n!"
		,ch,0,steed,TO_ROOM);
		act("A massive dragon lands beside you!",ch,0,steed,TO_CHAR);
		ch->mana -= 50;
		SET_BIT(steed->affected_by,AFF_CHARM);
        steed->leader = ch;
	    steed->master = ch;

		init_affect(&af);
		af.where 	 = TO_AFFECTS;
		af.type 	 = gsn_steed;
		af.aftype    = AFT_SKILL;
		af.level 	 = ch->level;
		af.duration  = 24;
		af.location  = 0;
		af.modifier  = 0;
		af.bitvector = 0;
		affect_to_char(ch,&af);
		do_mount(ch,arg);
    	return;
	}
	else if (!strcmp(arg, "blue" ))
	{
		steed = create_mobile(get_mob_index(MOB_VNUM_BLUE_STEED) );

		for (i = 0; i < 4; i++)
		{
			steed->armor[i] -= (4*ch->level);
	   	}

	   	steed->max_hit = ch->max_hit*1.5;
		steed->hit 	   = ch->max_hit*1.5;
		steed->damroll = (20 + ch->level/4);
		steed->hitroll = (20 + ch->level/4);

		char_to_room(steed,ch->in_room);
		steed->level = ch->level;
		act("A thunderous roar is heard as a massive dragon steed lands beside $n!"
		,ch,0,steed,TO_ROOM);
		act("A massive dragon lands beside you!",ch,0,steed,TO_CHAR);
		ch->mana -= 50;
		SET_BIT(steed->affected_by,AFF_CHARM);
        steed->leader = ch;
	    steed->master = ch;

		init_affect(&af);
		af.where 	 = TO_AFFECTS;
		af.type 	 = gsn_steed;
		af.aftype    = AFT_SKILL;
		af.level 	 = ch->level;
		af.duration  = 24;
		af.location  = 0;
		af.modifier  = 0;
		af.bitvector = 0;
		affect_to_char(ch,&af);
		do_mount(ch,arg);
    	return;
	}
	else if (!strcmp(arg, "green" ))
	{
		steed = create_mobile(get_mob_index(MOB_VNUM_GREEN_STEED) );

		for (i = 0; i < 4; i++)
		{
			steed->armor[i] -= (2*ch->level);
	   	}

	   	steed->max_hit = ch->max_hit*1.5;
		steed->hit 	   = ch->max_hit*1.5;
		steed->damroll = (ch->level/2);
		steed->hitroll = (ch->level/2);

		char_to_room(steed,ch->in_room);
		steed->level = ch->level;
		act("A thunderous roar is heard as a massive dragon steed lands beside $n!"
		,ch,0,steed,TO_ROOM);
		act("A massive dragon lands beside you!",ch,0,steed,TO_CHAR);
		ch->mana -= 50;
		SET_BIT(steed->affected_by,AFF_CHARM);
        steed->leader = ch;
	    steed->master = ch;

		init_affect(&af);
		af.where 	 = TO_AFFECTS;
		af.type 	 = gsn_steed;
		af.aftype    = AFT_SKILL;
		af.level 	 = ch->level;
		af.duration  = 24;
		af.location  = 0;
		af.modifier  = 0;
		af.bitvector = 0;
		affect_to_char(ch,&af);
		do_mount(ch,arg);
    	return;
	}else{
		send_to_char("You must choose either: [Blue, Black, Red or Green]\n\r", ch);
		return;
	}
}

void do_mount( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *mob;
	char arg[MAX_STRING_LENGTH];

	one_argument(argument, arg);

	if (arg == '\0')
	{
		send_to_char("Mount what?\n\r", ch );
		return;
	}

	if (IS_SET(ch->comm, COMM_MOUNTED))
	{
		send_to_char("Your already riding a mount.\n\r", ch );
		return;
	}

	if ( ( mob = get_char_room( ch, arg) ) == NULL )
	{
		send_to_char("You don't see that here.\n\r", ch );
		return;
	}

	if ( ( mob = get_char_room( ch, arg ) ) != NULL )
	{
		if (IS_NPC(mob) && IS_AFFECTED(mob,AFF_CHARM)
		&& (mob->master == ch)
		&& ( (mob->pIndexData->vnum == MOB_VNUM_BLACK_STEED)
		|| (mob->pIndexData->vnum == MOB_VNUM_RED_STEED)
		|| (mob->pIndexData->vnum == MOB_VNUM_BLUE_STEED)
		|| (mob->pIndexData->vnum == MOB_VNUM_GREEN_STEED) ) )
		{
			send_to_char("You gracefully sweep up onto your dragonmount.\n\r", ch);
			act("$n gracefully sweeps up onto $N's back and settles into the saddle."
			,ch,0,mob,TO_ROOM);
			SET_BIT(ch->comm, COMM_MOUNTED);
			return;
		}
		else
		{
			send_to_char("You can't mount that.\n\r", ch );
			return;
		}
	}
}

void do_dismount( CHAR_DATA *ch, char *argument )
{

	if (IS_SET(ch->comm, COMM_MOUNTED))
	{
		send_to_char("You effortlessly sweep down off your mount.\n\r", ch);
		act("$n effortlessly sweeps down off $s mount.",ch,0,0,TO_ROOM);
		REMOVE_BIT(ch->comm, COMM_MOUNTED);
		return;
	}
	else
	{
		send_to_char("You aren't mounted.\n\r", ch);
		return;
	}
}

void do_target( CHAR_DATA *ch, char *argument )
{
  	CHAR_DATA *victim;
  	AFFECT_DATA af;
  	char arg[MAX_STRING_LENGTH];


  	one_argument(argument, arg);

  	if (ch->cabal != CABAL_ACADIAN)
  	{
		send_to_char("Huh?\n\r", ch );
		return;
  	}

  	if (!strcmp(arg, "none"))
	{
		if (ch->pcdata->target == '\0')
		{
			send_to_char("You have no target to relase.\n\r", ch );
			return;
		}

		ch->pcdata->target = NULL;
		affect_strip(ch, gsn_target);
		send_to_char("You release your target.\n\r", ch );
		return;
	}



  	if ( (victim = get_char_world( ch, arg ) ) == NULL)
  	{
  		send_to_char("They aren't in the realm.\n\r",ch);
        return;
  	}

  	if (IS_NPC(victim))
  	{
		send_to_char("You can't target that!\n\r", ch );
		return;
	}

	if (IS_NPC(ch))
	{
		send_to_char("You can't do that!\n\r", ch );
		return;
	}

	if (victim == ch)
	{
		send_to_char("You can't target yourself.\n\r", ch );
		return;
	}

	if (victim->pcdata->bounty == 0)
	{
		send_to_char("They aren't marked.\n\r", ch );
		return;
	}


  	if (ch->pcdata->target == '\0')
  	{
		ch->pcdata->target = str_dup(victim->name);
  		send_to_char("You are now focused on your target.\n\r", ch );

  		init_affect(&af);
		af.where 	 = TO_AFFECTS;
		af.type 	 = gsn_target;
		af.aftype    = AFT_SKILL;
		af.level 	 = ch->level;
		af.duration  = 10;
		af.location  = 0;
		af.modifier  = 0;
		af.bitvector = 0;
		affect_to_char(ch,&af);
  		return;
	}
	else
	{
		ch->pcdata->target = str_dup(victim->name);
		send_to_char("You have refocused your target.\n\r", ch );
		affect_strip(ch, gsn_target);

		init_affect(&af);
		af.where 	 = TO_AFFECTS;
		af.type 	 = gsn_target;
		af.aftype    = AFT_SKILL;
		af.level 	 = ch->level;
		af.duration  = 10;
		af.location  = 0;
		af.modifier  = 0;
		af.bitvector = 0;
		affect_to_char(ch,&af);
  		return;
	}

}


void do_swoop( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *victim;
	CHAR_DATA *mob;
	char arg[MAX_STRING_LENGTH];
	int direction;
	int i;
	bool fArea;

	one_argument(argument, arg);




	if ( (victim = get_char_world( ch,arg )) == NULL)
	{
		send_to_char("They aren't here.\n\r",ch);
		return;
    }

    if (victim == ch)
	{
		send_to_char("That would be foolish, wouldn't it.\n\r",ch);
	    return;
	}

	if (is_safe(ch,victim))
    return;


    if (!IS_SET(ch->comm, COMM_MOUNTED))
	{
		send_to_char("You need to be mounted to swoop.\n\r", ch );
		return;
	}


	if( ch->in_room == victim->in_room )
	    {
	      act( "$N is here!", ch, NULL, victim, TO_CHAR );
	      return;
	    }

	fArea = ( get_trust(ch) < MAX_LEVEL );

	send_to_char("You rear your mount and swoop toward your victim.\n\r", ch );
	SET_BIT(ch->comm,COMM_BRIEF);

	for ( i = 0; i < 20; i++ )
	{
		direction = find_path( ch->in_room->vnum, victim->in_room->vnum, ch, -40000, fArea );

		if (number_percent() > ch->pcdata->learned[gsn_swoop])
		{
			send_to_char("You failed to swoop to them.\n\r", ch );
			return;
		}

		if( direction == -1 )
		{
			act( "You failed to swoop to them from here.",
		    ch, NULL, victim, TO_CHAR );
		    return;
		}

		if( direction < 0 || direction > 5 )
		{
			send_to_char( "Hmm... Something seems to be wrong.\n\r", ch );
		    return;
		}


		if ( ( mob = get_char_room( ch, arg ) ) != NULL )
		{
			if (IS_NPC(mob) && IS_AFFECTED(mob,AFF_CHARM)
			&& (mob->master == ch) )
			{
				move_char(mob, direction, TRUE );
				move_char(ch, direction, TRUE );
				check_improve(ch,gsn_swoop,TRUE,1);
			}
		}
		else
		{
			move_char(ch, direction, TRUE );
			check_improve(ch,gsn_swoop,TRUE,1);
		}
	}

	WAIT_STATE(ch,PULSE_VIOLENCE*1);
	check_improve(ch,gsn_swoop,FALSE,2);
	do_look(ch,"auto");
	REMOVE_BIT(ch->comm,COMM_BRIEF);
	return;

}