/* Random Exits v1.0 by Ryan Jennings (r-jenn@shaw.ca) (08/06/2003) Required for patch: ROM24b6 with OLC1.81, then move this file to the src directory and type 'patch < rexits.patch'. In Game Syntax: reset 1 random 0 world - adds a random exit to a random room in the world. reset 1 random north area - adds an exit north to a random room in the area. reset 1 random 4 - switches 4 exits in the room (Stock OLC). Exits will change every time the room is reset! Good for random clan hall entrances, ect. Notes: EX_TEMP flag prevents exits from saving, so make sure its not ever set on anything important. */ diff -ur src/act_info.c new/act_info.c --- src/act_info.c Sun Jun 8 15:17:53 2003 +++ new/act_info.c Sun Jun 8 15:47:02 2003 @@ -1350,7 +1350,11 @@ if ( fAuto ) { strcat( buf, " " ); + if(IS_SET(pexit->exit_info, EX_TEMP)) + strcat(buf, "("); strcat( buf, dir_name[door] ); + if(IS_SET(pexit->exit_info, EX_TEMP)) + strcat(buf, ")"); } else { diff -ur src/db.c new/db.c --- src/db.c Sun Jun 8 15:20:13 2003 +++ new/db.c Sun Jun 8 15:46:55 2003 @@ -430,6 +430,7 @@ pArea->max_vnum = fread_number(fp); pArea->age = 15; pArea->nplayer = 0; + pArea->version = 0; pArea->empty = FALSE; if ( !area_first ) @@ -503,6 +504,7 @@ pArea->min_vnum = 0; pArea->max_vnum = 0; pArea->area_flags = 0; + pArea->version = 0; /* pArea->recall = ROOM_VNUM_TEMPLE; ROM OLC */ for ( ; ; ) @@ -519,6 +521,7 @@ KEY( "Security", pArea->security, fread_number( fp ) ); break; case 'V': + KEY( "Version", pArea->version, fread_number( fp ) ); if ( !str_cmp( word, "VNUMs" ) ) { pArea->min_vnum = fread_number( fp ); @@ -1000,8 +1003,9 @@ /* if_flag */ fread_number( fp ); pReset->arg1 = fread_number( fp ); pReset->arg2 = fread_number( fp ); - pReset->arg3 = (letter == 'G' || letter == 'R') - ? 0 : fread_number( fp ); + pReset->arg3 = (letter == 'G' || (letter == 'R' + && area_last->version < 1)) ? 0 : + fread_number( fp ); pReset->arg4 = (letter == 'P' || letter == 'M') ? fread_number(fp) : 0; fread_to_eol( fp ); @@ -1150,7 +1154,6 @@ else if ( letter == 'D' ) { EXIT_DATA *pexit; - int locks; door = fread_number( fp ); if ( door < 0 || door > 5 ) @@ -1164,24 +1167,33 @@ pexit->keyword = fread_string( fp ); pexit->exit_info = 0; pexit->rs_flags = 0; /* OLC */ - locks = fread_number( fp ); + if(area_last->version < 1) + { + int locks = fread_number( fp ); + switch ( locks ) + { + case 1: + pexit->rs_flags = EX_ISDOOR; break; + case 2: + pexit->rs_flags = EX_ISDOOR | EX_PICKPROOF; break; + case 3: + pexit->rs_flags = EX_ISDOOR | EX_NOPASS; break; + case 4: + pexit->rs_flags = EX_ISDOOR|EX_NOPASS|EX_PICKPROOF; + break; + } + } + else + pexit->rs_flags = fread_flag(fp); + + if(IS_SET(pexit->rs_flags, EX_TEMP)) + REMOVE_BIT(pexit->rs_flags, EX_TEMP); + + pexit->exit_info = pexit->rs_flags; pexit->key = fread_number( fp ); pexit->u1.vnum = fread_number( fp ); pexit->orig_door = door; /* OLC */ - switch ( locks ) - { - case 1: pexit->exit_info = EX_ISDOOR; - pexit->rs_flags = EX_ISDOOR; break; - case 2: pexit->exit_info = EX_ISDOOR | EX_PICKPROOF; - pexit->rs_flags = EX_ISDOOR | EX_PICKPROOF; break; - case 3: pexit->exit_info = EX_ISDOOR | EX_NOPASS; - pexit->rs_flags = EX_ISDOOR | EX_NOPASS; break; - case 4: pexit->exit_info = EX_ISDOOR|EX_NOPASS|EX_PICKPROOF; - pexit->rs_flags = EX_ISDOOR|EX_NOPASS|EX_PICKPROOF; - break; - } - pRoomIndex->exit[door] = pexit; top_exit++; } @@ -1881,12 +1893,23 @@ int d0; int d1; - for ( d0 = 0; d0 < pReset->arg2 - 1; d0++ ) + switch (pReset->arg3) { - d1 = number_range( d0, pReset->arg2-1 ); - pExit = pRoomIndex->exit[d0]; - pRoomIndex->exit[d0] = pRoomIndex->exit[d1]; - pRoomIndex->exit[d1] = pExit; + default: + for (d0 = 0; d0 < pReset->arg2 - 1; d0++) + { + d1 = number_range(d0, pReset->arg2 - 1); + pExit = pRoomIndex->exit[d0]; + pRoomIndex->exit[d0] = pRoomIndex->exit[d1]; + pRoomIndex->exit[d1] = pExit; + } + break; + case 1: + add_random_exit(pRoomIndex, pReset, TRUE); + break; + case 2: + add_random_exit(pRoomIndex, pReset, FALSE); + break; } } break; diff -ur src/db2.c new/db2.c --- src/db2.c Sun Jun 8 15:15:05 2003 +++ new/db2.c Sun Jun 8 15:47:47 2003 @@ -41,6 +41,7 @@ #include "db.h" #include "tables.h" #include "lookup.h" +#include "olc.h" extern int flag_lookup args((const char *name, const struct flag_type *flag_table)); @@ -920,4 +921,143 @@ ++newmobs; return; +} + +int reset_door(RESET_DATA * pReset, bool fRandom) +{ + if (pReset && pReset->command == 'R') + { + if (pReset->arg2 > 0 && pReset->arg2 <= MAX_DIR) + { + return pReset->arg2 - 1; + } + else if (fRandom && pReset->arg4 > 0 && pReset->arg4 <= MAX_DIR) + { + return pReset->arg4 - 1; + } + } + return -1; +} + +int open_exit(ROOM_INDEX_DATA * toRoom, ROOM_INDEX_DATA * pRoom, + RESET_DATA * pReset) +{ + int door; + + if ((door = reset_door(pReset, FALSE)) != -1) + { + if (toRoom->exit[rev_dir[door]] != NULL) + return -1; + + return door; + } + for (door = 0; door < MAX_DIR; door++) + { + if (!toRoom->exit[rev_dir[door]] && !pRoom->exit[door]) + return door; + } + return -1; +} + +void clean_temp_exit(ROOM_INDEX_DATA * pRoom, int door) +{ + ROOM_INDEX_DATA *pToRoom; + + if (!pRoom || door < 0 || door >= MAX_DIR || + pRoom->exit[door] == NULL + || !IS_SET(pRoom->exit[door]->exit_info, EX_TEMP)) + return; + + if ((pToRoom = pRoom->exit[door]->u1.to_room) != NULL) + { + int rev = rev_dir[door]; + + if (pToRoom->exit[rev] + && IS_SET(pToRoom->exit[rev]->exit_info, EX_TEMP)) + { + free_exit(pToRoom->exit[rev]); + pToRoom->exit[rev] = NULL; + } + } + + free_exit(pRoom->exit[door]); + pRoom->exit[door] = NULL; +} + +void clean_entrance(ROOM_INDEX_DATA * pRoom, RESET_DATA * pReset) +{ + int door; + + if (!pRoom) + return; + + if ((door = reset_door(pReset, TRUE)) != -1) + { + clean_temp_exit(pRoom, door); + return; + } + for (door = 0; door < MAX_DIR; door++) + { + clean_temp_exit(pRoom, door); + } +} + +void add_random_exit(ROOM_INDEX_DATA * pRoom, RESET_DATA * pReset, bool Area) +{ + EXIT_DATA *pExit, *toExit; + ROOM_INDEX_DATA *toRoom; + int door, rev, safe = 0; + int minvn, maxvn; + + if (!pRoom) + return; + + if (Area) + { + minvn = pRoom->area->min_vnum; + maxvn = pRoom->area->max_vnum; + } + else + { + minvn = 2; + maxvn = top_vnum_room; + } + + clean_entrance(pRoom, pReset); + + for (;;) + { + toRoom = get_room_index(number_range(minvn, maxvn)); + if (toRoom != NULL && !IS_SET(toRoom->room_flags, ROOM_PRIVATE) + && !IS_SET(toRoom->room_flags, ROOM_SOLITARY) + && !IS_SET(toRoom->room_flags, ROOM_IMP_ONLY) + && !IS_SET(toRoom->room_flags, ROOM_GODS_ONLY) + && !IS_SET(toRoom->room_flags, ROOM_HEROES_ONLY) + && !IS_SET(toRoom->room_flags, ROOM_NEWBIES_ONLY) + && IS_NULLSTR(toRoom->owner) && (Area || !toRoom->clan) + && (door = open_exit(toRoom, pRoom, pReset)) != -1) + break; + if (safe++ > top_room) + return; + } + + pExit = new_exit(); + pExit->u1.to_room = toRoom; + pExit->orig_door = door; + SET_BIT(pExit->rs_flags, EX_TEMP); + SET_BIT(pExit->exit_info, EX_TEMP); + pRoom->exit[door] = pExit; + + rev = rev_dir[door]; + toExit = new_exit(); + toExit->u1.to_room = pRoom; + toExit->orig_door = rev; + SET_BIT(toExit->rs_flags, EX_TEMP); + SET_BIT(toExit->exit_info, EX_TEMP); + toRoom->exit[rev] = toExit; + + // arg4 doesn't save so we can use it to keep track + // of random exit doors + if (pReset && pReset->arg4 != -1) + pReset->arg4 = door + 1; } diff -ur src/merc.h new/merc.h --- src/merc.h Sun Jun 8 15:15:05 2003 +++ new/merc.h Sun Jun 8 15:46:59 2003 @@ -1146,6 +1146,7 @@ #define EX_INFURIATING (J) #define EX_NOCLOSE (K) #define EX_NOLOCK (L) +#define EX_TEMP (M) @@ -1676,6 +1677,7 @@ int vnum; /* OLC */ /* Area vnum */ int area_flags; /* OLC */ int security; /* OLC */ /* Value 1-9 */ + int version; }; @@ -2250,6 +2252,8 @@ void bug args( ( const char *str, int param ) ); void log_string args( ( const char *str ) ); void tail_chain args( ( void ) ); +int reset_door args((RESET_DATA * pReset, bool fRandom)); +void add_random_exit args((ROOM_INDEX_DATA * pRoom, RESET_DATA * pReset, bool Area)); /* effect.c */ void acid_effect args( (void *vo, int level, int dam, int target) ); @@ -2465,6 +2469,9 @@ #define AREA_CHANGED 1 /* Area has been modified. */ #define AREA_ADDED 2 /* Area has been added to. */ #define AREA_LOADING 4 /* Used for counting in db.c */ + +/* Area file version */ +#define AREA_VERSION 1 /* Use to make changes to area file format */ #define MAX_DIR 6 #define NO_FLAG -99 /* Must not be used in flags or stats. */ diff -ur src/olc.c new/olc.c --- src/olc.c Sun Jun 8 15:15:28 2003 +++ new/olc.c Sun Jun 8 15:47:04 2003 @@ -1165,9 +1165,13 @@ continue; } - sprintf( buf, "R[%5d] Exits are randomized in %s\n\r", - pReset->arg1, pRoomIndex->name ); - strcat( final, buf ); + sprintf(buf, "R[%5d] Set to randomize %s %s.\n\r", + pReset->arg1, + pReset->arg3 == 0 ? "exits" : pReset->arg2 == + 0 ? "any available exit" : dir_name[pReset->arg2 - 1], + pReset->arg3 == 0 ? "in room" : pReset->arg3 == + 1 ? "to this area" : "to the world"); + strcat(final, buf); break; } @@ -1222,6 +1226,23 @@ return; } +int get_direction(const char *arg) +{ + if (!str_cmp(arg, "n") || !str_cmp(arg, "north")) + return DIR_NORTH; + if (!str_cmp(arg, "e") || !str_cmp(arg, "east")) + return DIR_EAST; + if (!str_cmp(arg, "s") || !str_cmp(arg, "south")) + return DIR_SOUTH; + if (!str_cmp(arg, "w") || !str_cmp(arg, "west")) + return DIR_WEST; + if (!str_cmp(arg, "u") || !str_cmp(arg, "up")) + return DIR_UP; + if (!str_cmp(arg, "d") || !str_cmp(arg, "down")) + return DIR_DOWN; + + return -1; +} void do_resets( CHAR_DATA *ch, char *argument ) @@ -1328,6 +1349,7 @@ } free_reset_data( pReset ); + SET_BIT(ch->in_room->area->area_flags, AREA_CHANGED); send_to_char( "Reset deleted.\n\r", ch ); } else @@ -1431,21 +1453,49 @@ send_to_char( "Reset added.\n\r", ch ); } else - if (!str_cmp( arg2, "random") && is_number(arg3)) - { - if (atoi(arg3) < 1 || atoi(arg3) > 6) - { - send_to_char("Invalid argument.\n\r", ch); - return; - } - pReset = new_reset_data (); - pReset->command = 'R'; - pReset->arg1 = ch->in_room->vnum; - pReset->arg2 = atoi(arg3); - add_reset( ch->in_room, pReset, atoi( arg1 ) ); - SET_BIT( ch->in_room->area->area_flags, AREA_CHANGED ); - send_to_char( "Random exits reset added.\n\r", ch); - } + if (!str_cmp(arg2, "random")) + { + int door; + + if (is_number(arg3)) + { + door = atoi(arg3); + } + else + { + if ((door = get_direction(arg3)) != -1) + door++; + } + + if (door < 0 || door > 6) + { + send_to_char("Invalid argument.\n\r", ch); + return; + } + + if (door == 0 + && (IS_NULLSTR(arg4) || !is_exact_name(arg4, "area world"))) + { + send_to_char("Invalid or missing argument.\n\r", ch); + return; + } + if (is_exact_name(arg4, "area world") && door > 0 + && ch->in_room->exit[door - 1] != NULL) + { + send_to_char("There is already an exit in that direction.\n\r", ch); + return; + } + pReset = new_reset_data(); + pReset->command = 'R'; + pReset->arg1 = ch->in_room->vnum; + pReset->arg2 = door; + pReset->arg3 = + !str_cmp(arg4, "area") ? 1 : !str_cmp(arg4, "world") ? 2 : 0; + add_reset(ch->in_room, pReset, atoi(arg1)); + SET_BIT(ch->in_room->area->area_flags, AREA_CHANGED); + send_to_char("Random exits reset added.\n\r", ch); + return; + } else { send_to_char( "Syntax: RESET OBJ \n\r", ch ); @@ -1454,6 +1504,7 @@ send_to_char( " RESET MOB [max #x area] [max #x room]\n\r", ch ); send_to_char( " RESET DELETE\n\r", ch ); send_to_char( " RESET RANDOM [#x exits]\n\r", ch); + send_to_char( " RESET RANDOM area|world\n\r", ch); } } diff -ur src/olc_act.c new/olc_act.c --- src/olc_act.c Sun Jun 8 15:15:28 2003 +++ new/olc_act.c Sun Jun 8 15:47:07 2003 @@ -1241,7 +1241,17 @@ } +bool check_reset_exit(ROOM_INDEX_DATA * pRoom, int door) +{ + RESET_DATA *pReset; + for (pReset = pRoom->reset_first; pReset; pReset = pReset->next) + { + if (reset_door(pReset, FALSE) == door) + return TRUE; + } + return FALSE; +} /* Local function. */ bool change_exit( CHAR_DATA *ch, char *argument, int door ) @@ -1347,6 +1357,11 @@ EXIT_DATA *pExit; ROOM_INDEX_DATA *toRoom; + if (check_reset_exit(pRoom, door)) + { + send_to_char("There is a random exit reset already using that direction.\n\r", ch); + return FALSE; + } if ( arg[0] == '\0' || !is_number( arg ) ) { send_to_char( "Syntax: [direction] link [vnum]\n\r", ch ); @@ -1393,6 +1408,11 @@ { char buf[MAX_STRING_LENGTH]; + if (check_reset_exit(pRoom, door)) + { + send_to_char("There is a random exit reset already using that direction.\n\r", ch); + return FALSE; + } if ( arg[0] == '\0' || !is_number( arg ) ) { send_to_char( "Syntax: [direction] dig \n\r", ch ); @@ -1409,6 +1429,11 @@ { ROOM_INDEX_DATA *toRoom; + if (check_reset_exit(pRoom, door)) + { + send_to_char("There is a random exit reset already using that direction.\n\r", ch); + return FALSE; + } if ( arg[0] == '\0' || !is_number( arg ) ) { send_to_char( "Syntax: [direction] room [vnum]\n\r", ch ); diff -ur src/olc_save.c new/olc_save.c --- src/olc_save.c Sun Jun 8 15:22:49 2003 +++ new/olc_save.c Sun Jun 8 15:46:52 2003 @@ -479,6 +479,7 @@ EXTRA_DESCR_DATA *pEd; EXIT_DATA *pExit; int iHash; + char buf[MAX_STRING_LENGTH]; int door; fprintf( fp, "#ROOMS\n" ); @@ -504,9 +505,8 @@ for( door = 0; door < MAX_DIR; door++ ) /* I hate this! */ { if ( ( pExit = pRoomIndex->exit[door] ) - && pExit->u1.to_room ) + && pExit->u1.to_room && !IS_SET(pExit->rs_flags, EX_TEMP)) { - int locks = 0; /* HACK : TO PREVENT EX_LOCKED etc without EX_ISDOOR to stop booting the mud */ @@ -523,29 +523,10 @@ else REMOVE_BIT(pExit->rs_flags, EX_ISDOOR); - /* THIS SUCKS but it's backwards compatible */ - /* NOTE THAT EX_NOCLOSE NOLOCK etc aren't being saved */ - if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) - && ( !IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) - && ( !IS_SET( pExit->rs_flags, EX_NOPASS ) ) ) - locks = 1; - if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) - && ( IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) - && ( !IS_SET( pExit->rs_flags, EX_NOPASS ) ) ) - locks = 2; - if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) - && ( !IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) - && ( IS_SET( pExit->rs_flags, EX_NOPASS ) ) ) - locks = 3; - if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) - && ( IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) - && ( IS_SET( pExit->rs_flags, EX_NOPASS ) ) ) - locks = 4; - fprintf( fp, "D%d\n", pExit->orig_door ); fprintf( fp, "%s~\n", fix_string( pExit->description ) ); fprintf( fp, "%s~\n", pExit->keyword ); - fprintf( fp, "%d %d %d\n", locks, + fprintf( fp, "%s %d %d\n", fwrite_flag(pExit->rs_flags, buf), pExit->key, pExit->u1.to_room->vnum ); } @@ -627,7 +608,7 @@ for( door = 0; door < MAX_DIR; door++ ) { if ( ( pExit = pRoomIndex->exit[door] ) - && pExit->u1.to_room + && pExit->u1.to_room && !IS_SET(pExit->rs_flags, EX_TEMP) && ( IS_SET( pExit->rs_flags, EX_CLOSED ) || IS_SET( pExit->rs_flags, EX_LOCKED ) ) ) #if defined( VERBOSE ) @@ -751,9 +732,9 @@ case 'R': pRoom = get_room_index( pReset->arg1 ); - fprintf( fp, "R 0 %d %d Randomize %s\n", + fprintf( fp, "R 0 %d %d %d Randomize %s\n", pReset->arg1, - pReset->arg2, + pReset->arg2, pReset->arg3, pRoom->name ); break; } @@ -812,9 +793,9 @@ case 'R': pRoom = get_room_index( pReset->arg1 ); - fprintf( fp, "R 0 %d %d\n", + fprintf( fp, "R 0 %d %d %d\n", pReset->arg1, - pReset->arg2 ); + pReset->arg2, pReset->arg3 ); break; } #endif @@ -940,6 +921,7 @@ fprintf( fp, "VNUMs %d %d\n", pArea->min_vnum, pArea->max_vnum ); fprintf( fp, "Credits %s~\n", pArea->credits ); fprintf( fp, "Security %d\n", pArea->security ); + fprintf( fp, "Version %d\n", AREA_VERSION ); fprintf( fp, "End\n\n\n\n" ); save_mobiles( fp, pArea );