/
rogue24b3/
rogue24b3/data/
/***************************************************************************\
[*]    ___    ____   ____   __   __  ____ [*]   ROGUE: ROM With Attitude  [*]
[*]   /#/ )  /#/  ) /#/  ) /#/  /#/ /#/   [*]    All rights reserved      [*]
[*]  /#/ <  /#/  / /#/ _  /#/  /#/ /#/--  [*]   Copyright(C) 2000-2001    [*]
[*] /#/   \(#(__/ (#(__/ (#(__/#/ (#(___  [*] Kenneth Conley (Mendanbar)  [*]
[*]  Expression of Digital Creativity..   [*]  scmud@mad.scientist.com    [*]
[-]---------------------------------------+-+-----------------------------[-]
[*] File: vehicles.cpp                                                    [*]
[*] Usage: Vehicle Functions                                              [*]
\***************************************************************************/

#include "merc.h"
#include "interp.h"
#include "lookup.h"

void	vehicle_move(OBJ_DATA *vehicle, ROOM_INDEX_DATA *to);

extern	char *	dirs[];
extern	char *	dir_text[MAX_DIR];

#define VEHICLE_FLAGGED(vehicle, flag)	(IS_SET((vehicle)->value[1], (flag)))

#define NOWHERE				-1
#define DRIVE_NOT			0
#define DRIVE_CONTROL			1
#define DRIVE_MOUNT			2

#define ROOM_SECT(room)			(room->sector_type)

CHAR_DATA *get_char_on_obj(OBJ_DATA *obj);

OBJ_DATA *find_vehicle_by_vnum(int vnum) {
    OBJ_DATA *obj = NULL;

    for (obj = object_list; obj != NULL; obj = obj->next) {
	if (obj->pIndexData->vnum == vnum)
	    break;
    }
    return obj;
}

ACMD(do_mount) {
    CHAR_DATA *tch;
    OBJ_DATA *vehicle;
    char arg[MAX_INPUT_LENGTH];

    one_argument(argument, arg);

    if (!*arg)
	ch->Send("Mount what?\n\r");
    else if (!(vehicle = get_obj_list(ch, arg, IN_ROOM(ch)->contents)))
	ch->Send("You do not see that here.\n\r");
    else if ((tch = get_char_on_obj(vehicle)))
	act("$N is already mounted on $p.", ch, vehicle, tch, TO_CHAR);
    else if (!IS_MOUNTABLE(vehicle))
	act("You can't mount $p.", ch, vehicle, 0, TO_CHAR);
    else {
	act("You mount $p.", ch, vehicle, 0, TO_CHAR);
	act("$n mounts $p.", ch, vehicle, 0, TO_ROOM);
	GET_POS(ch) = POS_SITTING;
	ch->on = vehicle;
    }
}

ACMD(do_unmount) {
    if (!ch->on)
	ch->Send("You aren't sitting on anything.\n\r");
    else if (!IS_MOUNTABLE(ch->on))
	ch->Send("You aren't sitting on a vehicle.\n\r");
    else {
	GET_POS(ch) = POS_STANDING;
	act("You get off $p.", ch, ch->on, 0, TO_CHAR);
	act("$n gets off $p.", ch, ch->on, 0, TO_ROOM);
	ch->on = NULL;
    }
}

