/* ********************************************************************** * file: transport.cc * * author: Andrew Hynek * * (original monorail code, now deleted, written by Chris Dickey) * * purpose: contains all routines for time- and command-based transport * * Copyright (c) 1998 by Andrew Hynek * * (c) 2001 The AwakeMUD Consortium * ********************************************************************** */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <sys/types.h> #if defined(WIN32) && !defined(__CYGWIN__) #define strcasecmp(x, y) _stricmp(x,y) #else #endif #include "structs.h" #include "awake.h" #include "utils.h" #include "comm.h" #include "interpreter.h" #include "handler.h" #include "db.h" #include "transport.h" #include "utils.h" #include "constants.h" SPECIAL(call_elevator); SPECIAL(elevator_spec); extern int find_first_step(vnum_t src, vnum_t target); // ---------------------------------------------------------------------------- // ______________________________ // // static vars // ______________________________ static struct elevator_data *elevator = NULL; static int num_elevators = 0; static const int NUM_SEATTLE_STATIONS = 6; static const int NUM_SEATAC_STATIONS = 4; static struct dest_data destinations[] = { { "tacoma", "Tacoma", 2000 }, { "afterlife", "The Afterlife", 2072 }, { "chinatown", "ChinaTown", 2527 }, { "evergreen", "Evergreen Complex", 2201 }, { "twe", "Tacoma Weapons Emporium", 2514 }, { "nybbles", "Nybbles and Bytes", 2057 }, { "biohyde", "Biohyde Complex", 4201 }, { "puyallup", "Central Puyallup", 2457 }, { "park", "Seattle State Park", 4000 }, { "seattle", "Seattle", 32679 }, { "cinema", "Le Cinema Vieux", 32588 }, { "vieux", "Le Cinema Vieux", 32588 }, { "charne", "La Charne", 30548 }, { "tarislar", "Tarislar", 4965 }, { "reaper", "The Reaper", 32517 }, { "platinum", "Platinum Club", 32685 }, { "penumbra", "Club Penumbra", 32587 }, { "big", "The Big Rhino", 32635 }, { "epicenter", "The Epicenter", 2418 }, { "yoshi", "Yoshi's Sushi Bar", 32751 }, { "airport", "Seattle-Tacoma Airport", 19410 }, { "aztech", "Aztechnology Pyramid", 30539 }, { "garage", "Seattle Parking Garage", 32720 }, { "formal", "Seattle Formal Wear", 32746 }, { "sda", "The SDA Plaza", 30610 }, { "dante", "Dante's Inferno", 32661 }, { "quinns", "Quinn's", 32521 }, { "shintaru", "Shintaru", 32513 }, { "docks", "Seattle Dockyards", 32500 }, { "modern", "Modern Magik", 30514 }, { "methodist", "Seattle First Methodist", 30565 }, { "sculleys", "Sculleys", 30591 }, { "council", "Council Island", 9149 }, { "moonlight", "Moonlight Mall", 14373 }, { "library", "Seattle Public Library", 30600 }, { "kristins", "Kristin's", 30578 }, { "mitsuhama", "Mitsuhama Towers", 32722 }, { "chiba", "Little Chiba", 32686 }, { "stop", "The Stop Gap", 32708 }, { "apartment", "Redmond Apartment Block", 14337 }, { "humana", "Humana Hospital", 2536 }, { "hospital", "Council Island Hospital", 9161 }, { "coffin", "Tacoma Coffin Hotel", 2045 }, { "diver", "Easy Diver Coffin Hotel", 32644 }, { "action", "Action Computers", 32650 }, { "hellhound", "Hellhound Bus Stop", 32501 }, { "lysleul", "Lysleul Plaza", 30551 }, { "novatech", "Novatech Seattle", 32541 }, { "syberspace", "SyberSpace", 30612 }, { "bank", "UCASBank", 30524 }, { "matchsticks", "Matchsticks", 30579 }, { "homewood", "Homewood Suites", 30512 }, { "mall", "Tacoma Mall", 2093 }, { "racespec", "Racespec Performance", 30573 }, { "smiths", "Smith's Pub", 32566 }, { "\n", "", 0 } // this MUST be last }; static struct dest_data port_destinations[] = { { "hellhound", "Hellhound Bus Station", 14624 }, { "postal", "Royal Postal Station", 14629 }, { "trans-oregon", "Trans-Oregon Trucking", 14604 }, { "thompson", "Thompson Autogroup", 14602}, { "hard", "Hard Times", 14608 }, { "bank", "TT-Bank", 14610 }, { "sixth", "Sixth Street Parking", 14680 }, { "satyricon", "The Satyricon", 14611 }, { "rocco", "Rocco's Pizza", 14730 }, { "annabel", "Annabel's Antiquities", 2710 }, { "square", "O'Bryant Square", 2708 }, { "parking", "Portland City Parking", 2703 }, { "mary", "Mary's Bar", 14712 }, { "tower", "TTBank Tower", 14743 }, { "city", "City Center Parking", 14751 }, { "habitat", "Telestrian Habitat", 18800 }, { "hospital", "Royal Hospital", 14707 }, { "toadstool", "The Toadstool", 14671 }, { "powells", "Powell's Technical Books", 14724 }, { "davis", "Davis Street Offices", 14667 }, { "max", "Downtown MAX Station", 20800 }, { "\n", "", 0 } // this MUST be last }; struct transport_type { vnum_t transport; dir_t to; vnum_t room; dir_t from; }; static struct transport_type seatac[NUM_SEATAC_STATIONS] = { { 501, SOUTH, 3018, NORTH }, { 501, EAST, 29036, WEST }, { 501, EAST, 9823, WEST }, { 501, EAST, 29036, WEST }, }; /* static struct transport_type seattle[NUM_SEATTLE_STATION] = { { 502, SOUTH, 9824, NORTH }, } */ // ______________________________ // // func prototypes // ______________________________ SPECIAL(taxi); static int process_elevator(struct room_data *room, struct char_data *ch, int cmd, char *argument); // ____________________________________________________________________________ // // Taxi // ____________________________________________________________________________ // ______________________________ // // utility funcs // ______________________________ static void open_taxi_door(vnum_t room, int dir, int taxi) { world[room].dir_option[dir] = new room_direction_data; memset((char *) world[room].dir_option[dir], 0, sizeof (struct room_direction_data)); world[room].dir_option[dir]->to_room = taxi; world[room].dir_option[dir]->barrier = 8; world[room].dir_option[dir]->condition = 8; world[room].dir_option[dir]->material = 8; dir = rev_dir[dir]; world[taxi].dir_option[dir] = new room_direction_data; memset((char *) world[taxi].dir_option[dir], 0, sizeof (struct room_direction_data)); world[taxi].dir_option[dir]->to_room = room; world[taxi].dir_option[dir]->barrier = 8; world[taxi].dir_option[dir]->condition = 8; world[taxi].dir_option[dir]->material = 8; } static void close_taxi_door(int room, int dir, int taxi) { if (world[room].dir_option[dir]->keyword) delete [] world[room].dir_option[dir]->keyword; if (world[room].dir_option[dir]->general_description) delete [] world[room].dir_option[dir]->general_description; delete world[room].dir_option[dir]; world[room].dir_option[dir] = NULL; dir = rev_dir[dir]; if (world[taxi].dir_option[dir]->keyword) delete [] world[taxi].dir_option[dir]->keyword; if (world[taxi].dir_option[dir]->general_description) delete [] world[taxi].dir_option[dir]->general_description; delete world[taxi].dir_option[dir]; world[taxi].dir_option[dir] = NULL; } void taxi_leaves(void) { int i, j, found = 0, to; struct char_data *temp; for (j = real_room(FIRST_CAB); j <= real_room(LAST_PORTCAB); j++) { found = 0; for (temp = world[j].people; temp; temp = temp->next_in_room) if (!(GET_MOB_SPEC(temp) && GET_MOB_SPEC(temp) == taxi)) { found = 1; break; } if (found) continue; for (i = NORTH; i < UP; i++) if (world[j].dir_option[i]) { to = world[j].dir_option[i]->to_room; close_taxi_door(to, rev_dir[i], j); if (world[to].people) { if (j >= real_room(FIRST_PORTCAB)) sprintf(buf, "The taxi doors slide shut and it pulls off from the kerb."); else sprintf(buf, "The taxi door slams shut as its wheels churn up a cloud of smoke."); act(buf, FALSE, world[to].people, 0, 0, TO_ROOM); act(buf, FALSE, world[to].people, 0, 0, TO_CHAR); } if (world[j].people) act("The door automatically closes.", FALSE, world[j].people, 0, 0, TO_CHAR); } if (j == LAST_CAB) j = FIRST_PORTCAB - 1; } } // ______________________________ // // hail command // ______________________________ ACMD(do_hail) { struct char_data *temp; int cab, dir, first, last, i = -1; bool found = FALSE, empty = FALSE, portland = FALSE; SPECIAL(taxi); for (dir = NORTH; dir < UP; dir++) if (!world[ch->in_room].dir_option[dir]) empty = TRUE; if (IS_ASTRAL(ch)) { send_to_char("Magically active cab drivers...now I've heard everything...\n\r",ch); return; } if (world[ch->in_room].sector_type != SPIRIT_CITY || !empty || ROOM_FLAGGED(ch->in_room, ROOM_INDOORS)) { send_to_char("There doesn't seem to be any cabs in the area.\r\n", ch); return; } if ( (i = IN_ROOM(ch)) > -1 ) { switch (zone_table[world[i].zone].number) { case 13: case 15: case 20: case 22: case 23: case 24: case 25: case 26: case 29: case 30: case 32: case 38: case 40: case 42: case 45: case 49: case 74: case 91: case 143: case 194: case 290: case 293: case 301: case 305: case 325: case 707: break; case 27: case 146: case 188: case 208: case 241: portland = TRUE; break; default: /* Cab doesn't service the area */ send_to_char("There don't seem to be any cabs in the area.\n\r",ch); return; } } if (AFF_FLAGS(ch).AreAnySet(AFF_SPELLINVIS, AFF_INVISIBLE, AFF_SPELLIMPINVIS, AFF_IMP_INVIS, ENDBIT)) { send_to_char("A cab almost stops, but guns it at the last second, splashing you...\n\r",ch); return; } first = real_room(portland ? FIRST_PORTCAB : FIRST_CAB); last = real_room(portland ? LAST_PORTCAB : LAST_CAB); for (cab = first; cab <= last; cab++) { for (temp = world[cab].people; temp; temp = temp->next_in_room) if (!(GET_MOB_SPEC(temp) && GET_MOB_SPEC(temp) == taxi)) break; if (!temp) { found = TRUE; for (dir = NORTH; dir < UP; dir++) if (world[cab].dir_option[dir]) found = FALSE; if (found) break; } } if (!found) { send_to_char("Hail as you might, no cab answers.\r\n", ch); return; } for (dir = number(NORTH, UP - 1);; dir = number(NORTH, UP - 1)) if (!world[ch->in_room].dir_option[dir]) { open_taxi_door(ch->in_room, dir, cab); if (portland) sprintf(buf, "A nice looking red and white cab pulls up smoothly to the kerb, " "and its door opens to the %s.", fulldirs[dir]); else sprintf(buf, "A beat-up yellow cab screeches to a halt, " "and its door opens to the %s.", fulldirs[dir]); act(buf, FALSE, ch, 0, 0, TO_ROOM); act(buf, FALSE, ch, 0, 0, TO_CHAR); return; } } // ______________________________ // // driver spec // ______________________________ SPECIAL(taxi) { extern bool memory(struct char_data *ch, struct char_data *vict); ACMD(do_say); ACMD(do_action); struct char_data *temp = NULL, *driver = (struct char_data *) me; int comm = CMD_NONE, i = 0, j; char say[MAX_STRING_LENGTH]; vnum_t dest = 0; bool portland = FALSE; if (GET_MOB_VNUM(driver) == 650) portland = TRUE; if (!cmd) { for (temp = world[driver->in_room].people; temp; temp = temp->next_in_room) if (temp != driver && memory(driver, temp)) break; if (!temp) { GET_SPARE1(driver) = 0; GET_SPARE2(driver) = 0; GET_ACTIVE(driver) = ACT_AWAIT_CMD; } else switch (GET_ACTIVE(driver)) { case ACT_REPLY_DEST: if (portland) sprintf(say, "%s? Sure, that will be %d nuyen.", port_destinations[GET_SPARE2(driver)].str, (int)GET_SPARE1(driver)); else sprintf(say, "%s? Yeah, sure...it'll cost ya %d nuyen, whaddya say?", destinations[GET_SPARE2(driver)].str, (int)GET_SPARE1(driver)); do_say(driver, say, 0, 0); if (GET_EXTRA(driver) == 1) { do_say(driver, "But seeing as you're new around here, I'll waive my usual fee, okay?", 0, 0); GET_SPARE1(driver) = 0; } GET_EXTRA(driver) = 0; GET_ACTIVE(driver) = ACT_AWAIT_YESNO; break; case ACT_REPLY_NOTOK: if (portland) do_say(driver, "You don't seem to have enough nuyen!", 0, 0); else do_say(driver, "Ya ain't got the nuyen!", 0, 0); forget(driver, temp); GET_SPARE1(driver) = 0; GET_SPARE2(driver) = 0; GET_ACTIVE(driver) = ACT_AWAIT_CMD; break; case ACT_REPLY_TOOBAD: if (portland) do_say(driver, "Somewhere else then, chummer?", 0, 0); else do_say(driver, "Whatever, chum.", 0, 0); forget(driver, temp); GET_SPARE1(driver) = 0; GET_SPARE2(driver) = 0; GET_ACTIVE(driver) = ACT_AWAIT_CMD; break; case ACT_DRIVING: if (GET_SPARE1(driver) > 0) GET_SPARE1(driver)--; else { int x[] = { 0, 0, 0, 0, 0, 0, 0, 0 }, y = 0; for (j = number(NORTH, NORTHWEST);; j = number(NORTH, NORTHWEST)) { if (!x[j]) { x[j] = 1; y++; } if (y == NORTHWEST) return FALSE; dest = real_room(GET_SPARE2(driver)); if (!world[dest].dir_option[j]) { open_taxi_door(dest, j, driver->in_room); do_say(driver, "Ok, here we are.", 0, 0); forget(driver, temp); GET_SPARE2(driver) = 0; GET_ACTIVE(driver) = ACT_AWAIT_CMD; if (world[dest].people) { act("A taxi pulls to a stop, its door sliding open.", FALSE, world[dest].people, 0, 0, TO_ROOM); act("A taxi pulls to a stop, its door sliding open.", FALSE, world[dest].people, 0, 0, TO_CHAR); } sprintf(buf, "The door, rather noisily, slides open to the %s.", fulldirs[rev_dir[j]]); act(buf, FALSE, driver, 0, 0, TO_ROOM); act(buf, FALSE, driver, 0, 0, TO_CHAR); break; } } } break; } return FALSE; } if (!IS_NPC(ch) && memory(driver, ch) && (CMD_IS("north") || CMD_IS("east") || CMD_IS("west") || CMD_IS("south") || CMD_IS("ne") || CMD_IS("se") || CMD_IS("sw") || CMD_IS("nw") || CMD_IS("northeast") || CMD_IS("southeast") || CMD_IS("southwest") || CMD_IS("northwest")) && GET_ACTIVE(driver) != ACT_DRIVING) { forget(driver, ch); return FALSE; } if (!CAN_SEE(driver, ch) || IS_NPC(ch) || (GET_ACTIVE(driver) != ACT_AWAIT_CMD && GET_ACTIVE(driver) != ACT_AWAIT_YESNO)) return FALSE; skip_spaces(&argument); if (CMD_IS("say") || CMD_IS("'")) { bool found = FALSE; if (GET_ACTIVE(driver) == ACT_AWAIT_CMD) for (dest = 0; (portland ? *port_destinations[dest].keyword : *destinations[dest].keyword) != '\n'; dest++) if ( str_str((const char *)argument, (portland ? port_destinations[dest].keyword : destinations[dest].keyword))) { comm = CMD_DEST; found = TRUE; break; } if (!found) { if (str_str(argument, "yes") || str_str(argument, "sure") || str_str(argument, "yea") || str_str(argument, "okay")) comm = CMD_YES; else if (strstr(argument, "no")) comm = CMD_NO; } do_say(ch, argument, 0, 0); } else if (CMD_IS("nod")) { comm = CMD_YES; do_action(ch, argument, cmd, 0); } else if (CMD_IS("shake") && !*argument) { comm = CMD_NO; do_action(ch, argument, cmd, 0); } else return FALSE; if (comm == CMD_DEST && !memory(driver, ch) && (i = real_room(GET_LASTROOM(ch))) > -1 && GET_ACTIVE(driver) == ACT_AWAIT_CMD) { for (i = NORTH; i < UP; i++) if (world[ch->in_room].dir_option[i]) { i = world[ch->in_room].dir_option[i]->to_room; break; } int dist = 0; while (i != -1) { int x = find_first_step(i, real_room((portland ? port_destinations[dest].vnum : destinations[dest].vnum))); if (x == -2) break; else if (x < 0) { i = -1; break; } i = world[i].dir_option[x]->to_room; dist++; } if (i == -1) GET_SPARE1(driver) = 250; else GET_SPARE1(driver) = MIN(250, 5 + dist); GET_SPARE2(driver) = dest; GET_ACTIVE(driver) = ACT_REPLY_DEST; if (PLR_FLAGGED(ch, PLR_NEWBIE)) GET_EXTRA(driver) = 1; else GET_EXTRA(driver) = 0; remember(driver, ch); } else if (comm == CMD_YES && memory(driver, ch) && GET_ACTIVE(driver) == ACT_AWAIT_YESNO) { if (GET_NUYEN(ch) < GET_SPARE1(driver) && !IS_SENATOR(ch)) { GET_ACTIVE(driver) = ACT_REPLY_NOTOK; return TRUE; } if (!IS_SENATOR(ch)) GET_NUYEN(ch) -= GET_SPARE1(driver); GET_SPARE1(driver) = (int)(GET_SPARE1(driver) / 50); GET_SPARE2(driver) = portland ? port_destinations[GET_SPARE2(driver)].vnum : destinations[GET_SPARE2(driver)].vnum; GET_ACTIVE(driver) = ACT_DRIVING; for (i = NORTH; i < UP; i++) if (world[ch->in_room].dir_option[i]) { dest = world[ch->in_room].dir_option[i]->to_room; close_taxi_door(dest, rev_dir[i], ch->in_room); if (world[dest].people) { if (portland) sprintf(buf, "The taxi doors slide shut and it pulls off from the kerb."); else sprintf(buf, "The taxi door slams shut as its wheels churn up a cloud of smoke."); act(buf, FALSE, world[dest].people, 0, 0, TO_ROOM); act(buf, FALSE, world[dest].people, 0, 0, TO_CHAR); } act("The door shuts as the taxi begins to accelerate.", FALSE, ch, 0, 0, TO_ROOM); act("The door shuts as the taxi begins to accelerate.", FALSE, ch, 0, 0, TO_CHAR); } } else if (comm == CMD_NO && memory(driver, ch) && GET_ACTIVE(driver) == ACT_AWAIT_YESNO) GET_ACTIVE(driver) = ACT_REPLY_TOOBAD; return TRUE; } // ______________________________ // // Elevators // ______________________________ // ______________________________ // // utility funcs // ______________________________ static void init_elevators(void) { FILE *fl; char line[256]; int i, j, t[3]; vnum_t room[1], rnum; if (!(fl = fopen(ELEVATOR_FILE, "r"))) { log("Error opening elevator file."); shutdown(); } if (!get_line(fl, line) || sscanf(line, "%d", &num_elevators) != 1) { log("Error at beginning of elevator file."); shutdown(); } elevator = new struct elevator_data[num_elevators]; for (i = 0; i < num_elevators && !feof(fl); i++) { get_line(fl, line); if (sscanf(line, "%ld %d %d %d", room, t, t + 1, t + 2) != 4) { fprintf(stderr, "Format error in elevator #%d, expecting # # # #\n", i); shutdown(); } elevator[i].room = room[0]; if ((rnum = real_room(elevator[i].room)) > -1) { world[rnum].func = elevator_spec; world[rnum].rating = 0; } else log("Nonexistent elevator."); elevator[i].columns = t[0]; elevator[i].time_left = 0; elevator[i].dir = -1; elevator[i].destination = 0; elevator[i].num_floors = t[1]; elevator[i].start_floor = t[2]; if (elevator[i].num_floors > 0) { elevator[i].floor = new struct floor_data[elevator[i].num_floors]; for (j = 0; j < elevator[i].num_floors; j++) { get_line(fl, line); if (sscanf(line, "%ld %d", room, t + 1) != 2) { fprintf(stderr, "Format error in elevator #%d, floor #%d\n", i, j); shutdown(); } elevator[i].floor[j].vnum = room[0]; if ((rnum = real_room(elevator[i].floor[j].vnum)) > -1) world[rnum].func = call_elevator; else { elevator[i].floor[j].vnum = -1; log("Nonexistent elevator destination -- blocking."); } elevator[i].floor[j].doors = t[1]; } } else elevator[i].floor = NULL; } fclose(fl); } static void open_elevator_doors(struct room_data *room, int num, int floor) { int dir; long rnum; rnum = real_room(elevator[num].floor[floor].vnum); dir = elevator[num].floor[floor].doors; room->dir_option[dir] = new room_direction_data; memset((char *) room->dir_option[dir], 0, sizeof (struct room_direction_data)); room->dir_option[dir]->to_room = rnum; room->dir_option[dir]->barrier = 8; room->dir_option[dir]->condition = 8; room->dir_option[dir]->material = 8; dir = rev_dir[dir]; world[rnum].dir_option[dir] = new room_direction_data; memset((char *) world[rnum].dir_option[dir], 0, sizeof (struct room_direction_data)); world[rnum].dir_option[dir]->to_room = real_room(room->number); world[rnum].dir_option[dir]->barrier = 8; world[rnum].dir_option[dir]->condition = 8; world[rnum].dir_option[dir]->material = 8; elevator[num].dir = UP - 1; if (world[rnum].people) { sprintf(buf, "The elevator doors open to the %s.", fulldirs[dir]); act(buf, FALSE, world[rnum].people, 0, 0, TO_ROOM); act(buf, FALSE, world[rnum].people, 0, 0, TO_CHAR); } } static void close_elevator_doors(struct room_data *room, int num, int floor) { long rnum; int dir; dir = elevator[num].floor[floor].doors; rnum = room->dir_option[dir]->to_room; if (room->dir_option[dir]->keyword) delete [] room->dir_option[dir]->keyword; if (room->dir_option[dir]->general_description) delete [] room->dir_option[dir]->general_description; delete room->dir_option[dir]; room->dir_option[dir] = NULL; dir = rev_dir[dir]; if (world[rnum].dir_option[dir]->keyword) delete [] world[rnum].dir_option[dir]->keyword; if (world[rnum].dir_option[dir]->general_description) delete [] world[rnum].dir_option[dir]->general_description; delete world[rnum].dir_option[dir]; world[rnum].dir_option[dir] = NULL; if (world[rnum].people) { act("The elevator doors close.", FALSE, world[rnum].people, 0, 0, TO_ROOM); act("The elevator doors close.", FALSE, world[rnum].people, 0, 0, TO_CHAR); } } // ______________________________ // // elevator lobby / call-button spec // ______________________________ SPECIAL(call_elevator) { int i = 0, j, index = -1; long rnum; if (!cmd) return FALSE; for (i = 0; i < num_elevators && index < 0; i++) for (j = 0; j < elevator[i].num_floors && index < 0; j++) if (elevator[i].floor[j].vnum == world[ch->in_room].number) index = i; if (CMD_IS("push")) { skip_spaces(&argument); if (!*argument || !(!strcasecmp("elevator", argument) || !strcasecmp("button", argument))) send_to_char("Press what?\r\n", ch); else { if (IS_ASTRAL(ch)) { send_to_char("You can't do that in your current state.\r\n", ch); return TRUE; } if (index < 0 || elevator[index].destination) { send_to_char("You press the call button, " "but nothing seems to happen.\r\n", ch); return TRUE; } rnum = real_room(elevator[index].room); for (i = 0; i < UP; i++) if (world[rnum].dir_option[i] && world[rnum].dir_option[i]->to_room == ch->in_room) { send_to_char("The door is already open!\r\n", ch); elevator[index].destination = 0; return TRUE; } send_to_char("You press the call button, " "and the small light turns on.\r\n", ch); elevator[index].destination = world[ch->in_room].number; } return TRUE; } if (CMD_IS("look")) { one_argument(argument, arg); if (!*arg || index < 0 || !(!strcasecmp("panel", arg) || !strcasecmp("elevator", arg))) return FALSE; rnum = real_room(elevator[index].room); i = world[rnum].rating + 1 - elevator[index].num_floors - elevator[index].start_floor; if (i > 0) send_to_char(ch, "The floor indicator shows that the elevator is " "currently at B%d.\r\n", i); else if (i == 0) send_to_char(ch, "The floor indicator shows that the elevator is " "currently at the ground floor.\r\n"); else send_to_char(ch, "The floor indicator shows that the elevator is " "current at floor %d.\r\n", 0 - i); return TRUE; } return FALSE; } // ______________________________ // // elevator spec // ______________________________ SPECIAL(elevator_spec) { struct room_data *room = (struct room_data *) me; if (cmd && process_elevator(room, ch, cmd, argument)) return TRUE; return FALSE; } // ______________________________ // // processing funcs // ______________________________ static int process_elevator(struct room_data *room, struct char_data *ch, int cmd, char *argument) { int num, temp, number, floor = 0; for (num = 0; num < num_elevators; num++) if (elevator[num].room == room->number) break; if (num >= num_elevators) return 0; if (!cmd) { if (elevator[num].destination && elevator[num].dir == -1) { for (temp = 0; temp <= elevator[num].num_floors; temp++) if (elevator[num].floor[temp].vnum == elevator[num].destination) floor = temp; if (floor >= room->rating) { elevator[num].dir = DOWN; elevator[num].time_left = floor - room->rating; } else if (floor < room->rating) { elevator[num].dir = UP; elevator[num].time_left = room->rating - floor; } elevator[num].destination = 0; } if (elevator[num].time_left > 0) { elevator[num].time_left--; if (elevator[num].dir == DOWN) room->rating++; else room->rating--; } else if (elevator[num].dir == UP || elevator[num].dir == DOWN) { temp = room->rating + 1 - elevator[num].num_floors - elevator[num].start_floor; if (temp > 0) sprintf(buf, "The elevator stops at B%d, " "and the doors open to the %s.", temp, fulldirs[elevator[num].floor[room->rating].doors]); else if (temp == 0) sprintf(buf, "The elevator stops at the ground floor, " "and the doors open to the %s.", fulldirs[elevator[num].floor[room->rating].doors]); else sprintf(buf, "The elevator stops at floor %d, " "and the doors open to the %s.", 0 - temp, fulldirs[elevator[num].floor[room->rating].doors]); if (room->people) { act(buf, FALSE, room->people, 0, 0, TO_ROOM); act(buf, FALSE, room->people, 0, 0, TO_CHAR); } open_elevator_doors(room, num, room->rating); } else if (elevator[num].dir > 0) elevator[num].dir--; else if (!elevator[num].dir) { if (room->people) { act("The elevator doors close.", FALSE, room->people, 0, 0, TO_ROOM); act("The elevator doors close.", FALSE, room->people, 0, 0, TO_CHAR); } close_elevator_doors(room, num, room->rating); elevator[num].dir = -1; } } else if (CMD_IS("push")) { if (IS_ASTRAL(ch)) { send_to_char("You can't do that in your current state.\r\n", ch); return TRUE; } if (!*argument) { send_to_char("Press which button?\r\n", ch); return TRUE; } if (elevator[num].dir >= UP) { send_to_char("The elevator has already been activated.\r\n", ch); return TRUE; } skip_spaces(&argument); if (LOWER(*argument) == 'b' && (number = atoi(argument + 1)) > 0) number = elevator[num].num_floors + elevator[num].start_floor + number - 1; else if (LOWER(*argument) == 'g' && elevator[num].start_floor <= 0) number = elevator[num].num_floors + elevator[num].start_floor - 1; else if ((number = atoi(argument)) > 0) number = elevator[num].num_floors + elevator[num].start_floor - 1 - number; else number = -1; if (number < 0 || number >= elevator[num].num_floors || elevator[num].floor[number].vnum < 0) send_to_char(ch, "'%s' isn't a button.\r\n", argument); else if (number == room->rating) { if (room->dir_option[elevator[num].floor[number].doors]) { temp = room->rating + 1 - elevator[num].num_floors - elevator[num].start_floor; if (temp > 0) send_to_char(ch, "You are already at B%d!\r\n", temp); else if (temp == 0) send_to_char(ch, "You are already at the ground floor!\r\n"); else send_to_char(ch, "You are already at floor %d!\r\n", 0 - temp); } else { sprintf(buf, "The elevator doors open to the %s.", fulldirs[elevator[num].floor[room->rating].doors]); act(buf, FALSE, ch, 0, 0, TO_ROOM); act(buf, FALSE, ch, 0, 0, TO_CHAR); open_elevator_doors(room, num, room->rating); } } else { if (number > room->rating) { elevator[num].dir = DOWN; elevator[num].time_left = MAX(1, number - room->rating); } else { elevator[num].dir = UP; elevator[num].time_left = MAX(1, room->rating - number); } if (!room->dir_option[elevator[num].floor[room->rating].doors]) sprintf(buf, "The elevator begins to %s.", (elevator[num].dir == UP ? "ascend" : "descend")); else { sprintf(buf, "The elevator doors close and it begins to %s.", (elevator[num].dir == UP ? "ascend" : "descend")); close_elevator_doors(room, num, room->rating); } act(buf, FALSE, ch, 0, 0, TO_ROOM); act(buf, FALSE, ch, 0, 0, TO_CHAR); } return TRUE; } else if (CMD_IS("look")) { one_argument(argument, arg); if (!*arg || !(!strcasecmp("panel", arg) || !strcasecmp("elevator", arg) || !strcasecmp("buttons", arg))) return FALSE; strcpy(buf, "The elevator panel displays the following buttons:\r\n"); number = 0; for (floor = 0; floor < elevator[num].num_floors; floor++) if (elevator[num].floor[floor].vnum > -1) { temp = elevator[num].start_floor + floor; if (temp < 0) sprintf(buf + strlen(buf), " B%-2d", 0 - temp); else if (temp == 0) sprintf(buf + strlen(buf), " G "); else sprintf(buf + strlen(buf), " %-2d", temp); number++; if (!(number % elevator[num].columns)) strcat(buf, "\r\n"); } if ((number % elevator[num].columns)) strcat(buf, "\r\n"); temp = room->rating + 1 - elevator[num].num_floors - elevator[num].start_floor; if (temp > 0) sprintf(buf + strlen(buf), "The floor indicator shows that the " "elevator is currently at B%d.\r\n", temp); else if (temp == 0) sprintf(buf + strlen(buf), "The floor indicator shows that the " "elevator is currently at the ground floor.\r\n"); else sprintf(buf + strlen(buf), "The floor indicator shows that the " "elevator is currently at floor %d.\r\n", 0 - temp); send_to_char(buf, ch); return TRUE; } return FALSE; } void ElevatorProcess(void) { int i, rnum; for (i = 0; i < num_elevators; i++) if (elevator && (rnum = real_room(elevator[i].room)) > -1) process_elevator(&world[rnum], NULL, 0, ""); } // ______________________________ // // Escalators // ______________________________ // ______________________________ // // spec // ______________________________ SPECIAL(escalator) { return FALSE; } // ______________________________ // // processing funcs // ______________________________ void EscalatorProcess(void) { int i, dir; struct char_data *temp, *next; for (i = 0; i <= top_of_world; i++) if (world[i].func && world[i].func == escalator) for (temp = world[i].people; temp; temp = next) { next = temp->next_in_room; if (GET_LASTROOM(temp) > 0 || GET_LASTROOM(temp) < -3) GET_LASTROOM(temp) = -3; else if (GET_LASTROOM(temp) < 0) GET_LASTROOM(temp)++; else for (dir = NORTH; dir <= DOWN; dir++) if (world[i].dir_option[dir] && world[i].dir_option[dir]->to_room > 0) { act("As you reach the end, you step off the escalator.", FALSE, temp, 0, 0, TO_CHAR); act("$n steps off of the escalator.", TRUE, temp, 0, 0, TO_ROOM); char_from_room(temp); GET_LASTROOM(temp) = world[i].number; char_to_room(temp, world[i].dir_option[dir]->to_room); if (temp->desc) look_at_room(temp, 0); break; } } } // ______________________________ // // Monorail // ______________________________ // ______________________________ // // utility funcs // ______________________________ static void open_doors(int car, int to, int room, int from) { if (!world[car].dir_option[to]) { world[car].dir_option[to] = new room_direction_data; memset((char *) world[car].dir_option[to], 0, sizeof(struct room_direction_data)); world[car].dir_option[to]->to_room = room; world[car].dir_option[to]->to_room_vnum = world[room].number; world[car].dir_option[to]->barrier = 8; world[car].dir_option[to]->condition = 8; world[car].dir_option[to]->material = 8; } if (!world[room].dir_option[from]) { world[room].dir_option[from] = new room_direction_data; memset((char *) world[room].dir_option[from], 0, sizeof(struct room_direction_data)); world[room].dir_option[from]->to_room = car; world[room].dir_option[from]->to_room_vnum = world[car].number; world[room].dir_option[from]->barrier = 8; world[room].dir_option[from]->condition = 8; world[room].dir_option[from]->material = 8; } sprintf(buf, "The monorail stops and the doors open to %s.\r\n", thedirs[to]); send_to_room(buf, car); sprintf(buf, "The monorail stops and the doors open to %s.\r\n", thedirs[from]); send_to_room(buf, room); } static void close_doors(int car, int to, int room, int from) { if (world[car].dir_option[to]->keyword) delete [] world[car].dir_option[to]->keyword; if (world[car].dir_option[to]->general_description) delete [] world[car].dir_option[to]->general_description; delete world[car].dir_option[to]; world[car].dir_option[to] = NULL; if (world[room].dir_option[from]->keyword) delete [] world[room].dir_option[from]->keyword; if (world[room].dir_option[from]->general_description) delete [] world[room].dir_option[from]->general_description; delete world[room].dir_option[from]; world[room].dir_option[from] = NULL; send_to_room("The monorail doors close and it begins accelerating.\r\n", car); send_to_room("The monorail doors close and it begins accelerating.\r\n", room); } // ______________________________ // // processing funcs // ______________________________ void process_seatac_monorail(void) { int carnum, roomnum, ind; static int where = 0; if (where >= 16) where = 0; ind = (int)(where / 4); carnum = real_room(seatac[ind].transport); roomnum = real_room(seatac[ind].room); switch (where) { case 0: case 4: send_to_room("Lights flash along the runway as the monorail approaches.\r\n", roomnum); break; case 1: case 5: case 9: case 13: open_doors(carnum, seatac[ind].to, roomnum, seatac[ind].from); break; case 2: case 6: case 10: case 14: close_doors(carnum, seatac[ind].to, roomnum, seatac[ind].from); break; case 3: send_to_room("A voice announces, \"Next stop: Auburn\"\r\n", carnum); break; case 7: send_to_room("A voice announces, \"Next stop: Seattle. Change here for Downtown Shuttle\"\r\n", carnum); break; case 11: send_to_room("A voice announces, \"Next stop: Auburn\"\r\n", carnum); break; case 15: send_to_room("A voice announces, \"Next stop: West Tacoma.\"\r\n", carnum); break; } where++; } // ______________________________ // // Ferries and busses // ______________________________ /* Seattle/Tacoma Ferry */ struct transport_type seattle_ferry[2] = { { 12620, SOUTH, 12613, NORTH }, { 12620, SOUTHEAST, 2007, NORTHWEST }, }; void extend_walkway_st(int ferry, int to, int room, int from) { if (!world[ferry].dir_option[to]) { world[ferry].dir_option[to] = new room_direction_data; memset((char *) world[ferry].dir_option[to], 0, sizeof(struct room_direction_data)); world[ferry].dir_option[to]->to_room = room; world[ferry].dir_option[to]->to_room_vnum = world[room].number; world[ferry].dir_option[to]->barrier = 8; world[ferry].dir_option[to]->condition = 8; world[ferry].dir_option[to]->material = 8; } if (!world[room].dir_option[from]) { world[room].dir_option[from] = new room_direction_data; memset((char *) world[room].dir_option[from], 0, sizeof(struct room_direction_data)); world[room].dir_option[from]->to_room = ferry; world[room].dir_option[from]->to_room_vnum = world[ferry].number; world[room].dir_option[from]->barrier = 8; world[room].dir_option[from]->condition = 8; world[room].dir_option[from]->material = 8; } send_to_room("The ferry docks at the pier, and extends its walkway.\r\n", room); send_to_room("The ferry docks at the pier, and extends its walkway.\r\n", ferry); } void contract_walkway_st(int ferry, int to, int room, int from) { if (world[ferry].dir_option[to]->keyword) delete [] world[ferry].dir_option[to]->keyword; if (world[ferry].dir_option[to]->general_description) delete [] world[ferry].dir_option[to]->general_description; delete world[ferry].dir_option[to]; world[ferry].dir_option[to] = NULL; if (world[room].dir_option[from]->keyword) delete [] world[room].dir_option[from]->keyword; if (world[room].dir_option[from]->general_description) delete [] world[room].dir_option[from]->general_description; delete world[room].dir_option[from]; world[room].dir_option[from] = NULL; send_to_room("The walkway recedes, and the ferry departs.\r\n", room); send_to_room("The walkway recedes, and the ferry departs.\r\n", ferry); } void process_seattle_ferry(void) { static int where = 0; int ferry, dock, ind; if (where >= 26) where = 0; ind = (where >= 13 ? 1 : 0); ferry = real_room(seattle_ferry[ind].transport); dock = real_room(seattle_ferry[ind].room); switch (where) { case 0: send_to_room("The ferry approaches, gliding across the bay towards " "the dock.\r\n", dock); break; case 1: case 14: extend_walkway_st(ferry, seattle_ferry[ind].to, dock, seattle_ferry[ind].from); break; case 4: case 17: contract_walkway_st(ferry, seattle_ferry[ind].to, dock, seattle_ferry[ind].from); break; case 5: send_to_room("A voice announces through a rusting speaker, " "\"Next stop: Tacoma.\"\r\n", ferry); break; case 13: send_to_room("The ferry approaches, gliding across the bay towards " "the dock.\r\n", dock); break; case 18: send_to_room("A voice announces through a rusting speaker, " "\"Next stop: Seattle.\"\r\n", ferry); break; } where++; } /* Hellhound Bus Spec * Bus from Seattle to Portland and back */ struct transport_type hellhound[2] = { { 670, NORTHWEST, 32763, SOUTHEAST }, { 670, SOUTHWEST, 14700, NORTHEAST }, }; void open_busdoor(int bus, int to, int room, int from) { if (!world[bus].dir_option[to]) { world[bus].dir_option[to] = new room_direction_data; memset((char *) world[bus].dir_option[to], 0, sizeof(struct room_direction_data)); world[bus].dir_option[to]->to_room = room; world[bus].dir_option[to]->to_room_vnum = world[room].number; world[bus].dir_option[to]->barrier = 8; world[bus].dir_option[to]->condition = 8; world[bus].dir_option[to]->material = 8; } if (!world[room].dir_option[from]) { world[room].dir_option[from] = new room_direction_data; memset((char *) world[room].dir_option[from], 0, sizeof(struct room_direction_data)); world[room].dir_option[from]->to_room = bus; world[room].dir_option[from]->to_room_vnum = world[bus].number; world[room].dir_option[from]->barrier = 8; world[room].dir_option[from]->condition = 8; world[room].dir_option[from]->material = 8; } send_to_room("The bus rolls up to the platform, and the door opens.\r\n", room); send_to_room("The bus rolls up to the platform, and the door opens.\r\n", bus); } void close_busdoor(int bus, int to, int room, int from) { if (world[bus].dir_option[to]->keyword) delete [] world[bus].dir_option[to]->keyword; if (world[bus].dir_option[to]->general_description) delete [] world[bus].dir_option[to]->general_description; delete world[bus].dir_option[to]; world[bus].dir_option[to] = NULL; if (world[room].dir_option[from]->keyword) delete [] world[room].dir_option[from]->keyword; if (world[room].dir_option[from]->general_description) delete [] world[room].dir_option[from]->general_description; delete world[room].dir_option[from]; world[room].dir_option[from] = NULL; send_to_room("The bus door shuts, the driver yells \"^Wall aboard!^n\", and begins driving.\r\n", room); send_to_room("The bus door shuts, the driver yells \"^Wall aboard!^n\", and begins driving.\r\n", bus); } void process_hellhound_bus(void) { static int where = 0; int bus, stop, ind; if (where >= 52) where = 0; ind = (where >= 26 ? 1 : 0); bus = real_room(hellhound[ind].transport); stop = real_room(hellhound[ind].room); switch (where) { case 0: send_to_room("The bus pulls into the garage, and slowly moves to the platform.\r\n", stop); break; case 1: case 28: open_busdoor(bus, hellhound[ind].to, stop, hellhound[ind].from); break; case 8: case 34: close_busdoor(bus, hellhound[ind].to, stop, hellhound[ind].from); break; case 23: send_to_room("The driver shouts from the front, \"Next stop: Portland\"\r\n", bus); break; case 26: send_to_room("The bus pulls into the garage, and slowly moves to the platform.\r\n", stop); break; case 49: send_to_room("The driver shouts from the front, \"Next stop: Seattle\".\r\n", bus); break; } where++; } //FILEPOINTER //Downtown Portlan, 60th Street Hospital, Gresham, 60th Street back from Gresham //Lightrail struct transport_type lightrail[4] = { { 14799, SOUTH, 14701, NORTH } , //Downtown Portlan { 14799, EAST, 14702, WEST }, //60thStreet/Hospital { 14799, WEST, 14711, EAST }, //Gresham { 14799, EAST, 14702, WEST }, //60thStreet/BackfromGresham }; void open_lightraildoor(int lightrail, int to, int room, int from) { if (!world[lightrail].dir_option[to]) { world[lightrail].dir_option[to] = new room_direction_data; memset((char *) world[lightrail].dir_option[to], 0, sizeof(struct room_direction_data)); world[lightrail].dir_option[to]->to_room = room; world[lightrail].dir_option[to]->to_room_vnum = world[room].number; world[lightrail].dir_option[to]->barrier = 8; world[lightrail].dir_option[to]->condition = 8; world[lightrail].dir_option[to]->material = 8; } if (!world[room].dir_option[from]) { world[room].dir_option[from] = new room_direction_data; memset((char *) world[room].dir_option[from], 0, sizeof(struct room_direction_data)); world[room].dir_option[from]->to_room = lightrail; world[room].dir_option[from]->to_room_vnum = world[lightrail].number; world[room].dir_option[from]->barrier = 8; world[room].dir_option[from]->condition = 8; world[room].dir_option[from]->material = 8; } send_to_room("The incoming lightrail grinds to a halt and its doors slide open with a hiss.\r\n", room); send_to_room("The lightrail grinds to a halt and the doors hiss open.\r\n", lightrail); } void close_lightraildoor(int lightrail, int to, int room, int from) { if (world[lightrail].dir_option[to]->keyword) delete [] world[lightrail].dir_option[to]->keyword; if (world[lightrail].dir_option[to]->general_description) delete [] world[lightrail].dir_option[to]->general_description; delete world[lightrail].dir_option[to]; world[lightrail].dir_option[to] = NULL; if (world[room].dir_option[from]->keyword) delete [] world[room].dir_option[from]->keyword; if (world[room].dir_option[from]->general_description) delete [] world[room].dir_option[from]->general_description; delete world[room].dir_option[from]; world[room].dir_option[from] = NULL; send_to_room("The lightrail's doors slide shut and a tone eminates around the platform, signaling its departure.", room); send_to_room("The lightrail's doors slide shut and a tone signals as it begins moving.\r\n", lightrail); } void process_lightrail_train(void) { static int where = 0; int train, stop; static int ind = 0; if (where >= 40) where = 0; // if (where <= 0) // ind = 0; // if (where >= 10) // ind = 1; // if (where >= 20) // ind = 2; // if (where >= 30) // ind = 3; train = real_room(lightrail[ind].transport); stop = real_room(lightrail[ind].room); switch (where) { //Downtown Stop Stuff case 39: send_to_room("An LCD Panel Flashes: \"Next Stop: Downtown Portland\".\r\n", train); break; case 0: send_to_room("The lightrail emits a loud grind as it brakes into the station.\r\n", stop); break; case 1: open_lightraildoor(train, lightrail[ind].to, stop, lightrail[ind].from); break; case 5: close_lightraildoor(train, lightrail[ind].to, stop, lightrail[ind].from); ind = 1; break; //60th Stop Stuff (1) case 9: send_to_room("An LCD Panel Flashes: \"Next Stop: 60th Street\".\r\n", train); break; case 10: send_to_room("The lightrail emits a loud grind as it brakes into the station.\r\n", stop); break; case 11: open_lightraildoor(train, lightrail[ind].to, stop, lightrail[ind].from); break; case 15: close_lightraildoor(train, lightrail[ind].to, stop, lightrail[ind].from); ind = 2; break; //Gresham Stop Stuff case 19: send_to_room("An LCD Panel Flashes: \"Next Stop: Gresham\".\r\n", train); break; case 20: send_to_room("The lightrail emits a loud grind as it brakes into the station.\r\n", stop); break; case 21: open_lightraildoor(train, lightrail[ind].to, stop, lightrail[ind].from); break; case 25: close_lightraildoor(train, lightrail[ind].to, stop, lightrail[ind].from); ind = 3; break; //To60th case 29: send_to_room("An LCD Panel Flashes: \"Next Stop: 60th Street\".\r\n", train); break; case 30: send_to_room("The lightrail emits a loud grind as it brakes into the station.\r\n", stop); break; case 31: open_lightraildoor(train, lightrail[ind].to, stop, lightrail[ind].from); break; case 35: close_lightraildoor(train, lightrail[ind].to, stop, lightrail[ind].from); ind = 0; break; } where++; } struct transport_type tacsea[2] = { { 2099, SOUTH, 2007, NORTH }, { 2099, NORTH, 14500, SOUTH } }; void extend_walkway(int ferry, int to, int room, int from) { if (!world[ferry].dir_option[to]) { world[ferry].dir_option[to] = new room_direction_data; memset((char *) world[ferry].dir_option[to], 0, sizeof(struct room_direction_data)); world[ferry].dir_option[to]->to_room = room; world[ferry].dir_option[to]->to_room_vnum = world[room].number; world[ferry].dir_option[to]->barrier = 8; world[ferry].dir_option[to]->condition = 8; world[ferry].dir_option[to]->material = 8; } if (!world[room].dir_option[from]) { world[room].dir_option[from] = new room_direction_data; memset((char *) world[room].dir_option[from], 0, sizeof(struct room_direction_data)); world[room].dir_option[from]->to_room = ferry; world[room].dir_option[from]->to_room_vnum = world[ferry].number; world[room].dir_option[from]->barrier = 8; world[room].dir_option[from]->condition = 8; world[room].dir_option[from]->material = 8; } send_to_room("The ferry docks, and the walkway extends.\r\n", room); send_to_room("The ferry docks, and the walkway extends.\r\n", ferry); } void contract_walkway(int ferry, int to, int room, int from) { if (world[ferry].dir_option[to]->keyword) delete [] world[ferry].dir_option[to]->keyword; if (world[ferry].dir_option[to]->general_description) delete [] world[ferry].dir_option[to]->general_description; delete world[ferry].dir_option[to]; world[ferry].dir_option[to] = NULL; if (world[room].dir_option[from]->keyword) delete [] world[room].dir_option[from]->keyword; if (world[room].dir_option[from]->general_description) delete [] world[room].dir_option[from]->general_description; delete world[room].dir_option[from]; world[room].dir_option[from] = NULL; send_to_room("The walkway recedes, and the ferry departs.\r\n", room); send_to_room("The walkway recedes, and the ferry departs.\r\n", ferry); } void process_seatac_ferry(void) { static int where = 0; int ferry, dock, ind; if (where >= 26) where = 0; ind = (where >= 13 ? 1 : 0); ferry = real_room(tacsea[ind].transport); dock = real_room(tacsea[ind].room); switch (where) { case 0: send_to_room("The ferry approaches, gliding across the bay towards " "the dock.\r\n", dock); break; case 1: case 14: extend_walkway(ferry, tacsea[ind].to, dock, tacsea[ind].from); break; case 4: case 17: contract_walkway(ferry, tacsea[ind].to, dock, tacsea[ind].from); break; case 5: send_to_room("A voice announces through a rusting speaker, " "\"Next stop: Bradenton.\"\r\n", ferry); break; case 13: send_to_room("The ferry approaches, gliding across the bay towards " "the dock.\r\n", dock); break; case 18: send_to_room("A voice announces through a rusting speaker, " "\"Next stop: Tacoma.\"\r\n", ferry); break; } where++; } // ______________________________ // // external interface funcs // ______________________________ void TransportInit() { init_elevators(); } void MonorailProcess(void) { /* process_seatac_monorail(); process_seattle_ferry(); process_seatac_ferry(); process_hellhound_bus(); process_lightrail_train(); */ } void TransportEnd() {}