ackmud/
ackmud/area/imc/
ackmud/npcs/a/
ackmud/npcs/c/
ackmud/npcs/d/
ackmud/npcs/e/
ackmud/npcs/f/
ackmud/npcs/h/
ackmud/npcs/i/
ackmud/npcs/k/
ackmud/npcs/l/
ackmud/npcs/n/
ackmud/npcs/o/
ackmud/npcs/p/
ackmud/npcs/r/
ackmud/npcs/s/
ackmud/npcs/w/
ackmud/player/c/
ackmud/player/s/
ackmud/player/z/
/* Mount, ok ppl lets mount them damn horses, i knew they had to be good
 * for something.
 * 
 * Code written by Celestian on Oct 1st 1996
 *
 * Originally written for ThrynnMUD 2.0, Merc 2.2 based.
 *
 * Copyright (c) 1996 Virtual Research
 */


#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "merc.h"

/* external functions
 */
void	log_string	( const char *	str	);
int	move_gain	( CHAR_DATA *	ch	);

/* functions for riding
 */
void stop_riding	( CHAR_DATA *ch			);
void do_mount		( CHAR_DATA *ch, char *argument	);
void do_dismount	( CHAR_DATA *ch, char *argument	);
bool check_valid_ride	( CHAR_DATA *ch			);


void do_mount( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *mount;

	if ( IS_NPC ( ch ) )
	{
		send_to_char ( "Mob can't ride anything!\n\r ", ch );
		return;
	}

	one_argument(argument, arg);

	if (*arg)
	{
		if ( ( mount = get_char_room( ch, arg ) ) == NULL ) 
		{
			send_to_char ( "I see no one by that name "
				"here!\n\r", ch );
			return;
		}
	} else {
		send_to_char ( "Whom do you wish to ride?\n\r", ch );
		return;
	}

	if (ch->position == POS_RIDING)
	{
		if ( (ch->riding == NULL))
		{
			ch->position = POS_STANDING;
			send_to_char ( "Odd, you were mounted on thin air!\n\r",
				ch );
			return;
		}
	}

	if ( mount == ch )
	{
		send_to_char ( "Ride on your own back?  How?\n\r", ch );
		return;
	}

	if ( ch->position == POS_RIDING )
	{
		send_to_char ( "You are already riding on something.\n\r",
			ch );
		return;
	}

	if ( ch->in_room->room_flags & ROOM_SOLITARY )
	{
		send_to_char ( "This room is too narrow to ride.\n\r",
			ch );
		return;
	}

	if ( IS_NPC ( mount ) )
	{ 
		if ( !IS_SET ( mount->act, ACT_MOUNT ) )
		{
			act ( "It's too difficult to ride on $N.", ch, 0,
				mount, TO_CHAR );
			return;
		}

		if ( IS_AFFECTED ( mount, AFF_CHARM ) && mount->master != ch )
		{
			act ( "$N does not recognize you and refuses to "
				"let you ride $M.", ch, 0, mount, TO_CHAR );
			return;
		}

		if ( IS_NPC ( ch ) || ch->pcdata->learned[gsn_mount] == 0
	           || ( get_psuedo_level( ch ) < get_psuedo_level( mount ) ) )
		{
			act ( "You are not skillful enough to ride $N.",
				ch, NULL, mount, TO_CHAR );
			return;
		}

		if ( mount->rider && mount->rider != ch )
		{
			act ( "Someone else is riding on $N.", ch, 0,
				mount, TO_CHAR );
			return;
		}

		if ( ch->move < MOUNT_COST )
		{
			ch->move = 0;
			move_gain ( ch );
			act( "You are too tired to ride $N.", ch, 0,
				mount, TO_CHAR );
			return;
		}
		ch->move -= MOUNT_COST;
		move_gain( ch );

		ch->riding = mount;
		mount->rider = ch;
		ch->position = POS_RIDING;
		if ( !IS_SET ( mount->act, ACT_SENTINEL ) )
			SET_BIT ( mount->act, ACT_SENTINEL );
		act ( "You climb on and ride $N.", ch, 0, mount, TO_CHAR );
		act ( "$n climbs on and rides $N.", ch, 0, mount, TO_ROOM );
		act ( "$n climbs on and rides you.", ch, 0, mount, TO_VICT );
	} else {			
		send_to_char ( "You can't ride on another player!", ch ); 
	}

}

/* returns true if char is in same room.  Don't want to check ch
 * directly because it may be an invalid pointer already.
 * i.e.  Someone summons ride away and kills it.
 */

static int valid_ride ( int room, CHAR_DATA *	ch )
{
	CHAR_DATA *	i;

	if ( room == NOWHERE )
		return FALSE;
        if ( ch->in_room == NULL )
          return FALSE;
	for ( i = ch->in_room->first_person;
		i;
		i = i->next_in_room )
	{
		if ( IS_NPC ( i ) && ( i == ch ) )
		return TRUE;
	}
	return FALSE;
}

