/*************************************************************************** * 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 * * Castain, 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-1995 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@pacinfo.com) * * Gabrielle Taylor (gtaylor@pacinfo.com) * * Brian Moore (rom@rom.efn.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * ***************************************************************************/ /*************************************************************************** * ROT 1.4 is copyright 1996-1997 by Russ Walsh * * By using this code, you have agreed to follow the terms of the * * ROT license, in the file doc/rot.license * ***************************************************************************/ /* * Vehicle.c - ROM/ROT vehicle code. Ver. 2.05 * * Code is Copyright 1997 by Dominic J. Eidson, code may be freely * distributed and modified. * */ #if defined(macintosh) #include <types.h> #else #include <sys/types.h> #include <sys/time.h> #endif #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <time.h> #include "merc.h" #include "magic.h" #include "recycle.h" #include "tables.h" #include "lookup.h" /* command procedures needed */ /* * Local functions. */ int find_hack_door args( ( CHAR_DATA *ch, char *arg ) ); void enter_hack_exit args( ( CHAR_DATA *ch, OBJ_DATA *obj, char *arg ) ); void move_vehicle args( ( CHAR_DATA *ch, OBJ_DATA *obj, int door ) ); bool check_blind args( ( CHAR_DATA *ch ) ); void show_char_to_char args( ( CHAR_DATA *list, CHAR_DATA *ch ) ); void do_hack_exits args( ( CHAR_DATA *ch, ROOM_INDEX_DATA *room, char *argument ) ); BUFFER * show_list_to_char args( ( OBJ_DATA *list, CHAR_DATA *ch, bool fShort, bool fShowNothing ) ); void enter_hack_exit args( ( CHAR_DATA *ch, OBJ_DATA *obj, char *arg) ); void do_hack_look args( (CHAR_DATA *ch, char *argument ) ); void do_look args( (CHAR_DATA *ch, char *argument ) ); DECLARE_DO_FUN(do_stand ); /* New function needed for proper working */ OBJ_DATA *get_obj_exit( char *argument, OBJ_DATA *list ) { char arg[MIL]; OBJ_DATA *obj; int number; int count; number = number_argument( argument, arg ); count = 0; for ( obj = list; obj != NULL; obj = obj->next_content ) { if ( (obj->item_type == ITEM_EXIT) && is_name(arg, obj->name) ) { if ( ++count == number ) return obj; } } return NULL; } /* * Take care of exiting a vehicle */ void do_leave(CHAR_DATA *ch) { ROOM_INDEX_DATA *room; char buf[MSL]; /* Are we in a vehicle? */ if(ch->in_room->inside_of == NULL) { send_to_char("You are not riding anything.",ch); return; } sprintf(buf,"%s leaves %s.",IS_NPC(ch) ? ch->short_descr : capitalize(ch->name), ch->in_room->inside_of->short_descr); act("You leave $T.",ch,NULL,ch->in_room->inside_of->short_descr,TO_CHAR); act(buf,ch,NULL,NULL,TO_ROOM); room = ch->in_room->inside_of->in_room; char_from_room(ch); char_to_room(ch,room); act(buf, ch, NULL, NULL, TO_ROOM); do_look(ch, "auto"); } /* * the fullowing function is tricky. We are using a portal object as * vehicle. This means, we must dereference everything through * ch->in_room->inside_of, which is the vehicle object. * I am not yet sure how well this will work. */ void do_hack_look( CHAR_DATA *ch, char *argument ) { char buf [MSL]; char arg1 [MIL]; char arg2 [MIL]; char arg3 [MIL]; BUFFER *outlist; int number,count; if(IS_NPC(ch) && !ch->in_room->inside_of) return; if ( ch->position < POS_SLEEPING ) { send_to_char( "You can't see anything but stars!\n\r", ch ); return; } if ( ch->position == POS_SLEEPING ) { send_to_char( "You can't see anything, you're sleeping!\n\r", ch); return; } if ( !check_blind( ch ) ) return; if ( !IS_NPC(ch) && !IS_SET(ch->act, PLR_HOLYLIGHT) && room_is_dark( ch->in_room->inside_of->in_room ) ) { send_to_char( "It is pitch black ... \n\r", ch ); show_char_to_char( ch->in_room->inside_of->in_room->people, ch ); return; } argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); number = number_argument(arg1,arg3); count = 0; if ( arg1[0] == '\0' || !str_cmp( arg1, "auto" ) ) { /* 'look' or 'look auto' */ send_to_char( "{e", ch); send_to_char( ch->in_room->inside_of->in_room->name, ch); send_to_char( "{x", ch); if (IS_NPC(ch) || IS_SET(ch->act,PLR_HOLYLIGHT)) { sprintf(buf," [Room %d]",ch->in_room->inside_of->in_room->vnum); send_to_char(buf,ch); } send_to_char( "\n\r", ch ); if ( arg1[0] == '\0' || ( !IS_NPC(ch) && !IS_SET(ch->comm, COMM_BRIEF) ) ) { send_to_char( " ",ch); send_to_char( ch->in_room->inside_of->in_room->description, ch ); if (ch->in_room->inside_of->in_room->vnum == chain) { send_to_char("A huge black iron chain as thick as a tree trunk is drifting above the ground\n\r",ch); send_to_char("here.\n\r",ch); } } if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_AUTOEXIT) ) { send_to_char("\n\r",ch); do_hack_exits( ch, ch->in_room->inside_of->in_room, "auto" ); } outlist = show_list_to_char( ch->in_room->inside_of->in_room->contents, ch, FALSE, FALSE ); page_to_char( buf_string(outlist), ch ); free_buf(outlist); show_char_to_char( ch->in_room->inside_of->in_room->people,ch ); return; } return; } /* * Thanks to Zrin for auto-exit part. */ void do_hack_exits(CHAR_DATA *ch, ROOM_INDEX_DATA *room, char *argument ) { extern char * const dir_name[]; char buf[MSL]; EXIT_DATA *pexit; bool found; bool round; bool fAuto; int door; int outlet; fAuto = !str_cmp( argument, "auto" ); if ( !check_blind( ch ) ) return; if (fAuto) sprintf(buf,"[Exits:"); else if (IS_IMMORTAL(ch)) sprintf(buf,"Obvious exits from room %d:\n\r", room->vnum); else sprintf(buf,"Obvious exits:\n\r"); found = FALSE; for ( door = 0; door < 6; door++ ) { round = FALSE; outlet = door; if ( ( ch->alignment < 0 ) && ( pexit = room->exit[door+6] ) != NULL) outlet += 6; if ( ( pexit = room->exit[outlet] ) != NULL && pexit->u1.to_room != NULL && can_see_room(ch,pexit->u1.to_room) && !IS_SET(pexit->exit_info, EX_CLOSED) ) { found = TRUE; round = TRUE; if ( fAuto ) { strcat( buf, " " ); strcat( buf, dir_name[outlet] ); } else { sprintf( buf + strlen(buf), "%-5s - %s", capitalize( dir_name[outlet] ), room_is_dark( pexit->u1.to_room ) ? "Too dark to tell" : pexit->u1.to_room->name ); if (IS_IMMORTAL(ch)) sprintf(buf + strlen(buf), " (room %d)\n\r",pexit->u1.to_room->vnum); else sprintf(buf + strlen(buf), "\n\r"); } } if (!round) { OBJ_DATA *portal; ROOM_INDEX_DATA *to_room; portal = get_obj_exit( dir_name[door], room->contents ); if (portal != NULL) { found = TRUE; round = TRUE; if ( fAuto ) { strcat( buf, " " ); strcat( buf, dir_name[door] ); } else { to_room = get_room_index(portal->value[0]); sprintf( buf + strlen(buf), "%-5s - %s", capitalize( dir_name[door] ), room_is_dark( to_room ) ? "Too dark to tell" : to_room->name ); if (IS_IMMORTAL(ch)) sprintf(buf + strlen(buf), " (room %d)\n\r",to_room->vnum); else sprintf(buf + strlen(buf), "\n\r"); } } } } if ( !found ) strcat( buf, fAuto ? " none" : "None.\n\r" ); if ( fAuto ) strcat( buf, "]\n\r" ); send_to_char( buf, ch ); return; } void move_vehicle( CHAR_DATA *ch, OBJ_DATA *obj, int door ) { ROOM_INDEX_DATA *in_room; ROOM_INDEX_DATA *to_room; EXIT_DATA *pexit; char buf[MSL]; CHAR_DATA *vch; in_room = obj->in_room; if ( ( pexit = in_room->exit[door] ) == NULL ) { send_to_char("There is no way to go that direction.", ch ); return; } if ( ( ch->alignment > 0 ) && door < 6 && ( pexit = in_room->exit[door+6] ) != NULL ) { door += 6; } else if ( ( pexit = in_room->exit[door] ) == NULL) { if (0) { OBJ_DATA *portal; portal = get_obj_list( ch, dir_name[door], ch->in_room->inside_of->in_room->contents ); if (portal != NULL) { enter_hack_exit( ch, portal, dir_name[door] ); return; } } } if ( ( pexit = in_room->exit[door] ) == NULL || ( to_room = pexit->u1.to_room ) == NULL || !can_see_room(ch,pexit->u1.to_room)) { return; } if (IS_SET(pexit->exit_info, EX_CLOSED)) { return; } if ( in_room->sector_type == SECT_AIR || to_room->sector_type == SECT_AIR ) { send_to_char( "Vehicles can't fly.\n\r", ch); return; } if ( in_room->sector_type == SECT_WATER_NOSWIM || to_room->sector_type == SECT_WATER_NOSWIM ) { send_to_char("You can't take a vehicle there!", ch); return; } sprintf(buf, "%s rolls off %s.", capitalize(ch->in_room->inside_of->short_descr), dir_name[door]); for ( vch = ch->in_room->inside_of->in_room->people; vch != NULL; vch = vch->next_in_room ) { send_to_char(buf,vch); } obj_from_room( obj ); obj_to_room( obj, to_room ); sprintf(buf, "%s rolls in.", capitalize(ch->in_room->inside_of->short_descr)); for ( vch = ch->in_room->inside_of->in_room->people; vch != NULL; vch = vch->next_in_room ) { send_to_char(buf,vch); } for ( vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room ) do_hack_look( vch, "auto" ); if (in_room == to_room) /* no circular follows */ return; } /* RW Enter movable exits */ void enter_hack_exit( CHAR_DATA *ch, OBJ_DATA *obj, char *arg) { ROOM_INDEX_DATA *location; if (arg[0] != '\0') { ROOM_INDEX_DATA *old_room; OBJ_DATA *portal; old_room = obj->in_room; portal = get_obj_list( ch, arg, obj->in_room->contents ); if (portal == NULL) { send_to_char("And how would you do that?\n\r",ch); return; } if (portal->item_type != ITEM_EXIT) { send_to_char("And how would you do that?\n\r",ch); return; } location = get_room_index(portal->value[0]); if (location == NULL || location == old_room || !can_see_room(ch,location) || (room_is_private(ch,location) && !IS_TRUSTED(ch,IMPLEMENTOR))) { send_to_char("And how would you do that?\n\r",ch); return; } if ( !IS_NPC(ch) ) { if ( old_room->sector_type == SECT_AIR || location->sector_type == SECT_AIR ) { send_to_char("Vehicles can't fly.", ch); return; } if (( old_room->sector_type == SECT_WATER_NOSWIM || location->sector_type == SECT_WATER_NOSWIM )) { send_to_char( "Vehicles can not go there.\n\r", ch ); return; } } if ( !IS_AFFECTED(ch, AFF_SNEAK) && ch->invis_level <= LEVEL_HERO && ch->ghost_level <= LEVEL_HERO) { act("$n rolls off $T.",ch,NULL,arg,TO_ROOM); } obj_from_room(obj); obj_to_room(obj, location); if ( !IS_AFFECTED(ch, AFF_SNEAK) && ch->invis_level <= LEVEL_HERO && ch->ghost_level <= LEVEL_HERO) { act("$n rolls in.",ch,NULL,NULL,TO_ROOM); } do_hack_look(ch,"auto"); /* protect against circular follows */ if (old_room == location) return; return; } send_to_char("Alas, you cannot go that way.\n\r",ch); return; } void do_north( CHAR_DATA *ch, char *argument ) { /* if(ch->in_room->inside_of) send_to_char("You are riding.\n\r",ch); else */ move_char( ch, DIR_NORTH, FALSE, FALSE ); return; } void do_east( CHAR_DATA *ch, char *argument ) { move_char( ch, DIR_EAST, FALSE, FALSE ); return; } void do_south( CHAR_DATA *ch, char *argument ) { move_char( ch, DIR_SOUTH, FALSE, FALSE ); return; } void do_west( CHAR_DATA *ch, char *argument ) { move_char( ch, DIR_WEST, FALSE, FALSE ); return; } void do_up( CHAR_DATA *ch, char *argument ) { move_char( ch, DIR_UP, FALSE, FALSE ); return; } void do_down( CHAR_DATA *ch, char *argument ) { move_char( ch, DIR_DOWN, FALSE, FALSE ); return; } /* RT Enter portals */ void do_enter( CHAR_DATA *ch, char *argument) { ROOM_INDEX_DATA *location; if ( ch->fighting != NULL ) return; /* nifty portal stuff */ if (argument[0] != '\0') { ROOM_INDEX_DATA *old_room; OBJ_DATA *portal; CHAR_DATA *fch, *fch_next; old_room = ch->in_room; portal = get_obj_list( ch, argument, ch->in_room->contents ); // steve if (portal == NULL) { send_to_char("You don't see that here.\n\r",ch); return; } /* if (portal->item_type != ITEM_PORTAL || portal->item_type != ITEM_VEHICLE || (IS_SET(portal->value[1],EX_CLOSED) && !IS_TRUSTED(ch,KNIGHT))) { send_to_char("You can't seem to find a way in.\n\r",ch); return; } */ if (portal->item_type == ITEM_CORPSE_PC && !str_cmp(portal->owner, ch->name) && ch->spirit) { OBJ_DATA *obj; OBJ_DATA *obj_next; for ( obj = portal->contains; obj != NULL; obj = obj_next ) { obj_next = obj->next_content; obj_from_obj( obj ); if ( obj->item_type == ITEM_MONEY) { if (obj->value[0] > 0) add_cost(ch,obj->value[0],VALUE_SILVER); if (obj->value[1] > 0) add_cost(ch,obj->value[1],VALUE_GOLD); if (obj->value[2] > 0) add_cost(ch,obj->value[2],VALUE_PLATINUM); extract_obj( obj ); } else { obj_to_char( obj, ch ); } } extract_obj( portal ); ch->spirit = 0; send_to_char("You reach down and touch your corpse, and are suddenly\n\r",ch); send_to_char("sucked inside. You wake up to the agonizing pain of your last\n\r",ch); send_to_char("battle, and slowly climb to your feet.\n\r",ch); return; } if(portal->item_type == ITEM_PORTAL) { if (!IS_TRUSTED(ch,KNIGHT) && !IS_SET(portal->value[2],GATE_NOCURSE) && (IS_AFFECTED(ch,AFF_CURSE) || IS_SET(old_room->room_flags,ROOM_NO_RECALL))) { send_to_char("Something prevents you from leaving...\n\r",ch); return; } if (IS_SET(portal->value[2],GATE_RANDOM) || portal->value[3] == -1) { location = get_random_room(ch); portal->value[3] = location->vnum; /* for record keeping :) */ } else if (IS_SET(portal->value[2],GATE_BUGGY) && (number_percent() < 5)) location = get_random_room(ch); else location = get_room_index(portal->value[3]); if (location == NULL || location == old_room || !can_see_room(ch,location) || !can_see_door(ch,(long)portal->value[1]) || (room_is_private(ch,location) && !IS_TRUSTED(ch,IMPLEMENTOR))) { act("$p doesn't seem to go anywhere.",ch,portal,NULL,TO_CHAR); return; } if (IS_NPC(ch) && IS_SET(ch->act,ACT_AGGRESSIVE) && IS_SET(location->room_flags,ROOM_LAW)) { send_to_char("Something prevents you from leaving...\n\r",ch); return; } act("$n steps into $p.",ch,portal,NULL,TO_ROOM); if (IS_SET(portal->value[2],GATE_NORMAL_EXIT)) act("You enter $p.",ch,portal,NULL,TO_CHAR); else act("You walk through $p and find yourself somewhere else...", ch,portal,NULL,TO_CHAR); char_from_room(ch); char_to_room(ch, location); if (IS_SET(portal->value[2],GATE_GOWITH)) /* take the gate along */ { obj_from_room(portal); obj_to_room(portal,location); } if (IS_SET(portal->value[2],GATE_NORMAL_EXIT)) act("$n has arrived.",ch,portal,NULL,TO_ROOM); else act("$n has arrived through $p.",ch,portal,NULL,TO_ROOM); do_look(ch,"auto"); /* charges */ if (portal->value[0] > 0) { portal->value[0]--; if (portal->value[0] == 0) portal->value[0] = -1; } /* protect against circular follows */ if (old_room == location) return; if (ch->shadowed) { for ( fch = ch->shadower->in_room->people; fch != NULL; fch = fch->next_in_room ) { if (IS_NPC(fch)) continue; if (fch == ch->shadower) continue; if (!IS_IMMORTAL(fch)) continue; if (fch->level < get_trust(ch->shadower)) continue; act( "$n slips out of the room.", ch->shadower, NULL, fch, TO_VICT ); } char_from_room( ch->shadower ); char_to_room( ch->shadower, location ); for ( fch = ch->shadower->in_room->people; fch != NULL; fch = fch->next_in_room ) { if (IS_NPC(fch)) continue; if (fch == ch->shadower) continue; if (!IS_IMMORTAL(fch)) continue; if (fch->level < get_trust(ch->shadower)) continue; act( "$n silently slips into the room.", ch->shadower, NULL, fch, TO_VICT ); } act( "You follow $N.", ch->shadower, NULL, ch, TO_CHAR ); do_look( ch->shadower, "auto" ); } for ( fch = old_room->people; fch != NULL; fch = fch_next ) { fch_next = fch->next_in_room; if (portal == NULL || portal->value[0] == -1) /* no following through dead portals */ continue; if ( fch->master == ch && IS_AFFECTED(fch,AFF_CHARM) && fch->position < POS_STANDING) do_stand(fch,""); if ( fch->master == ch && fch->position == POS_STANDING) { if (IS_SET(ch->in_room->room_flags,ROOM_LAW) && (IS_NPC(fch) && IS_SET(fch->act,ACT_AGGRESSIVE))) { act("You can't bring $N into the city.", ch,NULL,fch,TO_CHAR); act("You aren't allowed in the city.", fch,NULL,NULL,TO_CHAR); continue; } act( "You follow $N.", fch, NULL, ch, TO_CHAR ); do_enter(fch,argument); } } if (portal != NULL && portal->value[0] == -1) { act("$p fades out of existence.",ch,portal,NULL,TO_CHAR); if (ch->in_room == old_room) act("$p fades out of existence.",ch,portal,NULL,TO_ROOM); else if (old_room->people != NULL) { act("$p fades out of existence.", old_room->people,portal,NULL,TO_CHAR); act("$p fades out of existence.", old_room->people,portal,NULL,TO_ROOM); } extract_obj(portal); } return; } if(portal->item_type == ITEM_VEHICLE) { if (!IS_TRUSTED(ch,KNIGHT) && (IS_AFFECTED(ch,AFF_CURSE) || IS_SET(old_room->room_flags,ROOM_NO_RECALL))) { send_to_char("Something prevents you from leaving...\n\r",ch); return; } location = get_room_index(portal->value[3]); if (location == NULL || location == old_room || !can_see_room(ch,location) || (room_is_private(ch,location) && !IS_TRUSTED(ch,IMPLEMENTOR))) { act("$p doesn't seem to go anywhere.",ch,portal,NULL,TO_CHAR); return; } if (IS_NPC(ch) && IS_SET(ch->act,ACT_AGGRESSIVE) && IS_SET(location->room_flags,ROOM_LAW)) { send_to_char("Something prevents you from leaving...\n\r",ch); return; } act("$n enters $p.",ch,portal,NULL,TO_ROOM); char_from_room(ch); char_to_room(ch, location); act("$n has entered $p.",ch,portal,NULL,TO_ROOM); do_look(ch,"auto"); /* protect against circular follows */ if (old_room == location) return; if(portal->item_type == ITEM_VEHICLE) { ch->in_room->inside_of = portal; } for ( fch = old_room->people; fch != NULL; fch = fch_next ) { fch_next = fch->next_in_room; if (portal == NULL || portal->value[0] == -1) /* no following through dead portals */ continue; if ( fch->master == ch && IS_AFFECTED(fch,AFF_CHARM) && fch->position < POS_STANDING) do_stand(fch,""); if ( fch->master == ch && fch->position == POS_STANDING) { if (IS_SET(ch->in_room->room_flags,ROOM_LAW) && (IS_NPC(fch) && IS_SET(fch->act,ACT_AGGRESSIVE))) { act("You can't take $N into vehicles.", ch,NULL,fch,TO_CHAR); act("You aren't allowed in vehicles.", fch,NULL,NULL,TO_CHAR); continue; } act( "You follow $N.", fch, NULL, ch, TO_CHAR ); do_enter(fch,argument); } } return; } } send_to_char("Nope, can't do it.\n\r",ch); return; } void do_drive(CHAR_DATA *ch, char *argument) { int door; if(ch->in_room->inside_of == NULL) { send_to_char("You are not riding anything.\n\r",ch); return; } if(argument[0] == '\0') { send_to_char("Syntax: drive <direction>\n\r",ch); return; } door = find_hack_door(ch, argument); move_vehicle(ch, ch->in_room->inside_of, door); return; } int find_hack_door( CHAR_DATA *ch, char *arg ) { EXIT_DATA *pexit; int door; if ( !str_cmp( arg, "n" ) || !str_cmp( arg, "north" ) ) door = 0; else if ( !str_cmp( arg, "e" ) || !str_cmp( arg, "east" ) ) door = 1; else if ( !str_cmp( arg, "s" ) || !str_cmp( arg, "south" ) ) door = 2; else if ( !str_cmp( arg, "w" ) || !str_cmp( arg, "west" ) ) door = 3; else if ( !str_cmp( arg, "u" ) || !str_cmp( arg, "up" ) ) door = 4; else if ( !str_cmp( arg, "d" ) || !str_cmp( arg, "down" ) ) door = 5; else { for ( door = 0; door <= 5; door++ ) { if ( (ch->alignment < 0) && ( pexit = ch->in_room->inside_of->in_room->exit[door+6] ) != NULL && IS_SET(pexit->exit_info, EX_ISDOOR) && pexit->keyword != NULL && is_name( arg, pexit->keyword ) ) { return door+6; } else if ( ( pexit = ch->in_room->inside_of->in_room->exit[door] ) != NULL && IS_SET(pexit->exit_info, EX_ISDOOR) && pexit->keyword != NULL && is_name( arg, pexit->keyword ) ) { return -1; } } act( "I see no $T here.", ch, NULL, arg, TO_CHAR ); return -1; } if ( (ch->alignment < 0) && (pexit = ch->in_room->inside_of->in_room->exit[door+6] ) != NULL ) { door += 6; } if ( ( pexit = ch->in_room->inside_of->in_room->exit[door] ) == NULL ) { act( "I see no door $T here.", ch, NULL, arg, TO_CHAR ); return -1; } return door; }