ACMD(do_drive) {
    int dir, drive_mode = DRIVE_NOT, i;
    OBJ_DATA *vehicle, *controls = NULL, *vehicle_in_out;
    char arg[MAX_INPUT_LENGTH];

    if (ch->on && IS_MOUNTABLE(ch->on))
	drive_mode = DRIVE_MOUNT;
    else {
	drive_mode = DRIVE_CONTROL;
	if (!(controls = get_obj_list_type(ITEM_V_CONTROLS, IN_ROOM(ch)->contents)))
	    if (!(controls = get_obj_list_type(ITEM_V_CONTROLS, ch->carrying)))
		for (i = 0; i < MAX_WEAR; i++) {
		    if ((controls = get_eq_char(ch, i)) && (controls->item_type == ITEM_V_CONTROLS))
			break;
		}
	if (!controls) {
	    ch->Send("You can't do that here.\n\r");
	    return;
	}
	if (!ch->CanUse(controls)) {
	    ch->Send("You can't figure out the controls.\n\r");
	    return;
	}
	if (ch->position > POS_SITTING) {
	    ch->Send("You must be sitting to drive.\n\r");
	    return;
	}
    }

    if (drive_mode == DRIVE_CONTROL) {
	vehicle = find_vehicle_by_vnum(controls->value[0]);
	if (!vehicle || vehicle->item_type != ITEM_VEHICLE) {
	    ch->Send("The controls seem to be broken.\n\r");
	    return;
	}
    } else if (!(vehicle = (ch->on)) || (IN_ROOM(vehicle) == NULL)) {
	ch->Send("The vehicle exists yet it doesn't.  Sorry, you're screwed...\r\n");
	return;
    }
    if (AFF_FLAGGED(ch, AFF_BLIND)) {
	ch->Send("You can't see the controls!\n\r");
	return;
    }

    argument = one_argument(argument, arg);

    if (!*arg)
	ch->Send("Drive which direction?\n\r");
    else if (is_abbrev(arg, "into")) {
	ROOM_INDEX_DATA *is_going_to;

	one_argument(argument, arg);

	if (!*arg)
	    ch->Send("Drive into what?\n\r");
	else if (!(vehicle_in_out = get_obj_list(ch, arg, IN_ROOM(vehicle)->contents)))
	    ch->Send("There is nothing here by that name.\n\r");
	else if (vehicle_in_out->item_type != ITEM_VEHICLE)
	    ch->Send("That is not a vehicle.\n\r");
	else if (vehicle == vehicle_in_out)
	    ch->Send("The laws of physics do not work that way.\n\r");
	else if (IS_MOUNTABLE(vehicle_in_out))
	    ch->Send("Thats a mountable vehicle, not one you can drive into!\n\r");
	else if (vehicle_in_out->value[0] == NOWHERE)
	    ch->Send("That is not a vehicle.\n\r");
	else if ((vehicle_in_out->value[4] / 2) < vehicle->value[4])
	    act("$p is too large to drive into $P.", ch, vehicle, vehicle_in_out, TO_CHAR);
	else if (!(is_going_to = get_room_index(vehicle_in_out->value[0])) ||
				!ROOM_FLAGGED(is_going_to, ROOM_VEHICLE))
	    ch->Send("That vehicle can't carry other vehicles.\n\r");
	else if (drive_mode == DRIVE_MOUNT) {
	    act("$n drives $p into $P.", ch, vehicle, vehicle_in_out, TO_ROOM);
	    act("You drive $p into $P.", ch, vehicle, vehicle_in_out, TO_CHAR);
	    vehicle_move(vehicle, is_going_to);
	    act("$n drives $p in.", ch, vehicle, 0, TO_ROOM);
	    look_at_room(ch, 0);
	} else {
	    act("You drive into $P", ch, 0, vehicle_in_out, TO_CHAR);
	    act("$n drives into $P.", ch, 0, vehicle_in_out, TO_ROOM);
	    act("$p enters $P.", 0, vehicle, vehicle_in_out, TO_ROOM);
	    vehicle_move(vehicle, is_going_to);
	    act("$p enters.", 0, vehicle, 0, TO_ROOM);
	    look_at_rnum(ch, IN_ROOM(vehicle), FALSE);
	}
    } else if (is_abbrev(arg, "out")) {
	OBJ_DATA *hatch;

	if (!(hatch = get_obj_list_type(ITEM_V_HATCH, IN_ROOM(vehicle)->contents)))
	    ch->Send("Nowhere to drive out of.\n\r");
	else if (!(vehicle_in_out = find_vehicle_by_vnum(hatch->value[0])) || (IN_ROOM(vehicle_in_out) == NULL))
	    ch->Send("ERROR! Vehicle to drive out of does not exist!\n\r");
	else if (drive_mode == DRIVE_MOUNT) {
	    act("$n drives $p out.", ch, vehicle, 0, TO_ROOM);
	    act("You drive $p out of $P.", ch, vehicle, vehicle_in_out, TO_CHAR);
	    vehicle_move(vehicle, IN_ROOM(vehicle_in_out));
	    act("$n drives $p out of $P.", ch, vehicle, vehicle_in_out, TO_ROOM);
	    look_at_room(ch, 0);
	} else {
	    act("$p exits $P.", 0, vehicle, vehicle_in_out, TO_ROOM);
	    vehicle_move(vehicle, IN_ROOM(vehicle_in_out));
	    act("$p drives out of $P.", 0, vehicle, vehicle_in_out, TO_ROOM);
	    act("$n drives out of $P.", ch, 0, vehicle_in_out, TO_ROOM);
	    act("You drive $p out of $P.", ch, vehicle, vehicle_in_out, TO_CHAR);
	    look_at_rnum(ch, IN_ROOM(vehicle), FALSE);
	}
    } else if ((dir = search_block(arg, dir_name, FALSE)) >= 0) {
	if (!ch || (dir < 0) || (dir >= MAX_DIR) || (IN_ROOM(vehicle) == NULL))
	    ch->Send("Sorry, an internal error has occurred.\n\r");
	else if (!CAN_GO(vehicle, dir))
	    ch->Send("Alas, you cannot go that way...\n\r");
	else if (EXIT_FLAGGED(EXIT(vehicle, dir), EX_CLOSED)) {
	    if (EXIT(vehicle, dir)->keyword)
		act("The $d seems to be closed.", ch, 0, (EXIT(vehicle, dir)->keyword), TO_CHAR);
	    else
		act("It seems to be closed.", ch, 0, 0, TO_CHAR);
	} else if (!ROOM_FLAGGED(EXIT(vehicle, dir)->u1.to_room, ROOM_VEHICLE) ||
	EXIT_FLAGGED(EXIT(vehicle, dir), EX_NOVEHICLES))
	    ch->Send("The vehicle can't manage that terrain.\n\r");
	else if (ROOM_SECT(EXIT(vehicle, dir)->u1.to_room) == SECT_AIR &&
	!VEHICLE_FLAGGED(vehicle, VEHICLE_AIR))
	    act("The $o can't fly.", ch, vehicle, 0, TO_CHAR);
	else if ((ROOM_SECT(EXIT(vehicle, dir)->u1.to_room) == SECT_WATER_NOSWIM) &&
	!VEHICLE_FLAGGED(vehicle, VEHICLE_WATER | VEHICLE_SUBMERGE))
	    act("The $o can't go in such deep water!", ch, vehicle, 0, TO_CHAR);
	else if ((ROOM_SECT(EXIT(vehicle, dir)->u1.to_room) == SECT_UNDERWATER) &&
	!VEHICLE_FLAGGED(vehicle, VEHICLE_SUBMERGE))
	    act("The $o can't go underwater!", ch, vehicle, 0, TO_CHAR);
	else if ((ROOM_SECT(EXIT(vehicle, dir)->u1.to_room) == SECT_SPACE) &&
	!VEHICLE_FLAGGED(vehicle, VEHICLE_SPACE))
	    act("The $o cannot handle space travel.", ch, vehicle, 0, TO_CHAR);
	else if ((ROOM_SECT(EXIT(vehicle, dir)->u1.to_room) > SECT_FIELD) &&
	(ROOM_SECT(EXIT(vehicle, dir)->u1.to_room) <= SECT_MOUNTAIN) &&
	!VEHICLE_FLAGGED(vehicle, VEHICLE_GROUND))
	    act("The $o cannot land on that terrain.", ch, vehicle, 0, TO_CHAR);
	else { // But nothing! Let's go that way!
	    if (drive_mode == DRIVE_MOUNT)
		act("$n drives $p $T.", ch, vehicle, dirs[dir], TO_ROOM);
	    else
		act("$p leaves $T.", 0, vehicle, dirs[dir], TO_ROOM);
	    vehicle_move(vehicle, EXIT(vehicle, dir)->u1.to_room);

	    if (drive_mode == DRIVE_MOUNT) {
		act("You drive $p $T.", ch, vehicle, dirs[dir], TO_CHAR);
		act("$n enters from $T on $p.", ch, vehicle, dir_text[rev_dir[dir]], TO_ROOM);
		if (ch->desc != NULL)
		    look_at_room(ch, 0);
	    } else {
		act("$p enters from $T.", 0, vehicle, dir_text[rev_dir[dir]], TO_ROOM);
		act("$n drives $T.", ch, 0, dirs[dir], TO_ROOM);
		act("You drive $T.", ch, 0, dirs[dir], TO_CHAR);
		if (ch->desc != NULL)
		    look_at_rnum(ch, IN_ROOM(vehicle), FALSE);
	    }
	}
    } else
	ch->Send("That is not a valid direction.\n\r");
    return;
}

void vehicle_move(OBJ_DATA *vehicle, ROOM_INDEX_DATA *to) {
    CHAR_DATA *tch;
    ROOM_INDEX_DATA *prev_in = IN_ROOM(vehicle);

    for (tch = prev_in->people; tch != NULL; tch = tch->next_in_room) {
	if (tch->on == vehicle) {
	    char_from_room(tch);
	    char_to_room(tch, to);
	    tch->on = vehicle;
	}
    }

    obj_from_room(vehicle);
    obj_to_room(vehicle, to);
}