void do_dismount ( CHAR_DATA *ch, char *argument )
{
	if ( IS_NPC ( ch ) )
	{
		send_to_char ( "You can't dismount.\n\r", ch );
		return;
	}

	if ( ch->position == POS_RIDING )
	{
		if ( !IS_RIDING ( ch ) )
		{
			ch->position = POS_STANDING;
			send_to_char ( "Odd, you were mounted on thin air!\n\r", ch );
			return;
		}
	}

	if ( ch->position == POS_RIDING )
	{
		if ( valid_ride ( ch->in_room->vnum, ch->riding ) )
		{
			if ( ch->in_room->sector_type >= SECT_WATER_SWIM
			&& ch->level < 5 && !IS_AFFECTED ( ch, AFF_FLYING ) )
				act ( "Here? That's not too wise.", ch, 0,
					0, TO_CHAR );
			else {
				act ( "You dismount $N.", ch, 0,
					ch->riding, TO_CHAR );
				act ( "$n dismounts $N.", ch, 0,
					ch->riding, TO_ROOM );
                                if ( is_same_group( ch, ch->riding ) )
                                  do_group( ch, ch->riding->name );
				ch->position = POS_STANDING;
				ch->riding->rider = 0;
				ch->riding = 0;
			}
		} else	/* mount not in same room??? How did this happen? */
		stop_riding ( ch );
                if ( ch->riding != NULL )
                  stop_follower ( ch->riding );
	} else
	send_to_char( "You are not riding anything!\n\r", ch );
}

/* update riding info when mount/rider no longer in same room
 */

void stop_riding ( CHAR_DATA *	ch )
{
	CHAR_DATA *	mount, *	t_ch;

	if ( !ch )
		return;

	if (IS_NPC ( ch ) )
	{
		mount	=	ch;
		t_ch	=	mount->rider;
	} else {
		t_ch	=	ch;
		mount	=	t_ch->riding;
	}

	if ( !t_ch )			/* rider has gone poof */
	{
		if ( !mount )		/* so has the mount! */
		{
			return;
		} else {
			if ( !IS_NPC ( mount ) )
			{
				send_to_char ( "We would appreciate it if "
					"you explained how a player"
					"became a mount?\r\n", mount );
				mount->riding	=	NULL;
				mount->position		=	POS_STANDING;
				update_pos ( mount );
				return;
			} else {
				act ( "You realize that you no longer have "
					"a rider!", mount, 0, 0, TO_CHAR );
				mount->rider	=	0;
				return;
			}
		}
	} else {	/* well we have a rider of some sort */
		if (IS_NPC(t_ch))
		{
			char	buf	[MAX_STRING_LENGTH];

			sprintf ( buf, "NPC %s got on a mount somehow",
				t_ch->short_descr );
			log_string ( buf );
			t_ch->rider	=	NULL;
			update_pos ( t_ch );
			if ( mount )
			{
				send_to_char ( "Your analomous rider has "
					"been forcibly dismounted.\r\n",
					mount );
				if ( IS_NPC ( mount ) )
					mount->rider	=	NULL;
				else {
					send_to_char ( "We would "
						"appreciate it if you "
						"explained how a player "
						"became a mount?\r\n",
						mount );
					mount->riding	=	NULL;
					mount->position		=	POS_STANDING;
					update_pos( mount );
				}
			}
			return;
		}
		if ( t_ch->position != POS_RIDING )
		{
			if ( IS_RIDING ( t_ch ) )
			{
				char	buf	[ MAX_STRING_LENGTH ];
				sprintf ( buf, "%s on mount, but not "
					"RIDING", t_ch->name );
				log_string ( buf );
				t_ch->position	=	POS_RIDING;
			} else
			return;
		}
		if (!mount)	/* but mount has vanished! */
		{
			act ( "You fall to the ground.  You stop riding.",
				t_ch, 0, 0, TO_CHAR );
			t_ch->riding	=	NULL;
			t_ch->position		=	POS_RESTING;
			update_pos( t_ch );
		} else {	/* ok, mount and rider both exist, but t_ch is no longer riding */
			if ( t_ch->in_room != mount->in_room )
			{
				act ( "You fall to the ground.  You stop "
					"riding.", ch, 0, 0, TO_CHAR );
				t_ch->riding	=	NULL;
				ch->position		=	POS_RESTING;
				update_pos( ch );
				if ( !IS_NPC ( mount ) )
				{
					send_to_char ( "We would "
						"appreciate it if you "
						"explained how a player "
						"became a mount?\r\n",
						mount );
					mount->riding	=	NULL;
					mount->position		=	POS_STANDING;
					update_pos( mount );
					return;
				} else {
					act ( "You realize that you no "
						"longer have a rider!",
						mount, 0, 0, TO_CHAR );
					mount->rider	=	NULL;
				}
			} else {
				act ( "You stop riding $N.", t_ch, 0,
					mount, TO_CHAR );
                                if ( is_same_group( ch, mount ) )
                                {
                                  do_group( ch, mount->name );
                                }
				t_ch->riding	=	NULL;
				mount->rider	=	NULL;
				t_ch->position		=	POS_STANDING;
                                
			}
		}
	}
}

/* check to make sure mount and rider both exist and are in same room
 */

bool	check_valid_ride ( CHAR_DATA *	ch )
{
	if ( !ch || IS_NPC ( ch ) )
		return FALSE;

	if ( valid_ride ( ch->in_room->vnum, ch->riding ) )
		if ( (ch->riding)->rider == ch )
			return TRUE;

	stop_riding( ch );

	return FALSE;
}