/*
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 <number> OBJ <vnum> <wear_loc>\n\r", ch );
@@ -1454,6 +1504,7 @@
send_to_char( " RESET <number> MOB <vnum> [max #x area] [max #x room]\n\r", ch );
send_to_char( " RESET <number> DELETE\n\r", ch );
send_to_char( " RESET <number> RANDOM [#x exits]\n\r", ch);
+ send_to_char( " RESET <number> RANDOM <exit|0> 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 <vnum>\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 );