mirror of
https://github.com/tbamud/tbamud.git
synced 2025-12-22 02:00:13 +01:00
Corrected more files not under SVN control.
This commit is contained in:
parent
73e8b58bee
commit
700d74bfcd
5 changed files with 2354 additions and 1 deletions
541
src/asciimap.c
Normal file
541
src/asciimap.c
Normal file
|
|
@ -0,0 +1,541 @@
|
|||
/**************************************************************************
|
||||
* File: asciimap.c Part of tbaMUD *
|
||||
* Usage: Generates an ASCII map of the player's surroundings. *
|
||||
* *
|
||||
* All rights reserved. See license for complete information. *
|
||||
* *
|
||||
* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
|
||||
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. *
|
||||
**************************************************************************/
|
||||
|
||||
#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 "spells.h"
|
||||
#include "house.h"
|
||||
#include "constants.h"
|
||||
#include "dg_scripts.h"
|
||||
#include "asciimap.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Begin Local (File Scope) Defines and Global Variables
|
||||
*****************************************************************************/
|
||||
/* Do not blindly change these values, as many values cause the map to stop working - backup first */
|
||||
#define CANVAS_HEIGHT 19
|
||||
#define CANVAS_WIDTH 51
|
||||
#define LEGEND_WIDTH 15
|
||||
|
||||
#define DEFAULT_MAP_SIZE CONFIG_MAP_SIZE
|
||||
|
||||
#define MAX_MAP_SIZE (CANVAS_WIDTH - 1)/4
|
||||
#define MAX_MAP CANVAS_WIDTH
|
||||
|
||||
#define MAX_MAP_DIR 6
|
||||
#define MAX_MAP_FOLLOW 4
|
||||
|
||||
#define SECT_EMPTY 30 /* anything greater than num sect types */
|
||||
#define SECT_STRANGE (SECT_EMPTY + 1)
|
||||
#define SECT_HERE (SECT_STRANGE + 1)
|
||||
|
||||
#define DOOR_NS -1
|
||||
#define DOOR_EW -2
|
||||
#define DOOR_UP -3
|
||||
#define DOOR_DOWN -4
|
||||
#define VDOOR_NS -5
|
||||
#define VDOOR_EW -6
|
||||
#define DOOR_NONE -7
|
||||
#define NUM_DOOR_TYPES 7
|
||||
|
||||
#define MAP_CIRCLE 0
|
||||
#define MAP_RECTANGLE 1
|
||||
|
||||
#define MAP_NORMAL 0
|
||||
#define MAP_COMPACT 1
|
||||
|
||||
struct map_info_type
|
||||
{
|
||||
int sector_type;
|
||||
char disp[20];
|
||||
};
|
||||
|
||||
static struct map_info_type door_info[] =
|
||||
{
|
||||
{ DOOR_NONE, " " },
|
||||
{ VDOOR_EW, " @m+@n " },
|
||||
{ VDOOR_NS, " @m+@n "},
|
||||
{ DOOR_DOWN, "@r-@n " },
|
||||
{ DOOR_UP, "@r+@n " },
|
||||
{ DOOR_EW, " - " },
|
||||
{ DOOR_NS, " | " }
|
||||
};
|
||||
|
||||
static struct map_info_type compact_door_info[] =
|
||||
{
|
||||
{ DOOR_NONE, " " },
|
||||
{ VDOOR_EW, " @m+@n " },
|
||||
{ VDOOR_NS, " @m+@n "},
|
||||
{ DOOR_DOWN, "@r-@n" },
|
||||
{ DOOR_UP, "@r+@n" },
|
||||
{ DOOR_EW, "-" },
|
||||
{ DOOR_NS, " | " }
|
||||
};
|
||||
|
||||
/* Add new sector types below for both map_info and world_map_info */
|
||||
/* The last 3 MUST remain the same, although the symbol can be changed */
|
||||
/* New sectors also need to be added to the perform_map function below */
|
||||
static struct map_info_type map_info[] =
|
||||
{
|
||||
{ SECT_INSIDE, "@c[@n.@c]@n" }, /* 0 */
|
||||
{ SECT_CITY, "@c[@wC@c]@n" },
|
||||
{ SECT_FIELD, "@c[@g,@c]@n" },
|
||||
{ SECT_FOREST, "@c[@gY@c]@n" },
|
||||
{ SECT_HILLS, "@c[@Mm@c]@n" },
|
||||
{ SECT_MOUNTAIN, "@c[@rM@c]@n" }, /* 5 */
|
||||
{ SECT_WATER_SWIM, "@c[@c~@c]@n" },
|
||||
{ SECT_WATER_NOSWIM, "@c[@b=@c]@n" },
|
||||
{ SECT_FLYING, "@c[@C^@c]@n" },
|
||||
{ SECT_UNDERWATER, "@c[@bU@c]@n" },
|
||||
{ -1, "" }, /* 10 */
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" }, /* 15 */
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" }, /* 20 */
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" }, /* 25 */
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ SECT_EMPTY, " " }, /* 30 */
|
||||
{ SECT_STRANGE, "@c[@R?@c]@n" },
|
||||
{ SECT_HERE, "@c[@B!@c]@n" },
|
||||
};
|
||||
|
||||
static struct map_info_type world_map_info[] =
|
||||
{
|
||||
{ SECT_INSIDE, "@n." }, /* 0 */
|
||||
{ SECT_CITY, "@wC" },
|
||||
{ SECT_FIELD, "@g," },
|
||||
{ SECT_FOREST, "@gY" },
|
||||
{ SECT_HILLS, "@Mm" },
|
||||
{ SECT_MOUNTAIN, "@rM" }, /* 5 */
|
||||
{ SECT_WATER_SWIM, "@c~" },
|
||||
{ SECT_WATER_NOSWIM, "@b=" },
|
||||
{ SECT_FLYING, "@C^" },
|
||||
{ SECT_UNDERWATER, "@bU" },
|
||||
{ -1, "" }, /* 10 */
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" }, /* 15 */
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" }, /* 20 */
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" }, /* 25 */
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ -1, "" },
|
||||
{ SECT_EMPTY, " " }, /* 30 */
|
||||
{ SECT_STRANGE, "@R?" },
|
||||
{ SECT_HERE, "@B!" },
|
||||
};
|
||||
|
||||
|
||||
static int map[MAX_MAP][MAX_MAP];
|
||||
static int offsets[4][2] ={ {-2, 0},{ 0, 2},{ 2, 0},{ 0, -2} };
|
||||
static int offsets_worldmap[4][2] ={ {-1, 0},{ 0, 1},{ 1, 0},{ 0, -1} };
|
||||
static int door_offsets[6][2] ={ {-1, 0},{ 0, 1},{ 1, 0},{ 0, -1},{ -1, 1},{ 1, 1} };
|
||||
static int door_marks[6] = { DOOR_NS, DOOR_EW, DOOR_NS, DOOR_EW, DOOR_UP, DOOR_DOWN };
|
||||
static int vdoor_marks[4] = { VDOOR_NS, VDOOR_EW, VDOOR_NS, VDOOR_EW };
|
||||
/******************************************************************************
|
||||
* End Local (File Scope) Defines and Global Variables
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* Begin Local (File Scope) Function Prototypes
|
||||
*****************************************************************************/
|
||||
static void MapArea(room_rnum room, struct char_data *ch, int x, int y, int min, int max, sh_int xpos, sh_int ypos, bool worldmap);
|
||||
static char *StringMap(int centre, int size);
|
||||
static char *WorldMap(int centre, int size, int mapshape, int maptype );
|
||||
static char *CompactStringMap(int centre, int size);
|
||||
static void perform_map( struct char_data *ch, char *argument, bool worldmap );
|
||||
/******************************************************************************
|
||||
* End Local (File Scope) Function Prototypes
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
bool can_see_map(struct char_data *ch) {
|
||||
/* Is the map funcionality disabled? */
|
||||
if (CONFIG_MAP == MAP_OFF)
|
||||
return FALSE;
|
||||
else if ((CONFIG_MAP == MAP_IMM_ONLY) && (GET_LEVEL(ch) < LVL_IMMORT))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* MapArea function - create the actual map */
|
||||
static void MapArea(room_rnum room, struct char_data *ch, int x, int y, int min, int max, sh_int xpos, sh_int ypos, bool worldmap)
|
||||
{
|
||||
room_rnum prospect_room;
|
||||
struct room_direction_data *pexit;
|
||||
int door, ew_size=0, ns_size=0, x_exit_pos=0, y_exit_pos=0;
|
||||
sh_int prospect_xpos, prospect_ypos;
|
||||
|
||||
if (map[x][y] < 0)
|
||||
return; /* this is a door */
|
||||
|
||||
/* marks the room as visited */
|
||||
if(room == IN_ROOM(ch))
|
||||
map[x][y] = SECT_HERE;
|
||||
else
|
||||
map[x][y] = SECT(room);
|
||||
|
||||
if ( (x < min) || ( y < min) || ( x > max ) || ( y > max) ) return;
|
||||
|
||||
/* Check for exits */
|
||||
for ( door = 0; door < MAX_MAP_DIR; door++ ) {
|
||||
|
||||
if( door < MAX_MAP_FOLLOW &&
|
||||
xpos+door_offsets[door][0] >= 0 &&
|
||||
xpos+door_offsets[door][0] <= ns_size &&
|
||||
ypos+door_offsets[door][1] >= 0 &&
|
||||
ypos+door_offsets[door][1] <= ew_size)
|
||||
{ /* Virtual exit */
|
||||
|
||||
map[x+door_offsets[door][0]][y+door_offsets[door][1]] = vdoor_marks[door] ;
|
||||
if (map[x+offsets[door][0]][y+offsets[door][1]] == SECT_EMPTY )
|
||||
MapArea(room,ch,x + offsets[door][0], y + offsets[door][1], min, max, xpos+door_offsets[door][0], ypos+door_offsets[door][1], worldmap);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( (pexit = world[room].dir_option[door]) > 0 &&
|
||||
(pexit->to_room > 0 ) && (pexit->to_room != NOWHERE) &&
|
||||
(!IS_SET(pexit->exit_info, EX_CLOSED))) { /* A real exit */
|
||||
|
||||
/* But is the door here... */
|
||||
switch (door) {
|
||||
case NORTH:
|
||||
if(xpos > 0 || ypos!=y_exit_pos) continue;
|
||||
break;
|
||||
case SOUTH:
|
||||
if(xpos < ns_size || ypos!=y_exit_pos) continue;
|
||||
break;
|
||||
case EAST:
|
||||
if(ypos < ew_size || xpos!=x_exit_pos) continue;
|
||||
break;
|
||||
case WEST:
|
||||
if(ypos > 0 || xpos!=x_exit_pos) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* if ( (x < min) || ( y < min) || ( x > max ) || ( y > max) ) return;*/
|
||||
prospect_room = pexit->to_room;
|
||||
|
||||
/* one way into area OR maze */
|
||||
if ( world[prospect_room].dir_option[rev_dir[door]] &&
|
||||
world[prospect_room].dir_option[rev_dir[door]]->to_room != room) {
|
||||
map[x][y] = SECT_STRANGE;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!worldmap)
|
||||
map[x+door_offsets[door][0]][y+door_offsets[door][1]] = door_marks[door] ;
|
||||
|
||||
prospect_xpos = prospect_ypos = 0;
|
||||
switch (door) {
|
||||
case NORTH:
|
||||
prospect_xpos = ns_size;
|
||||
case SOUTH:
|
||||
prospect_ypos = world[prospect_room].dir_option[rev_dir[door]] ? y_exit_pos : ew_size/2;
|
||||
break;
|
||||
case WEST:
|
||||
prospect_ypos = ew_size;
|
||||
case EAST:
|
||||
prospect_xpos = world[prospect_room].dir_option[rev_dir[door]] ? x_exit_pos : ns_size/2;
|
||||
}
|
||||
|
||||
if(worldmap) {
|
||||
if ( door < MAX_MAP_FOLLOW && map[x+offsets_worldmap[door][0]][y+offsets_worldmap[door][1]] == SECT_EMPTY )
|
||||
MapArea(pexit->to_room,ch,x + offsets_worldmap[door][0], y + offsets_worldmap[door][1], min, max, prospect_xpos, prospect_ypos, worldmap);
|
||||
} else {
|
||||
if ( door < MAX_MAP_FOLLOW && map[x+offsets[door][0]][y+offsets[door][1]] == SECT_EMPTY )
|
||||
MapArea(pexit->to_room,ch,x + offsets[door][0], y + offsets[door][1], min, max, prospect_xpos, prospect_ypos, worldmap);
|
||||
}
|
||||
} /* end if exit there */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Returns a string representation of the map */
|
||||
static char *StringMap(int centre, int size)
|
||||
{
|
||||
static char strmap[MAX_MAP*MAX_MAP*11 + MAX_MAP*2 + 1];
|
||||
char *mp = strmap;
|
||||
char *tmp;
|
||||
int x, y;
|
||||
|
||||
/* every row */
|
||||
for (x = centre - CANVAS_HEIGHT/2; x <= centre + CANVAS_HEIGHT/2; x++) {
|
||||
/* every column */
|
||||
for (y = centre - CANVAS_WIDTH/6; y <= centre + CANVAS_WIDTH/6; y++) {
|
||||
if (abs(centre - x)<=size && abs(centre-y)<=size)
|
||||
tmp = (map[x][y]<0) ? \
|
||||
door_info[NUM_DOOR_TYPES + map[x][y]].disp : \
|
||||
map_info[map[x][y]].disp ;
|
||||
else
|
||||
tmp = map_info[SECT_EMPTY].disp;
|
||||
strcpy(mp, tmp);
|
||||
mp += strlen(tmp);
|
||||
}
|
||||
strcpy(mp, "\r\n");
|
||||
mp+=2;
|
||||
}
|
||||
*mp='\0';
|
||||
return strmap;
|
||||
}
|
||||
|
||||
static char *WorldMap(int centre, int size, int mapshape, int maptype )
|
||||
{
|
||||
static char strmap[MAX_MAP*MAX_MAP*4 + MAX_MAP*2 + 1];
|
||||
char *mp = strmap;
|
||||
int x, y;
|
||||
int xmin, xmax, ymin, ymax;
|
||||
|
||||
switch(maptype) {
|
||||
case MAP_COMPACT:
|
||||
xmin = centre - size;
|
||||
xmax = centre + size;
|
||||
ymin = centre - 2*size;
|
||||
ymax = centre + 2*size;
|
||||
break;
|
||||
default:
|
||||
xmin = centre - CANVAS_HEIGHT/2;
|
||||
xmax = centre + CANVAS_HEIGHT/2;
|
||||
ymin = centre - CANVAS_WIDTH/2;
|
||||
ymax = centre + CANVAS_WIDTH/2;
|
||||
}
|
||||
|
||||
|
||||
/* every row */
|
||||
/* for (x = centre - size; x <= centre + size; x++) { */
|
||||
for (x = xmin; x <= xmax; x++) {
|
||||
/* every column */
|
||||
/* for (y = centre - (2*size) ; y <= centre + (2*size) ; y++) { */
|
||||
for (y = ymin ; y <= ymax ; y++) {
|
||||
|
||||
if((mapshape == MAP_RECTANGLE && abs(centre - y) <= size*2 && abs(centre - x) <= size ) ||
|
||||
((mapshape == MAP_CIRCLE) && (centre-x)*(centre-x) + (centre-y)*(centre-y)/4 <= (size * size + 1))) {
|
||||
strcpy(mp, world_map_info[map[x][y]].disp);
|
||||
mp += strlen(world_map_info[map[x][y]].disp);
|
||||
} else {
|
||||
strcpy(mp++, " ");
|
||||
}
|
||||
}
|
||||
strcpy(mp, "@n\r\n");
|
||||
mp+=4;
|
||||
}
|
||||
*mp='\0';
|
||||
return strmap;
|
||||
}
|
||||
|
||||
static char *CompactStringMap(int centre, int size)
|
||||
{
|
||||
static char strmap[MAX_MAP*MAX_MAP*12 + MAX_MAP*2 + 1];
|
||||
char *mp = strmap;
|
||||
int x, y;
|
||||
|
||||
/* every row */
|
||||
for (x = centre - size; x <= centre + size; x++) {
|
||||
/* every column */
|
||||
for (y = centre - size; y <= centre + size; y++) {
|
||||
strcpy(mp, (map[x][y]<0) ? \
|
||||
compact_door_info[NUM_DOOR_TYPES + map[x][y]].disp : \
|
||||
map_info[map[x][y]].disp);
|
||||
mp += strlen((map[x][y]<0) ? \
|
||||
compact_door_info[NUM_DOOR_TYPES + map[x][y]].disp : \
|
||||
map_info[map[x][y]].disp);
|
||||
}
|
||||
strcpy(mp, "\r\n");
|
||||
mp+=2;
|
||||
}
|
||||
*mp='\0';
|
||||
return strmap;
|
||||
}
|
||||
|
||||
/* Display a nicely formatted map with a legend */
|
||||
static void perform_map( struct char_data *ch, char *argument, bool worldmap )
|
||||
{
|
||||
int size = DEFAULT_MAP_SIZE;
|
||||
int centre, x, y, min, max;
|
||||
char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH], buf1[MAX_STRING_LENGTH], buf2[MAX_STRING_LENGTH];
|
||||
int count = 0;
|
||||
int ew_size=0, ns_size=0;
|
||||
int mapshape = MAP_CIRCLE;
|
||||
|
||||
two_arguments( argument, arg1 , arg2 );
|
||||
if(*arg1)
|
||||
{
|
||||
size = atoi(arg1);
|
||||
}
|
||||
if (*arg2)
|
||||
{
|
||||
if (is_abbrev(arg2, "normal")) worldmap=FALSE;
|
||||
else if (is_abbrev(arg2, "world")) worldmap=TRUE;
|
||||
else {
|
||||
send_to_char(ch, "Usage: @ymap <distance> [ normal | world ]@n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(size<0) {
|
||||
size = -size;
|
||||
mapshape = MAP_RECTANGLE;
|
||||
}
|
||||
size = URANGE(1,size,MAX_MAP_SIZE);
|
||||
|
||||
centre = MAX_MAP/2;
|
||||
|
||||
if(worldmap) {
|
||||
min = centre - 2*size;
|
||||
max = centre + 2*size;
|
||||
} else {
|
||||
min = centre - size;
|
||||
max = centre + size;
|
||||
}
|
||||
|
||||
/* Blank the map */
|
||||
for (x = 0; x < MAX_MAP; ++x)
|
||||
for (y = 0; y < MAX_MAP; ++y)
|
||||
map[x][y]= (!(y%2) && !worldmap) ? DOOR_NONE : SECT_EMPTY;
|
||||
|
||||
/* starts the mapping with the centre room */
|
||||
MapArea(IN_ROOM(ch), ch, centre, centre, min, max, ns_size/2, ew_size/2, worldmap);
|
||||
|
||||
/* marks the center, where ch is */
|
||||
map[centre][centre] = SECT_HERE;
|
||||
|
||||
/* Feel free to put your own MUD name or header in here */
|
||||
send_to_char(ch, " @Y-@ytbaMUD Map System@Y-@n\r\n"
|
||||
"@D .-.__--.,--.__.-.@n\r\n" );
|
||||
|
||||
count += sprintf(buf + count, "@n@n@n%s Up\\\\", door_info[NUM_DOOR_TYPES + DOOR_UP].disp);
|
||||
count += sprintf(buf + count, "@n@n@n%s Down\\\\", door_info[NUM_DOOR_TYPES + DOOR_DOWN].disp);
|
||||
count += sprintf(buf + count, "@n%s You\\\\", map_info[SECT_HERE].disp);
|
||||
count += sprintf(buf + count, "@n%s Inside\\\\", map_info[SECT_INSIDE].disp);
|
||||
count += sprintf(buf + count, "@n%s City\\\\", map_info[SECT_CITY].disp);
|
||||
count += sprintf(buf + count, "@n%s Field\\\\", map_info[SECT_FIELD].disp);
|
||||
count += sprintf(buf + count, "@n%s Forest\\\\", map_info[SECT_FOREST].disp);
|
||||
count += sprintf(buf + count, "@n%s Hills\\\\", map_info[SECT_HILLS].disp);
|
||||
count += sprintf(buf + count, "@n%s Mountain\\\\", map_info[SECT_MOUNTAIN].disp);
|
||||
count += sprintf(buf + count, "@n%s Swim\\\\", map_info[SECT_WATER_SWIM].disp);
|
||||
count += sprintf(buf + count, "@n%s Boat\\\\", map_info[SECT_WATER_NOSWIM].disp);
|
||||
count += sprintf(buf + count, "@n%s Flying\\\\", map_info[SECT_FLYING].disp);
|
||||
count += sprintf(buf + count, "@n%s Underwater\\\\", map_info[SECT_UNDERWATER].disp);
|
||||
|
||||
strcpy(buf, strfrmt(buf, LEGEND_WIDTH, CANVAS_HEIGHT + 2, FALSE, TRUE, TRUE));
|
||||
|
||||
/* Start with an empty column */
|
||||
strcpy(buf1, strfrmt("",0, CANVAS_HEIGHT + 2, FALSE, FALSE, TRUE));
|
||||
|
||||
/* Paste the legend */
|
||||
strcpy(buf2, strpaste(buf1, buf, "@D | @n"));
|
||||
|
||||
/* Set up the map */
|
||||
memset(buf, ' ', CANVAS_WIDTH);
|
||||
count = (CANVAS_WIDTH);
|
||||
if(worldmap)
|
||||
count += sprintf(buf + count , "\r\n%s", WorldMap(centre, size, mapshape, MAP_NORMAL));
|
||||
else
|
||||
count += sprintf(buf + count , "\r\n%s", StringMap(centre, size));
|
||||
memset(buf + count, ' ', CANVAS_WIDTH);
|
||||
strcpy(buf + count + CANVAS_WIDTH, "\r\n");
|
||||
/* Paste it on */
|
||||
strcpy(buf2, strpaste(buf2, buf, "@D | @n"));
|
||||
/* Paste on the right border */
|
||||
strcpy(buf2, strpaste(buf2, buf1, " "));
|
||||
/* Print it all out */
|
||||
send_to_char(ch, buf2);
|
||||
|
||||
send_to_char(ch, "@D `.-.__--.,-.__.-.-'@n\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Display a string with the map beside it */
|
||||
void str_and_map(char *str, struct char_data *ch ) {
|
||||
int size, centre, x, y, min, max, char_size;
|
||||
int ew_size=0, ns_size=0;
|
||||
bool worldmap;
|
||||
|
||||
/* Check MUDs map config options - if disabled, just show room decsription */
|
||||
if (!can_see_map(ch)) {
|
||||
send_to_char(ch, strfrmt(str, GET_SCREEN_WIDTH(ch), 1, FALSE, FALSE, FALSE));
|
||||
return;
|
||||
}
|
||||
|
||||
worldmap = ROOM_FLAGGED(IN_ROOM(ch), ROOM_WORLDMAP) ? TRUE : FALSE ;
|
||||
|
||||
if(!PRF_FLAGGED(ch, PRF_AUTOMAP)) {
|
||||
send_to_char(ch, strfrmt(str, GET_SCREEN_WIDTH(ch), 1, FALSE, FALSE, FALSE));
|
||||
return;
|
||||
}
|
||||
|
||||
size = CONFIG_MINIMAP_SIZE;
|
||||
centre = MAX_MAP/2;
|
||||
min = centre - 2*size;
|
||||
max = centre + 2*size;
|
||||
|
||||
for (x = 0; x < MAX_MAP; ++x)
|
||||
for (y = 0; y < MAX_MAP; ++y)
|
||||
map[x][y]= (!(y%2) && !worldmap) ? DOOR_NONE : SECT_EMPTY;
|
||||
|
||||
/* starts the mapping with the center room */
|
||||
MapArea(IN_ROOM(ch), ch, centre, centre, min, max, ns_size/2, ew_size/2, worldmap );
|
||||
map[centre][centre] = SECT_HERE;
|
||||
|
||||
/* char_size = rooms + doors + padding */
|
||||
if(worldmap)
|
||||
char_size = size * 4 + 5;
|
||||
else
|
||||
char_size = 3*(size+1) + (size) + 4;
|
||||
|
||||
if(worldmap)
|
||||
send_to_char(ch, strpaste(strfrmt(str, GET_SCREEN_WIDTH(ch) - char_size, size*2 + 1, FALSE, TRUE, TRUE), WorldMap(centre, size, MAP_CIRCLE, MAP_COMPACT), " "));
|
||||
else
|
||||
send_to_char(ch, strpaste(strfrmt(str, GET_SCREEN_WIDTH(ch) - char_size, size*2 + 1, FALSE, TRUE, TRUE), CompactStringMap(centre, size), " "));
|
||||
|
||||
}
|
||||
|
||||
ACMD(do_map) {
|
||||
if (!can_see_map(ch)) {
|
||||
send_to_char(ch, "Sorry, the map is disabled!\r\n");
|
||||
return;
|
||||
}
|
||||
perform_map(ch, argument, ROOM_FLAGGED(IN_ROOM(ch), ROOM_WORLDMAP) ? 1 : 0 );
|
||||
}
|
||||
|
||||
|
||||
265
src/genqst.c
Normal file
265
src/genqst.c
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
/* ***********************************************************************
|
||||
* File: genqst.c Part of CircleMUD *
|
||||
* Version: 2.0 (November 2005) Written for CircleMud CWG / Suntzu *
|
||||
* Purpose: To provide special quest-related code. *
|
||||
* Copyright: Kenneth Ray *
|
||||
* Original Version Details: *
|
||||
* Copyright 1996 by Harvey Gilpin *
|
||||
* Copyright 1997-2001 by George Greer (greerga@circlemud.org) *
|
||||
************************************************************************ */
|
||||
|
||||
#include "conf.h"
|
||||
#include "sysdep.h"
|
||||
#include "structs.h"
|
||||
#include "utils.h"
|
||||
#include "db.h"
|
||||
#include "quest.h"
|
||||
#include "genolc.h"
|
||||
#include "genzon.h"
|
||||
#include "genzon.h" /* for create_world_index */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
int copy_quest(struct aq_data *to, struct aq_data *from, int free_old_strings)
|
||||
{
|
||||
int i;
|
||||
if (free_old_strings)
|
||||
free_quest_strings(to);
|
||||
to->vnum = from->vnum;
|
||||
to->flags = from->flags;
|
||||
to->type = from->type;
|
||||
to->qm = from->qm;
|
||||
to->target = from->target;
|
||||
to->prereq = from->prereq;
|
||||
to->prev_quest = from->prev_quest;
|
||||
to->next_quest = from->next_quest;
|
||||
for (i = 0; i < 7; i++){
|
||||
to->value[i] = from->value[i];
|
||||
}
|
||||
to->gold_reward = from->gold_reward;
|
||||
to->exp_reward = from->exp_reward;
|
||||
to->obj_reward = from->obj_reward;
|
||||
to->func = from->func;
|
||||
return copy_quest_strings(to, from);
|
||||
}
|
||||
|
||||
int copy_quest_strings(struct aq_data *to, struct aq_data *from)
|
||||
{
|
||||
if (from == NULL || to == NULL) {
|
||||
log("SYSERR: GenQST: copy_quest_strings: Null values passed.");
|
||||
return FALSE;
|
||||
}
|
||||
to->name = str_udup(from->name);
|
||||
to->desc = str_udup(from->desc);
|
||||
to->info = str_udup(from->info);
|
||||
to->done = str_udup(from->done);
|
||||
to->quit = str_udup(from->quit);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void free_quest_strings(struct aq_data *quest)
|
||||
{
|
||||
if (quest->name)
|
||||
free(quest->name);
|
||||
if (quest->desc)
|
||||
free(quest->desc);
|
||||
if (quest->info)
|
||||
free(quest->info);
|
||||
if (quest->done)
|
||||
free(quest->done);
|
||||
if (quest->quit)
|
||||
free(quest->quit);
|
||||
}
|
||||
|
||||
void free_quest(struct aq_data *quest)
|
||||
{
|
||||
free_quest_strings(quest);
|
||||
free(quest);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
int add_quest(struct aq_data *nqst)
|
||||
{
|
||||
qst_rnum rnum;
|
||||
zone_rnum rznum = real_zone_by_thing(nqst->vnum);
|
||||
|
||||
/* The quest already exists, just update it. */
|
||||
if ((rnum = real_quest(nqst->vnum)) != NOWHERE) {
|
||||
copy_quest(&aquest_table[rnum], nqst, TRUE);
|
||||
} else {
|
||||
/* increase the number of quest table entries */
|
||||
total_quests++;
|
||||
RECREATE(aquest_table, struct aq_data, total_quests );
|
||||
/* Initialise top quest strings to null */
|
||||
QST_NAME(total_quests - 1) = NULL;
|
||||
QST_DESC(total_quests - 1) = NULL;
|
||||
QST_INFO(total_quests - 1) = NULL;
|
||||
QST_DONE(total_quests - 1) = NULL;
|
||||
QST_QUIT(total_quests - 1) = NULL;
|
||||
/* Now process enties from the top down to see where the new one goes */
|
||||
for (rnum = total_quests - 1; rnum > 0; rnum--) {
|
||||
if (nqst->vnum > QST_NUM(rnum - 1))
|
||||
break; //found the place
|
||||
aquest_table[rnum] = aquest_table[rnum - 1]; //shift quest up one
|
||||
}
|
||||
copy_quest(&aquest_table[rnum], nqst, FALSE);
|
||||
}
|
||||
/* Make sure we assign spec procs to the questmaster */
|
||||
if (mob_index[QST_MASTER(rnum)].func &&
|
||||
mob_index[QST_MASTER(rnum)].func != questmaster)
|
||||
QST_FUNC(rnum) = mob_index[QST_MASTER(rnum)].func;
|
||||
mob_index[QST_MASTER(rnum)].func = questmaster;
|
||||
|
||||
/* And make sure we save the updated quest information to disk */
|
||||
if (rznum != NOWHERE)
|
||||
add_to_save_list(zone_table[rznum].number, SL_QST);
|
||||
else
|
||||
mudlog(BRF, LVL_BUILDER, TRUE,
|
||||
"SYSERR: GenOLC: Cannot determine quest zone.");
|
||||
|
||||
return rnum;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
int delete_quest(qst_rnum rnum)
|
||||
{
|
||||
qst_rnum i;
|
||||
zone_rnum rznum = real_zone_by_thing(QST_NUM(rnum));
|
||||
mob_rnum qm = QST_MASTER(rnum);
|
||||
SPECIAL (*tempfunc);
|
||||
int quests_remaining = 0;
|
||||
|
||||
if (rnum >= total_quests)
|
||||
return FALSE;
|
||||
log("GenOLC: delete_quest: Deleting quest #%d (%s).",
|
||||
QST_NUM(rnum), QST_NAME(rnum));
|
||||
/* make a note of the quest master's secondary spec proc */
|
||||
tempfunc = QST_FUNC(rnum);
|
||||
|
||||
|
||||
free_quest_strings(&aquest_table[rnum]);
|
||||
for (i = rnum; i < total_quests - 1; i++) {
|
||||
aquest_table[i] = aquest_table[i + 1];
|
||||
}
|
||||
total_quests--;
|
||||
RECREATE(aquest_table, struct aq_data, total_quests);
|
||||
|
||||
if (rznum != NOWHERE)
|
||||
add_to_save_list(zone_table[rznum].number, SL_QST);
|
||||
else
|
||||
mudlog(BRF, LVL_BUILDER, TRUE,
|
||||
"SYSERR: GenOLC: Cannot determine quest zone.");
|
||||
/* does the questmaster mob have any quests left? */
|
||||
if (qm != NOBODY) {
|
||||
for (i = 0; i < total_quests; i++) {
|
||||
if (QST_MASTER(i) == qm)
|
||||
quests_remaining++;
|
||||
}
|
||||
if (quests_remaining == 0)
|
||||
mob_index[qm].func = tempfunc; // point back to original spec proc
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
int save_quests(zone_rnum zone_num)
|
||||
{
|
||||
FILE *sf;
|
||||
char filename[128], oldname[128], quest_flags[MAX_STRING_LENGTH];
|
||||
char quest_desc[MAX_STRING_LENGTH], quest_info[MAX_STRING_LENGTH];
|
||||
char quest_done[MAX_STRING_LENGTH], quest_quit[MAX_STRING_LENGTH];
|
||||
int i, num_quests = 0;
|
||||
|
||||
#if CIRCLE_UNSIGNED_INDEX
|
||||
if (zone_num == NOWHERE || zone_num > top_of_zone_table) {
|
||||
#else
|
||||
if (zone_num < 0 || zone_num > top_of_zone_table) {
|
||||
#endif
|
||||
log("SYSERR: GenOLC: save_quests: Invalid zone number %d passed! (0-%d)",
|
||||
zone_num, top_of_zone_table);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
log("GenOLC: save_quests: Saving quests in zone #%d (%d-%d).",
|
||||
zone_table[zone_num].number,
|
||||
genolc_zone_bottom(zone_num), zone_table[zone_num].top);
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s/%d.new",
|
||||
QST_PREFIX, zone_table[zone_num].number);
|
||||
if (!(sf = fopen(filename, "w"))) {
|
||||
perror("SYSERR: save_quests");
|
||||
return FALSE;
|
||||
}
|
||||
for (i = genolc_zone_bottom(zone_num); i <= zone_table[zone_num].top; i++) {
|
||||
qst_rnum rnum;
|
||||
if ((rnum = real_quest(i)) != NOTHING) {
|
||||
/* Copy the text strings and strip off trailing newlines. */
|
||||
strncpy(quest_desc, QST_DESC(rnum) ? QST_DESC(rnum) : "undefined",
|
||||
sizeof(quest_desc)-1 );
|
||||
strncpy(quest_info, QST_INFO(rnum) ? QST_INFO(rnum) : "undefined",
|
||||
sizeof(quest_info)-1 );
|
||||
strncpy(quest_done, QST_DONE(rnum) ? QST_DONE(rnum) : "undefined",
|
||||
sizeof(quest_done)-1 );
|
||||
strncpy(quest_quit, QST_QUIT(rnum) ? QST_QUIT(rnum) : "undefined",
|
||||
sizeof(quest_quit)-1 );
|
||||
strip_cr(quest_desc);
|
||||
strip_cr(quest_info);
|
||||
strip_cr(quest_done);
|
||||
strip_cr(quest_quit);
|
||||
/* Save the quest details to the file. */
|
||||
sprintascii(quest_flags, QST_FLAGS(rnum));
|
||||
fprintf(sf,
|
||||
"#%d\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n"
|
||||
"%s%c\n"
|
||||
"%d %d %s %d %d %d %d\n"
|
||||
"%d %d %d %d %d %d %d\n"
|
||||
"%d %d %d\n"
|
||||
"S\n",
|
||||
QST_NUM(rnum),
|
||||
QST_NAME(rnum) ? QST_NAME(rnum) : "Untitled", STRING_TERMINATOR,
|
||||
quest_desc, STRING_TERMINATOR,
|
||||
quest_info, STRING_TERMINATOR,
|
||||
quest_done, STRING_TERMINATOR,
|
||||
quest_quit, STRING_TERMINATOR,
|
||||
QST_TYPE(rnum),
|
||||
QST_MASTER(rnum) == NOBODY ? -1 : mob_index[QST_MASTER(rnum)].vnum,
|
||||
quest_flags,
|
||||
QST_TARGET(rnum) == NOTHING ? -1 : QST_TARGET(rnum),
|
||||
QST_PREV(rnum) == NOTHING ? -1 : QST_PREV(rnum),
|
||||
QST_NEXT(rnum) == NOTHING ? -1 : QST_NEXT(rnum),
|
||||
QST_PREREQ(rnum) == NOTHING ? -1 : QST_PREREQ(rnum),
|
||||
QST_POINTS(rnum), QST_PENALTY(rnum), QST_MINLEVEL(rnum),
|
||||
QST_MAXLEVEL(rnum), QST_TIME(rnum),
|
||||
QST_RETURNMOB(rnum) == NOBODY ? -1 : QST_RETURNMOB(rnum),
|
||||
QST_QUANTITY(rnum), QST_GOLD(rnum), QST_EXP(rnum), QST_OBJ(rnum)
|
||||
);
|
||||
num_quests++;
|
||||
}
|
||||
}
|
||||
/* Write the final line and close it. */
|
||||
fprintf(sf, "$~\n");
|
||||
fclose(sf);
|
||||
|
||||
/* Old file we're replacing. */
|
||||
snprintf(oldname, sizeof(oldname), "%s/%d.qst",
|
||||
QST_PREFIX, zone_table[zone_num].number);
|
||||
remove(oldname);
|
||||
rename(filename, oldname);
|
||||
|
||||
/* Do we need to update the index file? */
|
||||
if (num_quests > 0)
|
||||
create_world_index(zone_table[zone_num].number, "qst");
|
||||
|
||||
if (in_save_list(zone_table[zone_num].number, SL_QST))
|
||||
remove_from_save_list(zone_table[zone_num].number, SL_QST);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ void mobile_activity(void)
|
|||
(world[EXIT(ch, door)->to_room].zone == world[IN_ROOM(ch)].zone)))
|
||||
{
|
||||
/* If the mob is charmed, do not move the mob. */
|
||||
if (ch->master != NULL)
|
||||
if (ch->master == NULL)
|
||||
perform_move(ch, door, 1);
|
||||
}
|
||||
|
||||
|
|
|
|||
742
src/qedit.c
Normal file
742
src/qedit.c
Normal file
|
|
@ -0,0 +1,742 @@
|
|||
/* ***********************************************************************
|
||||
* File: qedit.c Part of CircleMUD *
|
||||
* Version: 2.0 (November 2005) Written for CircleMud CWG / Suntzu *
|
||||
* Purpose: To provide special quest-related code. *
|
||||
* Copyright: Kenneth Ray *
|
||||
* *
|
||||
* Made for Oasis OLC *
|
||||
* Copyright 1996 Harvey Gilpin. *
|
||||
*********************************************************************** */
|
||||
|
||||
#include "conf.h"
|
||||
#include "sysdep.h"
|
||||
|
||||
#include "structs.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "comm.h"
|
||||
#include "db.h"
|
||||
#include "oasis.h"
|
||||
#include "improved-edit.h"
|
||||
#include "screen.h"
|
||||
#include "genolc.h"
|
||||
#include "genzon.h"
|
||||
#include "interpreter.h"
|
||||
#include "modify.h"
|
||||
#include "quest.h"
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
/*. Function prototypes . */
|
||||
|
||||
static void qedit_setup_new(struct descriptor_data *d);
|
||||
static void qedit_setup_existing(struct descriptor_data *d, qst_rnum rnum);
|
||||
static void qedit_disp_menu(struct descriptor_data *d);
|
||||
static void qedit_save_internally(struct descriptor_data *d);
|
||||
static void qedit_save_to_disk(int num);
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
static void qedit_save_internally(struct descriptor_data *d)
|
||||
{
|
||||
add_quest(OLC_QUEST(d));
|
||||
}
|
||||
|
||||
static void qedit_save_to_disk(int num)
|
||||
{
|
||||
save_quests(num);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*\
|
||||
utility functions
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
ACMD(do_oasis_qedit)
|
||||
{
|
||||
int save = 0;
|
||||
qst_rnum real_num;
|
||||
qst_vnum number = NOWHERE;
|
||||
struct descriptor_data *d;
|
||||
char *buf3;
|
||||
char buf1[MAX_INPUT_LENGTH];
|
||||
char buf2[MAX_INPUT_LENGTH];
|
||||
|
||||
/****************************************************************************/
|
||||
/** Parse any arguments. **/
|
||||
/****************************************************************************/
|
||||
buf3 = two_arguments(argument, buf1, buf2);
|
||||
|
||||
if (!*buf1) {
|
||||
send_to_char(ch, "Specify a quest VNUM to edit.\r\n");
|
||||
return;
|
||||
} else if (!isdigit(*buf1)) {
|
||||
if (str_cmp("save", buf1) != 0) {
|
||||
send_to_char(ch, "Yikes! Stop that, someone will get hurt!\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
save = TRUE;
|
||||
|
||||
if (is_number(buf2))
|
||||
number = atoi(buf2);
|
||||
else if (GET_OLC_ZONE(ch) > 0) {
|
||||
zone_rnum zlok;
|
||||
|
||||
if ((zlok = real_zone(GET_OLC_ZONE(ch))) == NOWHERE)
|
||||
number = NOWHERE;
|
||||
else
|
||||
number = genolc_zone_bottom(zlok);
|
||||
}
|
||||
|
||||
if (number == NOWHERE) {
|
||||
send_to_char(ch, "Save which zone?\r\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/** If a numeric argument was given, get it. **/
|
||||
/****************************************************************************/
|
||||
if (number == NOWHERE)
|
||||
number = atoi(buf1);
|
||||
|
||||
/****************************************************************************/
|
||||
/** Check that the guild isn't already being edited. **/
|
||||
/****************************************************************************/
|
||||
for (d = descriptor_list; d; d = d->next) {
|
||||
if (STATE(d) == CON_QEDIT) {
|
||||
if (d->olc && OLC_NUM(d) == number) {
|
||||
send_to_char(ch, "That quest is currently being edited by %s.\r\n",
|
||||
PERS(d->character, ch));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/** Point d to the builder's descriptor. **/
|
||||
/****************************************************************************/
|
||||
d = ch->desc;
|
||||
|
||||
/****************************************************************************/
|
||||
/** Give the descriptor an OLC structure. **/
|
||||
/****************************************************************************/
|
||||
if (d->olc) {
|
||||
mudlog(BRF, LVL_IMMORT, TRUE,
|
||||
"SYSERR: do_oasis_quest: Player already had olc structure.");
|
||||
free(d->olc);
|
||||
}
|
||||
|
||||
CREATE(d->olc, struct oasis_olc_data, 1);
|
||||
|
||||
/****************************************************************************/
|
||||
/** Find the zone. **/
|
||||
/****************************************************************************/
|
||||
if ((OLC_ZNUM(d) = real_zone_by_thing(number)) == NOWHERE) {
|
||||
send_to_char(ch, "Sorry, there is no zone for that number!\r\n");
|
||||
free(d->olc);
|
||||
d->olc = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/** Everyone but IMPLs can only edit zones they have been assigned. **/
|
||||
/****************************************************************************/
|
||||
if (!can_edit_zone(ch, OLC_ZNUM(d))) {
|
||||
send_to_char(ch, "You do not have permission to edit this zone.\r\n");
|
||||
|
||||
/**************************************************************************/
|
||||
/** Free the OLC structure. **/
|
||||
/**************************************************************************/
|
||||
free(d->olc);
|
||||
d->olc = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (save) {
|
||||
send_to_char(ch, "Saving all quests in zone %d.\r\n",
|
||||
zone_table[OLC_ZNUM(d)].number);
|
||||
mudlog(CMP, MAX(LVL_BUILDER, GET_INVIS_LEV(ch)), TRUE,
|
||||
"OLC: %s saves quest info for zone %d.",
|
||||
GET_NAME(ch), zone_table[OLC_ZNUM(d)].number);
|
||||
|
||||
/**************************************************************************/
|
||||
/** Save the quest to the quest file. **/
|
||||
/**************************************************************************/
|
||||
qedit_save_to_disk(OLC_ZNUM(d));
|
||||
|
||||
/**************************************************************************/
|
||||
/** Free the OLC structure. **/
|
||||
/**************************************************************************/
|
||||
free(d->olc);
|
||||
d->olc = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
OLC_NUM(d) = number;
|
||||
|
||||
if ((real_num = real_quest(number)) != NOTHING)
|
||||
qedit_setup_existing(d, real_num);
|
||||
else
|
||||
qedit_setup_new(d);
|
||||
|
||||
STATE(d) = CON_QEDIT;
|
||||
|
||||
act("$n starts using OLC.", TRUE, d->character, 0, 0, TO_ROOM);
|
||||
SET_BIT_AR(PLR_FLAGS(ch), PLR_WRITING);
|
||||
|
||||
mudlog(BRF, LVL_IMMORT, TRUE,
|
||||
"OLC: %s starts editing zone %d allowed zone %d",
|
||||
GET_NAME(ch), zone_table[OLC_ZNUM(d)].number, GET_OLC_ZONE(ch));
|
||||
}
|
||||
|
||||
static void qedit_setup_new(struct descriptor_data *d)
|
||||
{
|
||||
struct aq_data *quest;
|
||||
|
||||
/* Allociate some quest shaped space */
|
||||
CREATE(quest, struct aq_data, 1);
|
||||
/* Set default values */
|
||||
quest->vnum = OLC_NUM(d); /* Quest vnum */
|
||||
quest->qm = NOBODY; /* Questmaster rnum */
|
||||
quest->flags = 0; /* Quest bitflags */
|
||||
quest->type = AQ_UNDEFINED; /* Quest type */
|
||||
quest->target = NOTHING; /* Quest target */
|
||||
quest->prereq = NOTHING; /* Prerequisite object */
|
||||
quest->value[0] = 0; /* Points for completing */
|
||||
quest->value[1] = 0; /* Points for abandoning */
|
||||
quest->value[2] = 0; /* Minimum level */
|
||||
quest->value[3] = LVL_IMPL; /* Maximim level */
|
||||
quest->value[4] = -1; /* Time limit */
|
||||
quest->value[5] = NOBODY; /* Mob to return object */
|
||||
quest->value[6] = 1; /* Quantity of targets */
|
||||
quest->prev_quest = NOTHING; /* Previous quest */
|
||||
quest->next_quest = NOTHING; /* Next quest */
|
||||
quest->gold_reward= 0; /* Prize in gold coins */
|
||||
quest->exp_reward = 0; /* Prize in exp points */
|
||||
quest->obj_reward = NOTHING; /* vnum of reward object */
|
||||
quest->name = strdup("Undefined Quest");
|
||||
quest->desc = strdup("Quest definition is incomplete.");
|
||||
quest->info = strdup("There is no information on this quest.\r\n");
|
||||
quest->done = strdup("You have completed the quest.\r\n");
|
||||
quest->quit = strdup("You have abandoned the quest.\r\n");
|
||||
quest->func = NULL; /* Secondary qm spec proc */
|
||||
/* Set the descriptor OLC structure to point to this quest */
|
||||
OLC_QUEST(d) = quest;
|
||||
/* Show the main quest edit menu */
|
||||
qedit_disp_menu(d);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
static void qedit_setup_existing(struct descriptor_data *d, qst_rnum r_num)
|
||||
{
|
||||
/*. Alloc some quest shaped space . */
|
||||
CREATE(OLC_QUEST(d), struct aq_data, 1);
|
||||
copy_quest(OLC_QUEST(d), aquest_table + r_num, FALSE);
|
||||
qedit_disp_menu(d);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
/**************************************************************************
|
||||
Menu functions
|
||||
**************************************************************************/
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
/*. Display main menu . */
|
||||
|
||||
static void qedit_disp_menu(struct descriptor_data *d)
|
||||
{
|
||||
struct aq_data *quest;
|
||||
char quest_flags[MAX_STRING_LENGTH], buf2[MAX_STRING_LENGTH];
|
||||
char targetname[MAX_STRING_LENGTH];
|
||||
mob_vnum return_mob;
|
||||
|
||||
quest = OLC_QUEST(d);
|
||||
|
||||
clear_screen(d);
|
||||
sprintbit(quest->flags, aq_flags, quest_flags, sizeof(quest_flags));
|
||||
if (quest->type == AQ_OBJ_RETURN) {
|
||||
if ((return_mob = real_mobile(quest->value[5])) != NOBODY)
|
||||
snprintf(buf2, sizeof(buf2), "to %s [%d]",
|
||||
mob_proto[return_mob].player.short_descr,
|
||||
quest->value[5]);
|
||||
else
|
||||
snprintf(buf2, sizeof(buf2), "to an unknown mob [%d].",
|
||||
quest->value[5]);
|
||||
}
|
||||
switch (quest->type) {
|
||||
case AQ_OBJ_FIND:
|
||||
case AQ_OBJ_RETURN:
|
||||
snprintf(targetname, sizeof(targetname), "%s",
|
||||
real_object(quest->target) == NOTHING ?
|
||||
"An unknown object" :
|
||||
obj_proto[real_object(quest->target)].short_description);
|
||||
break;
|
||||
case AQ_ROOM_FIND:
|
||||
case AQ_ROOM_CLEAR:
|
||||
snprintf(targetname, sizeof(targetname), "%s",
|
||||
real_room(quest->target) == NOWHERE ?
|
||||
"An unknown room" :
|
||||
world[real_room(quest->target)].name);
|
||||
break;
|
||||
case AQ_MOB_FIND:
|
||||
case AQ_MOB_KILL:
|
||||
case AQ_MOB_SAVE:
|
||||
snprintf(targetname, sizeof(targetname), "%s",
|
||||
real_mobile(quest->target) == NOBODY ?
|
||||
"An unknown mobile" :
|
||||
GET_NAME(&mob_proto[real_mobile(quest->target)]));
|
||||
break;
|
||||
default:
|
||||
snprintf(targetname, sizeof(targetname), "Unknown");
|
||||
break;
|
||||
}
|
||||
write_to_output(d,
|
||||
"-- Quest Number : @n[@c%6d@n]\r\n"
|
||||
"@g 1@n) Quest Name : @y%s\r\n"
|
||||
"@g 2@n) Description : @y%s\r\n"
|
||||
"@g 3@n) Accept Message\r\n@y%s"
|
||||
"@g 4@n) Completion Message\r\n@y%s"
|
||||
"@g 5@n) Quit Message\r\n@y%s"
|
||||
"@g 6@n) Quest Flags : @c%s\r\n"
|
||||
"@g 7@n) Quest Type : @c%s %s\r\n"
|
||||
"@g 8@n) Quest Master : [@c%6d@n] @y%s\r\n"
|
||||
"@g 9@n) Quest Target : [@c%6d@n] @y%s\r\n"
|
||||
"@g A@n) Quantity : [@c%6d@n]\r\n"
|
||||
"@n Quest Point Rewards\r\n"
|
||||
"@g B@n) Completed : [@c%6d@n] @g C@n) Abandoned : [@c%6d@n]\r\n"
|
||||
"@n Other Rewards Rewards\r\n"
|
||||
"@g G@n) Gold Coins : [@c%6d@n] @g T@n) Exp Points : [@c%6d@n] @g O@n) Object : [@c%6d@n]\r\n"
|
||||
"@n Level Limits to Accept Quest\r\n"
|
||||
"@g D@n) Lower Level : [@c%6d@n] @g E@n) Upper Level : [@c%6d@n]\r\n"
|
||||
"@g F@n) Prerequisite : [@c%6d@n] @y%s\r\n"
|
||||
"@g L@n) Time Limit : [@c%6d@n]\r\n"
|
||||
"@g N@n) Next Quest : [@c%6d@n] @y%s\r\n"
|
||||
"@g P@n) Previous Quest : [@c%6d@n] @y%s\r\n"
|
||||
"@g X@n) Delete Quest\r\n"
|
||||
"@g Q@n) Quit\r\n"
|
||||
"Enter Choice : ",
|
||||
quest->vnum,
|
||||
quest->name,
|
||||
quest->desc,
|
||||
quest->info && (str_cmp(quest->info, "undefined"))
|
||||
? quest->info : "Nothing\r\n",
|
||||
quest->done && (str_cmp(quest->done, "undefined"))
|
||||
? quest->done : "Nothing\r\n",
|
||||
quest->quit && (str_cmp(quest->quit, "undefined"))
|
||||
? quest->quit : "Nothing\r\n",
|
||||
quest_flags,
|
||||
quest_types[quest->type],
|
||||
quest->type == AQ_OBJ_RETURN ? buf2 : "",
|
||||
quest->qm == NOBODY ? -1 : mob_index[quest->qm].vnum,
|
||||
quest->qm == NOBODY ? "none" : mob_proto[quest->qm].player.short_descr,
|
||||
quest->target == NOBODY ? -1 : quest->target, targetname,
|
||||
quest->value[6],
|
||||
quest->value[0], quest->value[1],
|
||||
quest->gold_reward, quest->exp_reward, quest->obj_reward == NOTHING ? -1 : quest->obj_reward,
|
||||
quest->value[2], quest->value[3],
|
||||
quest->prereq == NOTHING ? -1 : quest->prereq,
|
||||
quest->prereq == NOTHING ? "" :
|
||||
real_object(quest->prereq) == NOTHING ? "an unknown object" :
|
||||
obj_proto[real_object(quest->prereq)].short_description,
|
||||
quest->value[4],
|
||||
quest->next_quest == NOTHING ? -1 : quest->next_quest,
|
||||
quest->next_quest == NOTHING ? "" : QST_DESC(real_quest(quest->next_quest)),
|
||||
quest->prev_quest == NOTHING ? -1 : quest->prev_quest,
|
||||
quest->prev_quest == NOTHING ? "" : QST_DESC(real_quest(quest->prev_quest))
|
||||
);
|
||||
OLC_MODE(d) = QEDIT_MAIN_MENU;
|
||||
}
|
||||
/* For sector type. */
|
||||
void qedit_disp_type_menu(struct descriptor_data *d)
|
||||
{
|
||||
int counter, columns = 0;
|
||||
|
||||
clear_screen(d);
|
||||
for (counter = 0; counter < NUM_AQ_TYPES; counter++) {
|
||||
write_to_output(d, "@g%2d@n) %-20.20s %s", counter,
|
||||
quest_types[counter], !(++columns % 2) ? "\r\n" : "");
|
||||
}
|
||||
write_to_output(d, "\r\nEnter Quest type : ");
|
||||
OLC_MODE(d) = QEDIT_TYPES;
|
||||
}
|
||||
/* For quest flags. */
|
||||
void qedit_disp_flag_menu(struct descriptor_data *d)
|
||||
{
|
||||
char bits[MAX_STRING_LENGTH];
|
||||
int counter, columns = 0;
|
||||
|
||||
get_char_colors(d->character);
|
||||
clear_screen(d);
|
||||
for (counter = 0; counter < NUM_AQ_FLAGS; counter++) {
|
||||
write_to_output(d, "%s%2d%s) %-20.20s %s", grn, counter + 1, nrm,
|
||||
aq_flags[counter], !(++columns % 2) ? "\r\n" : "");
|
||||
}
|
||||
sprintbit(OLC_QUEST(d)->flags, aq_flags, bits, sizeof(bits));
|
||||
write_to_output(d, "\r\nQuest flags: @c%s@n\r\n"
|
||||
"Enter quest flags, 0 to quit : ", bits);
|
||||
OLC_MODE(d) = QEDIT_FLAGS;
|
||||
}
|
||||
/**************************************************************************
|
||||
The GARGANTUAN event handler
|
||||
**************************************************************************/
|
||||
|
||||
void qedit_parse(struct descriptor_data *d, char *arg)
|
||||
{
|
||||
int number = atoi(arg);
|
||||
char *oldtext = NULL;
|
||||
|
||||
switch (OLC_MODE(d)) {
|
||||
/*-------------------------------------------------------------------*/
|
||||
case QEDIT_CONFIRM_SAVESTRING:
|
||||
switch (*arg) {
|
||||
case 'y':
|
||||
case 'Y':
|
||||
send_to_char(d->character, "Saving Quest to memory.\r\n");
|
||||
qedit_save_internally(d);
|
||||
mudlog(CMP, MAX(LVL_BUILDER, GET_INVIS_LEV(d->character)), TRUE,
|
||||
"OLC: %s edits quest %d", GET_NAME(d->character), OLC_NUM(d));
|
||||
if (CONFIG_OLC_SAVE) {
|
||||
qedit_save_to_disk(real_zone_by_thing(OLC_NUM(d)));
|
||||
write_to_output(d, "Quest %d saved to disk.\r\n", OLC_NUM(d));
|
||||
} else
|
||||
write_to_output(d, "Quest %d saved to memory.\r\n", OLC_NUM(d));
|
||||
cleanup_olc(d, CLEANUP_STRUCTS);
|
||||
return;
|
||||
case 'n':
|
||||
case 'N':
|
||||
cleanup_olc(d, CLEANUP_ALL);
|
||||
return;
|
||||
default:
|
||||
write_to_output(d,
|
||||
"Invalid choice!\r\nDo you wish to save the quest? : ");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
/*-------------------------------------------------------------------*/
|
||||
case QEDIT_CONFIRM_DELETE:
|
||||
switch (*arg) {
|
||||
case 'y':
|
||||
case 'Y':
|
||||
if (delete_quest(real_quest(OLC_NUM(d))))
|
||||
write_to_output(d, "Quest deleted.\r\n");
|
||||
else
|
||||
write_to_output(d, "Couldn't delete the quest!\r\n");
|
||||
if (CONFIG_OLC_SAVE) {
|
||||
qedit_save_to_disk(real_zone_by_thing(OLC_NUM(d)));
|
||||
write_to_output(d, "Quest file saved to disk.\r\n");
|
||||
} else
|
||||
write_to_output(d, "Quest file saved to memory.\r\n");
|
||||
cleanup_olc(d, CLEANUP_ALL);
|
||||
return;
|
||||
case 'n':
|
||||
case 'N':
|
||||
qedit_disp_menu(d);
|
||||
return;
|
||||
default:
|
||||
write_to_output(d,
|
||||
"Invalid choice!\r\nDo you wish to delete the quest? : ");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
case QEDIT_MAIN_MENU:
|
||||
switch (*arg) {
|
||||
case 'q':
|
||||
case 'Q':
|
||||
if (OLC_VAL(d)) { /*. Anything been changed? . */
|
||||
write_to_output(d,
|
||||
"Do you wish to save the changes to the Quest? (y/n) : ");
|
||||
OLC_MODE(d) = QEDIT_CONFIRM_SAVESTRING;
|
||||
} else
|
||||
cleanup_olc(d, CLEANUP_ALL);
|
||||
return;
|
||||
case 'x':
|
||||
case 'X':
|
||||
OLC_MODE(d) = QEDIT_CONFIRM_DELETE;
|
||||
write_to_output(d, "Do you wish to delete the Quest? (y/n) : ");
|
||||
break;
|
||||
case '1':
|
||||
OLC_MODE(d) = QEDIT_NAME;
|
||||
write_to_output(d, "Enter the quest name : ");
|
||||
break;
|
||||
case '2':
|
||||
OLC_MODE(d) = QEDIT_DESC;
|
||||
write_to_output(d, "Enter the quest description :-\r\n] ");
|
||||
break;
|
||||
case '3':
|
||||
OLC_MODE(d) = QEDIT_INFO;
|
||||
clear_screen(d);
|
||||
send_editor_help(d);
|
||||
write_to_output(d, "Enter quest acceptance message:\r\n\r\n");
|
||||
|
||||
if (OLC_QUEST(d)->info) {
|
||||
write_to_output(d, "%s", OLC_QUEST(d)->info);
|
||||
oldtext = strdup(OLC_QUEST(d)->info);
|
||||
}
|
||||
string_write(d, &OLC_QUEST(d)->info, MAX_QUEST_MSG, 0, oldtext);
|
||||
OLC_VAL(d) = 1;
|
||||
break;
|
||||
case '4':
|
||||
OLC_MODE(d) = QEDIT_COMPLETE;
|
||||
clear_screen(d);
|
||||
send_editor_help(d);
|
||||
write_to_output(d, "Enter quest completion message:\r\n\r\n");
|
||||
|
||||
if (OLC_QUEST(d)->done) {
|
||||
write_to_output(d, "%s", OLC_QUEST(d)->done);
|
||||
oldtext = strdup(OLC_QUEST(d)->done);
|
||||
}
|
||||
string_write(d, &OLC_QUEST(d)->done, MAX_QUEST_MSG, 0, oldtext);
|
||||
OLC_VAL(d) = 1;
|
||||
break;
|
||||
case '5':
|
||||
OLC_MODE(d) = QEDIT_ABANDON;
|
||||
clear_screen(d);
|
||||
send_editor_help(d);
|
||||
write_to_output(d, "Enter quest quit message:\r\n\r\n");
|
||||
|
||||
if (OLC_QUEST(d)->quit) {
|
||||
write_to_output(d, "%s", OLC_QUEST(d)->quit);
|
||||
oldtext = strdup(OLC_QUEST(d)->quit);
|
||||
}
|
||||
string_write(d, &OLC_QUEST(d)->quit, MAX_QUEST_MSG, 0, oldtext);
|
||||
OLC_VAL(d) = 1;
|
||||
break;
|
||||
case '6':
|
||||
OLC_MODE(d) = QEDIT_FLAGS;
|
||||
qedit_disp_flag_menu(d);
|
||||
break;
|
||||
case '7':
|
||||
OLC_MODE(d) = QEDIT_TYPES;
|
||||
qedit_disp_type_menu(d);
|
||||
break;
|
||||
case '8':
|
||||
OLC_MODE(d) = QEDIT_QUESTMASTER;
|
||||
write_to_output(d, "Enter vnum of quest master : ");
|
||||
break;
|
||||
case '9':
|
||||
OLC_MODE(d) = QEDIT_TARGET;
|
||||
write_to_output(d, "Enter target vnum : ");
|
||||
break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
OLC_MODE(d) = QEDIT_QUANTITY;
|
||||
write_to_output(d, "Enter quantity of target : ");
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
OLC_MODE(d) = QEDIT_POINTSCOMP;
|
||||
write_to_output(d, "Enter points for completing the quest : " );
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
OLC_MODE(d) = QEDIT_POINTSQUIT;
|
||||
write_to_output(d, "Enter points for quitting the quest : " );
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
OLC_MODE(d) = QEDIT_LEVELMIN;
|
||||
write_to_output(d, "Enter minimum level to accept the quest : " );
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
OLC_MODE(d) = QEDIT_LEVELMAX;
|
||||
write_to_output(d, "Enter maximum level to accept the quest : " );
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
OLC_MODE(d) = QEDIT_PREREQ;
|
||||
write_to_output(d, "Enter a prerequisite object vnum (-1 for none) : ");
|
||||
break;
|
||||
case 'g':
|
||||
case 'G':
|
||||
OLC_MODE(d) = QEDIT_GOLD;
|
||||
write_to_output(d, "Enter the number of gold coins (0 for none) : ");
|
||||
break;
|
||||
case 't':
|
||||
case 'T':
|
||||
OLC_MODE(d) = QEDIT_EXP;
|
||||
write_to_output(d, "Enter a number of experience points (0 for none) : ");
|
||||
break;
|
||||
case 'o':
|
||||
case 'O':
|
||||
OLC_MODE(d) = QEDIT_OBJ;
|
||||
write_to_output(d, "Enter the prize object vnum (-1 for none) : ");
|
||||
break;
|
||||
case 'l':
|
||||
case 'L':
|
||||
OLC_MODE(d) = QEDIT_TIMELIMIT;
|
||||
write_to_output(d, "Enter time limit to complete (-1 for none) : " );
|
||||
break;
|
||||
case 'n':
|
||||
case 'N':
|
||||
OLC_MODE(d) = QEDIT_NEXTQUEST;
|
||||
write_to_output(d, "Enter vnum of next quest (-1 for none) : ");
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
OLC_MODE(d) = QEDIT_PREVQUEST;
|
||||
write_to_output(d, "Enter vnum of previous quest (-1 for none) : ");
|
||||
break;
|
||||
default:
|
||||
write_to_output(d, "Invalid choice!\r\n");
|
||||
qedit_disp_menu(d);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
/*-------------------------------------------------------------------*/
|
||||
case QEDIT_NAME:
|
||||
if (!genolc_checkstring(d, arg))
|
||||
break;
|
||||
if (OLC_QUEST(d)->name)
|
||||
free(OLC_QUEST(d)->name);
|
||||
arg[MAX_QUEST_NAME - 1] = '\0';
|
||||
OLC_QUEST(d)->name = str_udup(arg);
|
||||
break;
|
||||
case QEDIT_DESC:
|
||||
if (!genolc_checkstring(d, arg))
|
||||
break;
|
||||
if (OLC_QUEST(d)->desc)
|
||||
free(OLC_QUEST(d)->desc);
|
||||
arg[MAX_QUEST_DESC - 1] = '\0';
|
||||
OLC_QUEST(d)->desc = str_udup(arg);
|
||||
break;
|
||||
case QEDIT_QUESTMASTER:
|
||||
if (number != -1)
|
||||
if ((number = real_mobile(number)) == NOBODY) {
|
||||
write_to_output(d, "That mobile does not exist, try again : ");
|
||||
return;
|
||||
}
|
||||
OLC_QUEST(d)->qm = number;
|
||||
break;
|
||||
case QEDIT_TYPES:
|
||||
if (number < 0 || number >= NUM_AQ_TYPES) {
|
||||
write_to_output(d, "Invalid choice!\r\n");
|
||||
qedit_disp_type_menu(d);
|
||||
return;
|
||||
}
|
||||
OLC_QUEST(d)->type = number;
|
||||
if (number == AQ_OBJ_RETURN) {
|
||||
OLC_MODE(d) = QEDIT_RETURNMOB;
|
||||
write_to_output(d, "Enter mob vnum to return object to : ");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case QEDIT_FLAGS:
|
||||
if (number < 0 || number > NUM_AQ_FLAGS) {
|
||||
write_to_output(d, "That is not a valid choice!\r\n");
|
||||
qedit_disp_flag_menu(d);
|
||||
} else if (number == 0)
|
||||
break;
|
||||
else {
|
||||
TOGGLE_BIT(OLC_QUEST(d)->flags, number );
|
||||
qedit_disp_flag_menu(d);
|
||||
}
|
||||
return;
|
||||
case QEDIT_QUANTITY:
|
||||
OLC_QUEST(d)->value[6] = LIMIT(number, 1, 50);
|
||||
break;
|
||||
case QEDIT_POINTSCOMP:
|
||||
OLC_QUEST(d)->value[0] = LIMIT(number, 0, 999999);
|
||||
break;
|
||||
case QEDIT_POINTSQUIT:
|
||||
OLC_QUEST(d)->value[1] = LIMIT(number, 0, 999999);
|
||||
break;
|
||||
case QEDIT_PREREQ:
|
||||
if ((number = atoi(arg)) != -1)
|
||||
if (real_object(number) == NOTHING) {
|
||||
write_to_output(d, "That object does not exist, try again : ");
|
||||
return;
|
||||
}
|
||||
OLC_QUEST(d)->prereq = number;
|
||||
break;
|
||||
case QEDIT_LEVELMIN:
|
||||
if (number < 0 || number > LVL_IMPL) {
|
||||
write_to_output(d, "Level must be between 0 and %d!\r\n", LVL_IMPL);
|
||||
write_to_output(d, "Enter minimum level to accept the quest : " );
|
||||
return;
|
||||
} else if (number > OLC_QUEST(d)->value[3]) {
|
||||
write_to_output(d, "Minimum level can't be above maximum level!\r\n");
|
||||
write_to_output(d, "Enter minimum level to accept the quest : " );
|
||||
return;
|
||||
} else {
|
||||
OLC_QUEST(d)->value[2] = number;
|
||||
break;
|
||||
}
|
||||
case QEDIT_LEVELMAX:
|
||||
if (number < 0 || number > LVL_IMPL) {
|
||||
write_to_output(d, "Level must be between 0 and %d!\r\n", LVL_IMPL);
|
||||
write_to_output(d, "Enter maximum level to accept the quest : " );
|
||||
return;
|
||||
} else if (number < OLC_QUEST(d)->value[2]) {
|
||||
write_to_output(d, "Maximum level can't be below minimum level!\r\n");
|
||||
write_to_output(d, "Enter maximum level to accept the quest : " );
|
||||
return;
|
||||
} else {
|
||||
OLC_QUEST(d)->value[3] = number;
|
||||
break;
|
||||
}
|
||||
case QEDIT_TIMELIMIT:
|
||||
OLC_QUEST(d)->value[4] = LIMIT(number, -1, 100);
|
||||
break;
|
||||
case QEDIT_RETURNMOB:
|
||||
if ((number = atoi(arg)) != -1)
|
||||
if (real_mobile(number) == NOBODY) {
|
||||
write_to_output(d, "That mobile does not exist, try again : ");
|
||||
return;
|
||||
}
|
||||
OLC_QUEST(d)->value[5] = number;
|
||||
break;
|
||||
case QEDIT_TARGET:
|
||||
OLC_QUEST(d)->target = number;
|
||||
break;
|
||||
case QEDIT_NEXTQUEST:
|
||||
OLC_QUEST(d)->next_quest = (number == -1 ? NOTHING : atoi(arg));
|
||||
break;
|
||||
case QEDIT_PREVQUEST:
|
||||
OLC_QUEST(d)->prev_quest = (number == -1 ? NOTHING : atoi(arg));
|
||||
break;
|
||||
case QEDIT_GOLD:
|
||||
OLC_QUEST(d)->gold_reward = LIMIT(number, 0, 99999);
|
||||
break;
|
||||
case QEDIT_EXP:
|
||||
OLC_QUEST(d)->exp_reward = LIMIT(number, 0, 99999);
|
||||
break;
|
||||
case QEDIT_OBJ:
|
||||
if ((number = atoi(arg)) != -1)
|
||||
if (real_object(number) == NOTHING) {
|
||||
write_to_output(d, "That object does not exist, try again : ");
|
||||
return;
|
||||
}
|
||||
OLC_QUEST(d)->obj_reward = number;
|
||||
break;
|
||||
default:
|
||||
/*. We should never get here . */
|
||||
cleanup_olc(d, CLEANUP_ALL);
|
||||
mudlog(BRF, LVL_BUILDER, TRUE, "SYSERR: OLC: qedit_parse(): "
|
||||
"Reached default case!");
|
||||
write_to_output(d, "Oops...\r\n");
|
||||
break;
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
/*. END OF CASE
|
||||
If we get here, we have probably changed something, and now want to
|
||||
return to main menu. Use OLC_VAL as a 'has changed' flag . */
|
||||
|
||||
OLC_VAL(d) = 1;
|
||||
qedit_disp_menu(d);
|
||||
}
|
||||
|
||||
void qedit_string_cleanup(struct descriptor_data *d, int terminator)
|
||||
{
|
||||
switch (OLC_MODE(d)) {
|
||||
case QEDIT_INFO:
|
||||
case QEDIT_COMPLETE:
|
||||
case QEDIT_ABANDON:
|
||||
qedit_disp_menu(d);
|
||||
break;
|
||||
}
|
||||
}
|
||||
805
src/quest.c
Normal file
805
src/quest.c
Normal file
|
|
@ -0,0 +1,805 @@
|
|||
/* ***********************************************************************
|
||||
* File: quest.c Part of CircleMUD *
|
||||
* Version: 2.1 (December 2005) Written for CircleMud CWG / Suntzu *
|
||||
* Purpose: To provide special quest-related code. *
|
||||
* Copyright: Kenneth Ray *
|
||||
* Original Version Details: *
|
||||
* Morgaelin - quest.c *
|
||||
* Copyright (C) 1997 MS *
|
||||
*********************************************************************** */
|
||||
|
||||
#define __QUEST_C__
|
||||
|
||||
#include "conf.h"
|
||||
#include "sysdep.h"
|
||||
|
||||
#include "structs.h"
|
||||
#include "utils.h"
|
||||
#include "interpreter.h"
|
||||
#include "handler.h"
|
||||
#include "db.h"
|
||||
#include "comm.h"
|
||||
#include "screen.h"
|
||||
#include "quest.h"
|
||||
#include "act.h" /* for do_tell */
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* Exported global variables
|
||||
*--------------------------------------------------------------------------*/
|
||||
const char *quest_types[] = {
|
||||
"Object",
|
||||
"Room",
|
||||
"Find mob",
|
||||
"Kill mob",
|
||||
"Save mob",
|
||||
"Return object",
|
||||
"Clear room",
|
||||
"\n"
|
||||
};
|
||||
const char *aq_flags[] = {
|
||||
"REPEATABLE",
|
||||
"\n"
|
||||
};
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* Local (file scope) global variables
|
||||
*--------------------------------------------------------------------------*/
|
||||
static int cmd_tell;
|
||||
|
||||
static const char *quest_cmd[] = {
|
||||
"list", "history", "join", "leave", "progress", "status", "\n"};
|
||||
|
||||
static const char *quest_mort_usage =
|
||||
"Usage: quest list | history | progress | join <nn> | leave";
|
||||
|
||||
static const char *quest_imm_usage =
|
||||
"Usage: quest list | history | progress | join <nn> | leave | status <vnum>";
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Utility Functions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
qst_rnum real_quest(qst_vnum vnum)
|
||||
{
|
||||
int rnum;
|
||||
|
||||
for (rnum = 0; rnum < total_quests; rnum++)
|
||||
if (QST_NUM(rnum) == vnum)
|
||||
return(rnum);
|
||||
return(NOTHING);
|
||||
}
|
||||
|
||||
int is_complete(struct char_data *ch, qst_vnum vnum)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < GET_NUM_QUESTS(ch); i++)
|
||||
if (ch->player_specials->saved.completed_quests[i] == vnum)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
qst_vnum find_quest_by_qmnum(struct char_data *ch, mob_rnum qm, int num)
|
||||
{
|
||||
qst_rnum rnum;
|
||||
int found=0;
|
||||
for (rnum = 0; rnum < total_quests; rnum++) {
|
||||
if (qm == QST_MASTER(rnum))
|
||||
if (++found == num)
|
||||
return (QST_NUM(rnum));
|
||||
}
|
||||
return NOTHING;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Quest Loading and Unloading Functions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void destroy_quests(void)
|
||||
{
|
||||
qst_rnum rnum = 0;
|
||||
|
||||
if (!aquest_table)
|
||||
return;
|
||||
|
||||
for (rnum = 0; rnum < total_quests; rnum++){
|
||||
free_quest_strings(&aquest_table[rnum]);
|
||||
}
|
||||
free(aquest_table);
|
||||
aquest_table = NULL;
|
||||
total_quests = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int count_quests(qst_vnum low, qst_vnum high)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = j = 0; QST_NUM(i) <= high; i++)
|
||||
if (QST_NUM(i) >= low)
|
||||
j++;
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
void parse_quest(FILE *quest_f, int nr)
|
||||
{
|
||||
static char line[256];
|
||||
static int i = 0, j;
|
||||
int retval = 0, t[7];
|
||||
char f1[128], buf2[MAX_STRING_LENGTH];
|
||||
aquest_table[i].vnum = nr;
|
||||
aquest_table[i].qm = NOBODY;
|
||||
aquest_table[i].name = NULL;
|
||||
aquest_table[i].desc = NULL;
|
||||
aquest_table[i].info = NULL;
|
||||
aquest_table[i].done = NULL;
|
||||
aquest_table[i].quit = NULL;
|
||||
aquest_table[i].flags = 0;
|
||||
aquest_table[i].type = -1;
|
||||
aquest_table[i].target = -1;
|
||||
aquest_table[i].prereq = NOTHING;
|
||||
for (j = 0; j < 7; j++)
|
||||
aquest_table[i].value[j] = 0;
|
||||
aquest_table[i].prev_quest = NOTHING;
|
||||
aquest_table[i].next_quest = NOTHING;
|
||||
aquest_table[i].func = NULL;
|
||||
|
||||
aquest_table[i].gold_reward = 0;
|
||||
aquest_table[i].exp_reward = 0;
|
||||
aquest_table[i].obj_reward = NOTHING;
|
||||
|
||||
/* begin to parse the data */
|
||||
aquest_table[i].name = fread_string(quest_f, buf2);
|
||||
aquest_table[i].desc = fread_string(quest_f, buf2);
|
||||
aquest_table[i].info = fread_string(quest_f, buf2);
|
||||
aquest_table[i].done = fread_string(quest_f, buf2);
|
||||
aquest_table[i].quit = fread_string(quest_f, buf2);
|
||||
if (!get_line(quest_f, line) ||
|
||||
(retval = sscanf(line, " %d %d %s %d %d %d %d",
|
||||
t, t+1, f1, t+2, t+3, t + 4, t + 5)) != 7) {
|
||||
log("Format error in numeric line (expected 7, got %d), %s\n",
|
||||
retval, line);
|
||||
exit(1);
|
||||
}
|
||||
aquest_table[i].type = t[0];
|
||||
aquest_table[i].qm = real_mobile(t[1]);
|
||||
aquest_table[i].flags = asciiflag_conv(f1);
|
||||
aquest_table[i].target = (t[2] == -1) ? NOTHING : t[2];
|
||||
aquest_table[i].prev_quest = (t[3] == -1) ? NOTHING : t[3];
|
||||
aquest_table[i].next_quest = (t[4] == -1) ? NOTHING : t[4];
|
||||
aquest_table[i].prereq = (t[5] == -1) ? NOTHING : t[5];
|
||||
if (!get_line(quest_f, line) ||
|
||||
(retval = sscanf(line, " %d %d %d %d %d %d %d",
|
||||
t, t+1, t+2, t+3, t+4, t + 5, t + 6)) != 7) {
|
||||
log("Format error in numeric line (expected 7, got %d), %s\n",
|
||||
retval, line);
|
||||
exit(1);
|
||||
}
|
||||
for (j = 0; j < 7; j++)
|
||||
aquest_table[i].value[j] = t[j];
|
||||
|
||||
if (!get_line(quest_f, line) ||
|
||||
(retval = sscanf(line, " %d %d %d",
|
||||
t, t+1, t+2)) != 3) {
|
||||
log("Format error in numeric (rewards) line (expected 3, got %d), %s\n",
|
||||
retval, line);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
aquest_table[i].gold_reward = t[0];
|
||||
aquest_table[i].exp_reward = t[1];
|
||||
aquest_table[i].obj_reward = (t[2] == -1) ? NOTHING : t[2];
|
||||
|
||||
for (;;) {
|
||||
if (!get_line(quest_f, line)) {
|
||||
log("Format error in %s\n", line);
|
||||
exit(1);
|
||||
}
|
||||
switch(*line) {
|
||||
case 'S':
|
||||
total_quests = ++i;
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* parse_quest */
|
||||
|
||||
void assign_the_quests(void)
|
||||
{
|
||||
qst_rnum rnum;
|
||||
|
||||
cmd_tell = find_command("tell");
|
||||
|
||||
for (rnum = 0; rnum < total_quests; rnum ++) {
|
||||
if (QST_MASTER(rnum) == NOBODY) {
|
||||
log("SYSERR: Quest #%d has no questmaster specified.", QST_NUM(rnum));
|
||||
continue;
|
||||
}
|
||||
if (mob_index[QST_MASTER(rnum)].func &&
|
||||
mob_index[QST_MASTER(rnum)].func != questmaster)
|
||||
QST_FUNC(rnum) = mob_index[QST_MASTER(rnum)].func;
|
||||
mob_index[QST_MASTER(rnum)].func = questmaster;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Quest Completion Functions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void set_quest(struct char_data *ch, qst_rnum rnum)
|
||||
{
|
||||
GET_QUEST(ch) = QST_NUM(rnum);
|
||||
GET_QUEST_TIME(ch) = QST_TIME(rnum);
|
||||
GET_QUEST_COUNTER(ch) = QST_QUANTITY(rnum);
|
||||
SET_BIT_AR(PRF_FLAGS(ch), PRF_QUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
void clear_quest(struct char_data *ch)
|
||||
{
|
||||
GET_QUEST(ch) = NOTHING;
|
||||
GET_QUEST_TIME(ch) = -1;
|
||||
GET_QUEST_COUNTER(ch) = 0;
|
||||
REMOVE_BIT_AR(PRF_FLAGS(ch), PRF_QUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
void add_completed_quest(struct char_data *ch, qst_vnum vnum)
|
||||
{
|
||||
qst_vnum *temp;
|
||||
int i;
|
||||
|
||||
CREATE(temp, qst_vnum, GET_NUM_QUESTS(ch) +1);
|
||||
for (i=0; i < GET_NUM_QUESTS(ch); i++)
|
||||
temp[i] = ch->player_specials->saved.completed_quests[i];
|
||||
|
||||
temp[GET_NUM_QUESTS(ch)] = vnum;
|
||||
GET_NUM_QUESTS(ch)++;
|
||||
|
||||
if (ch->player_specials->saved.completed_quests)
|
||||
free(ch->player_specials->saved.completed_quests);
|
||||
ch->player_specials->saved.completed_quests = temp;
|
||||
}
|
||||
|
||||
void remove_completed_quest(struct char_data *ch, qst_vnum vnum)
|
||||
{
|
||||
qst_vnum *temp;
|
||||
int i, j = 0;
|
||||
|
||||
CREATE(temp, qst_vnum, GET_NUM_QUESTS(ch));
|
||||
for (i = 0; i < GET_NUM_QUESTS(ch); i++)
|
||||
if (ch->player_specials->saved.completed_quests[i] != vnum)
|
||||
temp[j++] = ch->player_specials->saved.completed_quests[i];
|
||||
|
||||
GET_NUM_QUESTS(ch)--;
|
||||
|
||||
if (ch->player_specials->saved.completed_quests)
|
||||
free(ch->player_specials->saved.completed_quests);
|
||||
ch->player_specials->saved.completed_quests = temp;
|
||||
}
|
||||
|
||||
void generic_complete_quest(struct char_data *ch)
|
||||
{
|
||||
qst_rnum rnum;
|
||||
qst_vnum vnum = GET_QUEST(ch);
|
||||
struct obj_data *new_obj;
|
||||
|
||||
if (--GET_QUEST_COUNTER(ch) <= 0) {
|
||||
rnum = real_quest(vnum);
|
||||
GET_QUESTPOINTS(ch) += QST_POINTS(rnum);
|
||||
send_to_char(ch,
|
||||
"%s\r\nYou have been awarded %d quest points for your service.\r\n",
|
||||
QST_DONE(rnum), QST_POINTS(rnum));
|
||||
if (QST_GOLD(rnum)) {
|
||||
GET_GOLD(ch) += QST_GOLD(rnum);
|
||||
send_to_char(ch,
|
||||
"You have been awarded %d gold coins for your service.\r\n",
|
||||
QST_GOLD(rnum));
|
||||
}
|
||||
if (QST_EXP(rnum)) {
|
||||
gain_exp(ch, QST_GOLD(rnum));
|
||||
send_to_char(ch,
|
||||
"You have been awarded %d experience points for your service.\r\n",
|
||||
QST_EXP(rnum));
|
||||
}
|
||||
if (QST_OBJ(rnum)) {
|
||||
if (real_object(QST_OBJ(rnum))) {
|
||||
if ((new_obj = create_obj()) != NULL) {
|
||||
new_obj = read_object((QST_OBJ(rnum)),VIRTUAL);
|
||||
obj_to_char(new_obj, ch);
|
||||
send_to_char(ch,
|
||||
"You have been presented with %s%s for your service.\r\n",
|
||||
GET_OBJ_SHORT(new_obj), CCNRM(ch, C_NRM));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!IS_SET(QST_FLAGS(rnum), AQ_REPEATABLE))
|
||||
add_completed_quest(ch, vnum);
|
||||
clear_quest(ch);
|
||||
if ((real_quest(QST_NEXT(rnum)) != NOTHING) &&
|
||||
(QST_NEXT(rnum) != vnum) &&
|
||||
!is_complete(ch, QST_NEXT(rnum))) {
|
||||
rnum = real_quest(QST_NEXT(rnum));
|
||||
set_quest(ch, rnum);
|
||||
send_to_char(ch,
|
||||
"The next stage of your quest awaits:\r\n%s",
|
||||
QST_INFO(rnum));
|
||||
}
|
||||
}
|
||||
save_char(ch);
|
||||
}
|
||||
|
||||
void autoquest_trigger_check(struct char_data *ch, struct char_data *vict,
|
||||
struct obj_data *object, int type)
|
||||
{
|
||||
struct char_data *i;
|
||||
qst_rnum rnum;
|
||||
int found = TRUE;
|
||||
|
||||
if (IS_NPC(ch))
|
||||
return;
|
||||
if (GET_QUEST(ch) == NOTHING) /* No current quest, skip this */
|
||||
return;
|
||||
if (GET_QUEST_TYPE(ch) != type)
|
||||
return;
|
||||
if ((rnum = real_quest(GET_QUEST(ch))) == NOTHING)
|
||||
return;
|
||||
switch (type) {
|
||||
case AQ_OBJ_FIND:
|
||||
if (QST_TARGET(rnum) == GET_OBJ_VNUM(object))
|
||||
generic_complete_quest(ch);
|
||||
break;
|
||||
case AQ_ROOM_FIND:
|
||||
if (QST_TARGET(rnum) == world[IN_ROOM(ch)].number)
|
||||
generic_complete_quest(ch);
|
||||
break;
|
||||
case AQ_MOB_FIND:
|
||||
for (i=world[IN_ROOM(ch)].people; i; i = i->next_in_room)
|
||||
if (IS_NPC(i))
|
||||
if (QST_TARGET(rnum) == GET_MOB_VNUM(i))
|
||||
generic_complete_quest(ch);
|
||||
break;
|
||||
case AQ_MOB_KILL:
|
||||
if (!IS_NPC(ch) && IS_NPC(vict) && (ch != vict))
|
||||
if (QST_TARGET(rnum) == GET_MOB_VNUM(vict))
|
||||
generic_complete_quest(ch);
|
||||
break;
|
||||
case AQ_MOB_SAVE:
|
||||
if (ch == vict)
|
||||
found = FALSE;
|
||||
for (i = world[IN_ROOM(ch)].people; i && found; i = i->next_in_room)
|
||||
if (i && IS_NPC(i) && !MOB_FLAGGED(i, MOB_NOTDEADYET))
|
||||
if ((GET_MOB_VNUM(i) != QST_TARGET(rnum)) &&
|
||||
!AFF_FLAGGED(i, AFF_CHARM))
|
||||
found = FALSE;
|
||||
if (found)
|
||||
generic_complete_quest(ch);
|
||||
break;
|
||||
case AQ_OBJ_RETURN:
|
||||
if (IS_NPC(vict) && (GET_MOB_VNUM(vict) == QST_RETURNMOB(rnum)))
|
||||
if (object && (GET_OBJ_VNUM(object) == QST_TARGET(rnum)))
|
||||
generic_complete_quest(ch);
|
||||
break;
|
||||
case AQ_ROOM_CLEAR:
|
||||
if (QST_TARGET(rnum) == world[IN_ROOM(ch)].number) {
|
||||
for (i = world[IN_ROOM(ch)].people; i && found; i = i->next_in_room)
|
||||
if (i && IS_NPC(i) && !MOB_FLAGGED(i, MOB_NOTDEADYET))
|
||||
found = FALSE;
|
||||
if (found)
|
||||
generic_complete_quest(ch);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log("SYSERR: Invalid quest type passed to autoquest_trigger_check");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void quest_timeout(struct char_data *ch)
|
||||
{
|
||||
if ((GET_QUEST(ch) != NOTHING) && (GET_QUEST_TIME(ch) != -1)) {
|
||||
clear_quest(ch);
|
||||
send_to_char(ch, "You have run out of time to complete the quest.\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void check_timed_quests(void)
|
||||
{
|
||||
struct char_data *ch;
|
||||
|
||||
for (ch = character_list; ch; ch = ch->next)
|
||||
if (!IS_NPC(ch) && (GET_QUEST(ch) != NOTHING) && (GET_QUEST_TIME(ch) != -1))
|
||||
if (--GET_QUEST_TIME(ch) == 0)
|
||||
quest_timeout(ch);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Quest Command Helper Functions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void list_quests(struct char_data *ch, zone_rnum zone, qst_vnum vmin, qst_vnum vmax)
|
||||
{
|
||||
qst_rnum rnum;
|
||||
qst_vnum bottom, top;
|
||||
int counter = 0;
|
||||
|
||||
if (zone != NOWHERE) {
|
||||
bottom = zone_table[zone].bot;
|
||||
top = zone_table[zone].top;
|
||||
} else {
|
||||
bottom = vmin;
|
||||
top = vmax;
|
||||
}
|
||||
/* Print the header for the quest listing. */
|
||||
send_to_char (ch,
|
||||
"Index VNum Description Questmaster\r\n"
|
||||
"----- ------- -------------------------------------------- -----------\r\n");
|
||||
for (rnum = 0; rnum < total_quests ; rnum++)
|
||||
if (QST_NUM(rnum) >= bottom && QST_NUM(rnum) <= top)
|
||||
send_to_char(ch, "@g%4d@n) [@g%-5d@n] @c%-44.44s@n @y[%5d]@n\r\n",
|
||||
++counter,
|
||||
QST_NUM(rnum), QST_NAME(rnum),
|
||||
mob_index[QST_MASTER(rnum)].vnum);
|
||||
if (!counter)
|
||||
send_to_char(ch, "None found.\r\n");
|
||||
}
|
||||
|
||||
void quest_hist(struct char_data *ch)
|
||||
{
|
||||
int i = 0, counter = 0;
|
||||
qst_rnum rnum = NOTHING;
|
||||
|
||||
send_to_char(ch, "Quests that you have completed:\r\n"
|
||||
"Index Description Questmaster\r\n"
|
||||
"----- ---------------------------------------------------- -----------\r\n");
|
||||
for (i = 0; i < GET_NUM_QUESTS(ch); i++) {
|
||||
if ((rnum = real_quest(ch->player_specials->saved.completed_quests[i])) != NOTHING)
|
||||
send_to_char(ch, "@g%4d@n) @c%-52.52s@n @y%s@n\r\n",
|
||||
++counter, QST_DESC(rnum), GET_NAME(&mob_proto[QST_MASTER(rnum)]));
|
||||
else
|
||||
send_to_char(ch,
|
||||
"@g%4d@n) @cUnknown Quest (it no longer exists)@n\r\n", ++counter);
|
||||
}
|
||||
if (!counter)
|
||||
send_to_char(ch, "You haven't completed any quests yet.\r\n");
|
||||
}
|
||||
|
||||
void quest_join(struct char_data *ch, struct char_data *qm, char argument[MAX_INPUT_LENGTH])
|
||||
{
|
||||
qst_vnum vnum;
|
||||
qst_rnum rnum;
|
||||
char buf[MAX_INPUT_LENGTH];
|
||||
|
||||
if (!*argument)
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s What quest did you wish to join?", GET_NAME(ch));
|
||||
else if (GET_QUEST(ch) != NOTHING)
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s But you are already part of a quest!", GET_NAME(ch));
|
||||
else if((vnum = find_quest_by_qmnum(ch, qm->nr, atoi(argument))) == NOTHING)
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s I don't know of such a quest!", GET_NAME(ch));
|
||||
else if ((rnum = real_quest(vnum)) == NOTHING)
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s I don't know of such a quest!", GET_NAME(ch));
|
||||
else if (GET_LEVEL(ch) < QST_MINLEVEL(rnum))
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s You are not experienced enough for that quest!", GET_NAME(ch));
|
||||
else if (GET_LEVEL(ch) > QST_MAXLEVEL(rnum))
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s You are too experienced for that quest!", GET_NAME(ch));
|
||||
else if (is_complete(ch, vnum))
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s You have already completed that quest!", GET_NAME(ch));
|
||||
else if ((QST_PREV(rnum) != NOTHING) && !is_complete(ch, vnum))
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s That quest is not available to you yet!", GET_NAME(ch));
|
||||
else if ((QST_PREREQ(rnum) != NOTHING) &&
|
||||
(real_object(QST_PREREQ(rnum)) != NOTHING) &&
|
||||
(get_obj_in_list_num(real_object(QST_PREREQ(rnum)),
|
||||
ch->carrying) == NULL))
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s You need to have %s first!", GET_NAME(ch),
|
||||
obj_proto[real_object(QST_PREREQ(rnum))].short_description);
|
||||
else {
|
||||
act("You join the quest.", TRUE, ch, NULL, NULL, TO_CHAR);
|
||||
act("$n has joined a quest.", TRUE, ch, NULL, NULL, TO_ROOM);
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s Listen carefully to the instructions.", GET_NAME(ch));
|
||||
do_tell(qm, buf, cmd_tell, 0);
|
||||
set_quest(ch, rnum);
|
||||
send_to_char(ch, QST_INFO(rnum));
|
||||
if (QST_TIME(rnum) != -1)
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s You have a time limit of %d turn%s to complete the quest.",
|
||||
GET_NAME(ch), QST_TIME(rnum), QST_TIME(rnum) == 1 ? "" : "s");
|
||||
else
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s You can take however long you want to complete the quest.",
|
||||
GET_NAME(ch));
|
||||
}
|
||||
do_tell(qm, buf, cmd_tell, 0);
|
||||
save_char(ch);
|
||||
}
|
||||
|
||||
void quest_list(struct char_data *ch, struct char_data *qm, char argument[MAX_INPUT_LENGTH])
|
||||
{
|
||||
qst_vnum vnum;
|
||||
qst_rnum rnum;
|
||||
|
||||
if ((vnum = find_quest_by_qmnum(ch, qm->nr, atoi(argument))) == NOTHING)
|
||||
send_to_char(ch, "That is not a valid quest!\r\n");
|
||||
else if ((rnum = real_quest(vnum)) == NOTHING)
|
||||
send_to_char(ch, "That is not a valid quest!\r\n");
|
||||
else if (QST_INFO(rnum)) {
|
||||
send_to_char(ch,"Complete Details on Quest %d @c%s@n:\r\n%s",
|
||||
vnum,
|
||||
QST_DESC(rnum),
|
||||
QST_INFO(rnum));
|
||||
if (QST_PREV(rnum) != NOTHING)
|
||||
send_to_char(ch, "You have to have completed quest %s first.\r\n",
|
||||
QST_NAME(real_quest(QST_PREV(rnum))));
|
||||
if (QST_TIME(rnum) != -1)
|
||||
send_to_char(ch,
|
||||
"There is a time limit of %d turn%s to complete the quest.\r\n",
|
||||
QST_TIME(rnum),
|
||||
QST_TIME(rnum) == 1 ? "" : "s");
|
||||
} else
|
||||
send_to_char(ch, "There is no further information on that quest.\r\n");
|
||||
}
|
||||
|
||||
void quest_quit(struct char_data *ch)
|
||||
{
|
||||
qst_rnum rnum;
|
||||
|
||||
if (GET_QUEST(ch) == NOTHING)
|
||||
send_to_char(ch, "But you currently aren't on a quest!\r\n");
|
||||
else if ((rnum = real_quest(GET_QUEST(ch))) == NOTHING) {
|
||||
clear_quest(ch);
|
||||
send_to_char(ch, "You are now no longer part of the quest.\r\n");
|
||||
save_char(ch);
|
||||
} else {
|
||||
clear_quest(ch);
|
||||
if (QST_QUIT(rnum) && (str_cmp(QST_QUIT(rnum), "undefined") != 0))
|
||||
send_to_char(ch, "%s", QST_QUIT(rnum));
|
||||
else
|
||||
send_to_char(ch, "You are now no longer part of the quest.\r\n");
|
||||
if (QST_PENALTY(rnum)) {
|
||||
GET_QUESTPOINTS(ch) -= QST_PENALTY(rnum);
|
||||
send_to_char(ch,
|
||||
"You have lost %d quest points for your cowardice.\r\n",
|
||||
QST_PENALTY(rnum));
|
||||
}
|
||||
save_char(ch);
|
||||
}
|
||||
}
|
||||
|
||||
void quest_progress(struct char_data *ch)
|
||||
{
|
||||
qst_rnum rnum;
|
||||
|
||||
if (GET_QUEST(ch) == NOTHING)
|
||||
send_to_char(ch, "But you currently aren't on a quest!\r\n");
|
||||
else if ((rnum = real_quest(GET_QUEST(ch))) == NOTHING) {
|
||||
clear_quest(ch);
|
||||
send_to_char(ch, "Your quest seems to no longer exist.\r\n");
|
||||
} else {
|
||||
send_to_char(ch, "You are on the following quest:\r\n%s\r\n%s",
|
||||
QST_DESC(rnum), QST_INFO(rnum));
|
||||
if (QST_QUANTITY(rnum) > 1)
|
||||
send_to_char(ch,
|
||||
"You still have to achieve %d out of %d goals for the quest.\r\n",
|
||||
GET_QUEST_COUNTER(ch), QST_QUANTITY(rnum));
|
||||
if (GET_QUEST_TIME(ch) > 0)
|
||||
send_to_char(ch,
|
||||
"You have %d turn%s remaining to complete the quest.\r\n",
|
||||
GET_QUEST_TIME(ch),
|
||||
GET_QUEST_TIME(ch) == 1 ? "" : "s");
|
||||
}
|
||||
}
|
||||
|
||||
void quest_show(struct char_data *ch, mob_rnum qm)
|
||||
{
|
||||
qst_rnum rnum;
|
||||
int counter = 0;
|
||||
|
||||
send_to_char(ch,
|
||||
"The following quests are available:\r\n"
|
||||
"Index Description ( Vnum) Done?\r\n"
|
||||
"----- ---------------------------------------------------- ------- -----\r\n");
|
||||
for (rnum = 0; rnum < total_quests; rnum++)
|
||||
if (qm == QST_MASTER(rnum))
|
||||
send_to_char(ch, "@g%4d@n) @c%-52.52s@n @y(%5d)@n @y(%s)@n\r\n",
|
||||
++counter, QST_DESC(rnum), QST_NUM(rnum),
|
||||
(is_complete(ch, QST_NUM(rnum)) ? "Yes" : "No "));
|
||||
if (!counter)
|
||||
send_to_char(ch, "There are no quests available here at the moment.\r\n");
|
||||
}
|
||||
|
||||
void quest_stat(struct char_data *ch, char argument[MAX_STRING_LENGTH])
|
||||
{
|
||||
qst_rnum rnum;
|
||||
char buf[MAX_STRING_LENGTH];
|
||||
char targetname[MAX_STRING_LENGTH];
|
||||
|
||||
if (GET_LEVEL(ch) < LVL_IMMORT)
|
||||
send_to_char(ch, "Huh!?!\r\n");
|
||||
else if (!*argument)
|
||||
send_to_char(ch, "%s\r\n", quest_imm_usage);
|
||||
else if ((rnum = real_quest(atoi(argument))) == NOTHING )
|
||||
send_to_char(ch, "That quest does not exist.\r\n");
|
||||
else {
|
||||
sprintbit(QST_FLAGS(rnum), aq_flags, buf, sizeof(buf));
|
||||
switch (QST_TYPE(rnum)) {
|
||||
case AQ_OBJ_FIND:
|
||||
case AQ_OBJ_RETURN:
|
||||
snprintf(targetname, sizeof(targetname), "%s",
|
||||
real_object(QST_TARGET(rnum)) == NOTHING ?
|
||||
"An unknown object" :
|
||||
obj_proto[real_object(QST_TARGET(rnum))].short_description);
|
||||
break;
|
||||
case AQ_ROOM_FIND:
|
||||
case AQ_ROOM_CLEAR:
|
||||
snprintf(targetname, sizeof(targetname), "%s",
|
||||
real_room(QST_TARGET(rnum)) == NOWHERE ?
|
||||
"An unknown room" :
|
||||
world[real_room(QST_TARGET(rnum))].name);
|
||||
break;
|
||||
case AQ_MOB_FIND:
|
||||
case AQ_MOB_KILL:
|
||||
case AQ_MOB_SAVE:
|
||||
snprintf(targetname, sizeof(targetname), "%s",
|
||||
real_mobile(QST_TARGET(rnum)) == NOBODY ?
|
||||
"An unknown mobile" :
|
||||
GET_NAME(&mob_proto[real_mobile(QST_TARGET(rnum))]));
|
||||
break;
|
||||
default:
|
||||
snprintf(targetname, sizeof(targetname), "Unknown");
|
||||
break;
|
||||
}
|
||||
send_to_char(ch,
|
||||
"VNum : [@y%5d@n], RNum: [@y%5d@n] -- Questmaster: [@y%5d@n] @y%s@n\r\n"
|
||||
"Name : @y%s@n\r\n"
|
||||
"Desc : @y%s@n\r\n"
|
||||
"Accept Message:\r\n@c%s@n"
|
||||
"Completion Message:\r\n@c%s@n"
|
||||
"Quit Message:\r\n@c%s@n"
|
||||
"Type : @y%s@n\r\n"
|
||||
"Target: @y%d@n @y%s@n, Quantity: @y%d@n\r\n"
|
||||
"Value : @y%d@n, Penalty: @y%d@n, Min Level: @y%2d@n, Max Level: @y%2d@n\r\n"
|
||||
"Flags : @c%s@n\r\n",
|
||||
QST_NUM(rnum), rnum,
|
||||
QST_MASTER(rnum) == NOBODY ? -1 : mob_index[QST_MASTER(rnum)].vnum,
|
||||
QST_MASTER(rnum) == NOBODY ? "" : GET_NAME(&mob_proto[QST_MASTER(rnum)]),
|
||||
QST_NAME(rnum), QST_DESC(rnum),
|
||||
QST_INFO(rnum), QST_DONE(rnum),
|
||||
(QST_QUIT(rnum) &&
|
||||
(str_cmp(QST_QUIT(rnum), "undefined") != 0)
|
||||
? QST_QUIT(rnum) : "Nothing\r\n"),
|
||||
quest_types[QST_TYPE(rnum)],
|
||||
QST_TARGET(rnum) == NOBODY ? -1 : QST_TARGET(rnum),
|
||||
targetname,
|
||||
QST_QUANTITY(rnum),
|
||||
QST_POINTS(rnum), QST_PENALTY(rnum), QST_MINLEVEL(rnum),
|
||||
QST_MAXLEVEL(rnum), buf);
|
||||
if (QST_PREREQ(rnum) != NOTHING)
|
||||
send_to_char(ch, "Preq : [@y%5d@n] @y%s@n\r\n",
|
||||
QST_PREREQ(rnum) == NOTHING ? -1 : QST_PREREQ(rnum),
|
||||
QST_PREREQ(rnum) == NOTHING ? "" :
|
||||
real_object(QST_PREREQ(rnum)) == NOTHING ? "an unknown object" :
|
||||
obj_proto[real_object(QST_PREREQ(rnum))].short_description);
|
||||
if (QST_TYPE(rnum) == AQ_OBJ_RETURN)
|
||||
send_to_char(ch, "Mob : [@y%5d@n] @y%s@n\r\n",
|
||||
QST_RETURNMOB(rnum),
|
||||
real_mobile(QST_RETURNMOB(rnum)) == NOBODY ? "an unknown mob" :
|
||||
mob_proto[real_mobile(QST_RETURNMOB(rnum))].player.short_descr);
|
||||
if (QST_TIME(rnum) != -1)
|
||||
send_to_char(ch, "Limit : There is a time limit of %d turn%s to complete.\r\n",
|
||||
QST_TIME(rnum),
|
||||
QST_TIME(rnum) == 1 ? "" : "s");
|
||||
else
|
||||
send_to_char(ch, "Limit : There is no time limit on this quest.\r\n");
|
||||
send_to_char(ch, "Prior :");
|
||||
if (QST_PREV(rnum) == NOTHING)
|
||||
send_to_char(ch, " @yNone.@n\r\n");
|
||||
else
|
||||
send_to_char(ch, " [@y%5d@n] @c%s@n\r\n",
|
||||
QST_PREV(rnum), QST_DESC(real_quest(QST_PREV(rnum))));
|
||||
send_to_char(ch, "Next :");
|
||||
if (QST_NEXT(rnum) == NOTHING)
|
||||
send_to_char(ch, " @yNone.@n\r\n");
|
||||
else
|
||||
send_to_char(ch, " [@y%5d@n] @c%s@n\r\n",
|
||||
QST_NEXT(rnum), QST_DESC(real_quest(QST_NEXT(rnum))));
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Quest Command Processing Function and Questmaster Special */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
ACMD(do_quest)
|
||||
{
|
||||
char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH];
|
||||
int tp;
|
||||
|
||||
two_arguments(argument, arg1, arg2);
|
||||
if (!*arg1)
|
||||
send_to_char(ch, "%s\r\n", GET_LEVEL(ch) < LVL_IMMORT ?
|
||||
quest_mort_usage : quest_imm_usage);
|
||||
else if (((tp = search_block(arg1, quest_cmd, FALSE)) == -1))
|
||||
send_to_char(ch, "%s\r\n", GET_LEVEL(ch) < LVL_IMMORT ?
|
||||
quest_mort_usage : quest_imm_usage);
|
||||
else {
|
||||
switch (tp) {
|
||||
case SCMD_QUEST_LIST:
|
||||
case SCMD_QUEST_JOIN:
|
||||
/* list, join should hve been handled by questmaster spec proc */
|
||||
send_to_char(ch, "Sorry, but you cannot do that here!\r\n");
|
||||
break;
|
||||
case SCMD_QUEST_HISTORY:
|
||||
quest_hist(ch);
|
||||
break;
|
||||
case SCMD_QUEST_LEAVE:
|
||||
quest_quit(ch);
|
||||
break;
|
||||
case SCMD_QUEST_PROGRESS:
|
||||
quest_progress(ch);
|
||||
break;
|
||||
case SCMD_QUEST_STATUS:
|
||||
if (GET_LEVEL(ch) < LVL_IMMORT)
|
||||
send_to_char(ch, "%s\r\n", quest_mort_usage);
|
||||
else
|
||||
quest_stat(ch, arg2);
|
||||
break;
|
||||
default: /* Whe should never get here, but... */
|
||||
send_to_char(ch, "%s\r\n", GET_LEVEL(ch) < LVL_IMMORT ?
|
||||
quest_mort_usage : quest_imm_usage);
|
||||
break;
|
||||
} /* switch on subcmd number */
|
||||
}
|
||||
}
|
||||
|
||||
SPECIAL(questmaster)
|
||||
{
|
||||
qst_rnum rnum;
|
||||
char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH];
|
||||
int tp;
|
||||
struct char_data *qm = (struct char_data *)me;
|
||||
|
||||
/* check that qm mob has quests assigned */
|
||||
for (rnum = 0; (rnum < total_quests &&
|
||||
QST_MASTER(rnum) != GET_MOB_RNUM(qm)) ; rnum ++);
|
||||
if (rnum >= total_quests)
|
||||
return FALSE; /* No quests for this mob */
|
||||
else if (QST_FUNC(rnum) && (QST_FUNC(rnum) (ch, me, cmd, argument)))
|
||||
return TRUE; /* The secondary spec proc handled this command */
|
||||
else if (CMD_IS("quest")) {
|
||||
two_arguments(argument, arg1, arg2);
|
||||
if (!*arg1)
|
||||
return FALSE;
|
||||
else if (((tp = search_block(arg1, quest_cmd, FALSE)) == -1))
|
||||
return FALSE;
|
||||
else {
|
||||
switch (tp) {
|
||||
case SCMD_QUEST_LIST:
|
||||
if (!*arg2)
|
||||
quest_show(ch, GET_MOB_RNUM(qm));
|
||||
else
|
||||
quest_list(ch, qm, arg2);
|
||||
break;
|
||||
case SCMD_QUEST_JOIN:
|
||||
quest_join(ch, qm, arg2);
|
||||
break;
|
||||
default:
|
||||
return FALSE; /* fall through to the do_quest command processor */
|
||||
} /* switch on subcmd number */
|
||||
return TRUE;
|
||||
}
|
||||
} else {
|
||||
return FALSE; /* not a questmaster command */
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue