From: Chris Jacobson Subject: Vehicles Ok, here is the vehicles.c I wrote! I am releasing the /original/ code, which is all in a seperate file (except spec_assign) and relied on spec_procs, but the new version, which no longer requires ANY specprocs (thereby allowing easier vehicle creation, and no modification of source), will not be released, because I merged most of it into the main source files themselves, and since I expanded it to support 3 extra variables (water-capable, flight-capable, and space-capable), along with a discussion with my other imms (who do not do any coding, but are actively supportive of the game because we are so unique in theme and implementation) I decided that it wouldn't be in our best interest to release. THIS IS CODE, but is semi-mailer code... it is from a backup version, no more instructions can or will be provided (please don't email me asking for help installing), and also realize my version of Circle is HEAVILY modified... *** BEGIN VEHICLE.C *** #include "conf.h" #include "sysdep.h" #include "structs.h" #include "utils.h" #include "comm.h" #include "interpreter.h" #include "handler.h" #include "db.h" #include "screen.h" #include "house.h" extern struct room_data *world; extern struct char_data *character_list; extern struct descriptor_data *descriptor_list; extern struct index_data *obj_index; extern int rev_dir[]; extern char *dirs[]; extern char *room_bits[]; struct obj_data *find_vehicle(int roomNum); typedef struct { int dirNum; char* dirCmd; } dirParseStruct; #define DRIVE_DIRS 4 #define PILOT_DIRS 6 #ifndef EXITN # define EXITN(room, door) (world[room].dir_option[door]) #endif struct obj_data *find_vehicle_by_vnum(int vnum) { extern struct obj_data * object_list; struct obj_data * i; for (i = object_list; i; i = i->next) if (GET_OBJ_TYPE(i) == ITEM_VEHICLE) if (GET_OBJ_VNUM(i) == vnum) return i; return 0; } void auto_exits_by_rnum(struct char_data * ch, int is_in) { int door; *buf = '\0'; for (door = 0; door < NUM_OF_DIRS; door++) if (EXITN(is_in, door) && EXITN(is_in, door)->to_room != NOWHERE && !IS_SET(EXITN(is_in, door)->exit_info, EX_CLOSED)) sprintf(buf, "%s%c ", buf, LOWER(*dirs[door])); sprintf(buf2, "%s[ Exits: %s]%s\r\n", CCCYN(ch, C_NRM), *buf ? buf : "None! ", CCNRM(ch, C_NRM)); send_to_char(buf2, ch); } void view_room_by_rnum(struct char_data * ch, int is_in) { if (IS_DARK(is_in) && !CAN_SEE_IN_DARK(ch)) { send_to_char("It is pitch black...\r\n", ch); return; } send_to_char(CCCYN(ch, C_NRM), ch); if (PRF_FLAGGED(ch, PRF_ROOMFLAGS)) { sprintbit((long) ROOM_FLAGS(is_in), room_bits, buf); sprintf(buf2, "[%5d] %s [ %s]", world[is_in].number, world[is_in].name, buf); send_to_char(buf2, ch); } else send_to_char(world[is_in].name, ch); send_to_char(CCNRM(ch, C_NRM), ch); send_to_char("\r\n", ch); send_to_char(world[is_in].description, ch); /* autoexits */ if (PRF_FLAGGED(ch, PRF_AUTOEXIT)) auto_exits_by_rnum(ch, is_in); /* now list characters & objects */ send_to_char(CCGRN(ch, C_NRM), ch); list_obj_to_char(world[is_in].contents, ch, 0, FALSE); send_to_char(CCYEL(ch, C_NRM), ch); list_char_to_char(world[is_in].people, ch); send_to_char(CCNRM(ch, C_NRM), ch); } ACMD(do_drive) { int x, dir; const dirParseStruct dirParse[6] = { {SCMD_NORTH - 1, "north"}, {SCMD_SOUTH - 1, "south"}, {SCMD_EAST - 1, "east"}, {SCMD_WEST - 1, "west"}, {SCMD_UP - 1, "up"}, {SCMD_DOWN - 1, "down"} }; struct obj_data *vehicle, *controls, *vehicle_in_out; controls = get_obj_in_list_type(ITEM_V_CONTROLS, world[ch->in_room].contents); if (!controls) { send_to_char("ERROR! Vehicle controls present yet not present!\r\n", ch); return; } vehicle = find_vehicle_by_vnum(GET_OBJ_VAL(controls, 0)); if (!vehicle) { send_to_char("ERROR! Vehicle has been lost somehow!\r\n", ch); return; } if (IS_AFFECTED(ch, AFF_BLIND)) { /* Blind characters can't drive! */ send_to_char("You can't see the controls!\r\n", ch); return; } two_arguments(argument, arg, buf2); /* Gotta give us a direction... */ if (!*arg) { send_to_char("Drive which direction?\r\n", ch); return; } /* Driving Into another Vehicle */ if (is_abbrev(arg, "into")) { int was_in, is_in, is_going_to; if (!*buf2) { send_to_char("Drive into what?\r\n", ch); return; } vehicle_in_out = get_obj_in_list_vis(ch, buf2, world[vehicle->in_room].contents); if (!vehicle_in_out) { send_to_char("Nothing here by that name!\r\n", ch); return; } if (GET_OBJ_TYPE(vehicle_in_out) != ITEM_VEHICLE) { send_to_char("Thats not a vehicle.\r\n", ch); return; } is_going_to = real_room(GET_OBJ_VAL(vehicle_in_out, 0)); if (!IS_SET(ROOM_FLAGS(is_going_to), ROOM_VEHICLE)) { send_to_char("That vehicle can't carry other vehicles.", ch); return; } sprintf(buf, "%s enters %s.\n\r", vehicle->short_description, vehicle_in_out->short_description); send_to_room(buf, vehicle->in_room); was_in = vehicle->in_room; obj_from_room(vehicle); obj_to_room(vehicle, is_going_to); is_in = vehicle->in_room; if (ch->desc != NULL) view_room_by_rnum(ch, is_in); sprintf(buf, "%s enters.\r\n", vehicle->short_description); send_to_room(buf, is_in); return; } else if (is_abbrev(arg, "out")) { struct obj_data *hatch; hatch = get_obj_in_list_type(ITEM_V_HATCH, world[vehicle->in_room].contents); if (!hatch) { send_to_char("Nowhere to drive out of.\r\n", ch); return; } vehicle_in_out = find_vehicle_by_vnum(GET_OBJ_VAL(hatch, 0)); if (!vehicle_in_out) { send_to_char("ERROR! Vehicle to drive out of doesn't exist!\r\n", ch); return; } sprintf(buf, "%s exits %s.\r\n", vehicle->short_description, vehicle_in_out->short_description); send_to_room(buf, vehicle->in_room); obj_from_room(vehicle); obj_to_room(vehicle, vehicle_in_out->in_room); if (ch->desc != NULL) view_room_by_rnum(ch, vehicle->in_room); sprintf(buf, "%s drives out of %s.\r\n", vehicle->short_description, vehicle_in_out->short_description); send_to_room(buf, vehicle->in_room); return; } else for(x = 0; x < (GET_OBJ_VAL(vehicle, 1) ? PILOT_DIRS : DRIVE_DIRS); x++) /* Drive in a direction... */ if (is_abbrev(arg, dirParse[x].dirCmd)) { dir = dirParse[x].dirNum; /* Ok we found the direction! */ if (ch == NULL || dir < 0 || dir >= NUM_OF_DIRS) /* But something is invalid */ return; else if (!EXIT(vehicle, dir) || EXIT(vehicle, dir)->to_room == NOWHERE) { /* But there is no exit that way */ send_to_char("Alas, you cannot go that way...\r\n", ch); return; } else if (IS_SET(EXIT(vehicle, dir)->exit_info, EX_CLOSED)) { /* But the door is closed */ if (EXIT(vehicle, dir)->keyword) { sprintf(buf2, "The %s seems to be closed.\r\n", fname(EXIT(vehicle, dir)->keyword)); send_to_char(buf2, ch); } else send_to_char("It seems to be closed.\r\n", ch); return; } else if (!IS_SET(ROOM_FLAGS(EXIT(vehicle, dir)->to_room), ROOM_VEHICLE)) { /* But the vehicle can't go that way*/ send_to_char("The vehicle can't manage that terrain.\r\n", ch); return; } else { /* But nothing! Let's go that way! */ int was_in, is_in; sprintf(buf, "%s leaves %s.\n\r", vehicle->short_description, dirs[dir]); send_to_room(buf, vehicle->in_room); was_in = vehicle->in_room; obj_from_room(vehicle); obj_to_room(vehicle, world[was_in].dir_option[dir]->to_room); is_in = vehicle->in_room; if (ch->desc != NULL) view_room_by_rnum(ch, is_in); sprintf(buf, "%s enters from the %s.\r\n", vehicle->short_description, dirs[rev_dir[dir]]); send_to_room(buf, is_in); return; } } send_to_char("Thats not a valid direction.\r\n", ch); return; } SPECIAL(vehicle) { struct obj_data * obj; if (CMD_IS("enter")) { one_argument(argument, arg); if (!*arg) { send_to_char("Enter what?\r\n", ch); return 1; } obj = get_obj_in_list_vis(ch, arg, world[ch->in_room].contents); if (!obj) { send_to_char("Nothing by that name is here to enter!\r\n", ch); return 1; } act("You climb into $o.", TRUE, ch, obj, 0, TO_CHAR); act("$n climbs into $o", TRUE, ch, obj, 0, TO_ROOM); char_from_room(ch); char_to_room(ch, real_room(GET_OBJ_VAL(obj, 0))); act("$n climbs in.", TRUE, ch, 0, 0, TO_ROOM); do_look(ch, "", "", 0); return 1; } return 0; } SPECIAL(vehicle_controls) { if (CMD_IS("drive") || CMD_IS("pilot")) { do_drive(ch, argument, cmd, 0); return 1; } return 0; } SPECIAL(vehicle_hatch) { struct obj_data * hatch, * vehicle; if (CMD_IS("leave")) { hatch = get_obj_in_list_type(ITEM_V_HATCH, world[ch->in_room].contents); if (!hatch) { send_to_char("ERROR! Hatch is there, yet it isn't!\r\n", ch); return 1; } vehicle = find_vehicle_by_vnum(GET_OBJ_VAL(hatch, 0)); if (!vehicle) { send_to_char("ERROR! Vehicle has been lost somehow!\r\n", ch); return 1; } act("$n leaves $o", TRUE, ch, vehicle, 0, TO_ROOM); act("You climb out of $o.", TRUE, ch, vehicle, 0, TO_CHAR); char_from_room(ch); char_to_room(ch, vehicle->in_room); act("$n climbs out of $o", TRUE, ch, vehicle, 0, TO_ROOM); /* Now show them the room */ do_look(ch, "", "", 0); return 1; } return 0; } SPECIAL(vehicle_window) { struct obj_data * viewport, * vehicle; if (CMD_IS("look")) { one_argument(argument, arg); if (is_abbrev(arg, "out")) { viewport = get_obj_in_list_type(ITEM_V_WINDOW, world[ch->in_room].contents); if (!viewport) { send_to_char("ERROR! Viewport present, yet not present!\r\n", ch); return 1; } vehicle = find_vehicle_by_vnum(GET_OBJ_VAL(viewport, 0)); if (!vehicle) { send_to_char("ERROR! Vehicle has been lost somehow!\r\n", ch); return 1; } view_room_by_rnum(ch, vehicle->in_room); return 1; } } return 0; } /* assign special procedures to vehicular objects */ void assign_vehicles(void) { SPECIAL(vehicle_controls); SPECIAL(vehicle_window); SPECIAL(vehicle_hatch); SPECIAL(vehicle); /* Assign the generic tank! */ ASSIGNOBJ(200, vehicle); ASSIGNOBJ(201, vehicle_controls); ASSIGNOBJ(202, vehicle_hatch); ASSIGNOBJ(203, vehicle_window); } *** END VEHICLES.C *** Define this in the code (handler.c and handler.h): /* Search the given list for an object type, and return a ptr to that obj */ struct obj_data *get_obj_in_list_type(int type, struct obj_data *list) { struct obj_data * i; for (i = list; i; i = i->next_content) if (GET_OBJ_TYPE(i) == type) return i; return NULL; } In structs.h and constant.c: Declare the relevant Object and Room types for use. Instructions: Create a vehicle object. Set object value 1 to the room to send people who 'enter' the vehicle to. vehicle_controls, vehicle_window, and vehicle_hatch use variable 1 to reference the vnum of the vehicle. DO NOT use more than 1 vehicle of each VNUM... Each vehicle requires its own set of the 4 objects, and its own set of rooms. Want 3 tanks? Make 3 sets of the objects and 3 sets of the rooms. From any room within the vehicle with the CONTROLS a player can "drive "... From any room within the vehicle with the HATCH a player can "exit" From any room within the vehicle with the WINDOW a player can "look out" Note that if there is no vehicle object, proper error checking does take place :-) Also implemented is the ability to let vehicles into other vehicles, but it isn't TOO debugged. Also note that the rooms a vehicle is allowed through need the ROOM_VEHICLES flag set... that way it keeps vehicle movement limited to appropriate areas. FINALLY, please >try< to do the debugging yourself first, before emailing me. This is from an old version (4 days ago, but like on the second day after I started coding it, and probably the day before I merged it into the main source tree), so I can't support it too much, but I >will< try if it appears you tried to handle it yourself first (aka, Im not going to lead the blind, only those with glasses, or contacts, or sand in their eyes :-). Also, there were very few bugs to begin with (I think it worked nearly perfectly on the second day, after I found an initial bug in me forgetting 'char_from_room' before 'char_to_room') Also, if you use it, I would appreciate a line of credit within the login screen or credits (your choice :-). Please email me if you need any assistance (and have given it a shot yourself first) or any comments. - Chris Jacobson