Updated World and files for 3.58 release. --Rumble
This commit is contained in:
@@ -2222,19 +2222,7 @@ ACMD(do_commands)
|
||||
}
|
||||
|
||||
/* display commands list in a nice columnized format */
|
||||
column_list(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
||||
/* subtract 1 or 2 lines (the pager adds 1 or 2) */
|
||||
/* also "skip" a line since we printed a header above */
|
||||
GET_PAGE_LENGTH(ch) - (PRF_FLAGGED(ch, PRF_COMPACT) ? 1 : 2), 1,
|
||||
/* 7 columns; no == how many elements, 0 offset */
|
||||
7, commands, no, 0, "$11l");
|
||||
|
||||
if (overflow < 0) {
|
||||
log("SYSERR: Too many commands for do_commands; increase size of *commands array.");
|
||||
strncat(buf, "\r\n** OVERFLOW **\r\n", sizeof(buf) - strlen(buf));
|
||||
}
|
||||
|
||||
page_string(ch->desc, buf, TRUE);
|
||||
column_list(ch, 7, commands, no, FALSE);
|
||||
}
|
||||
|
||||
void free_history(struct char_data *ch, int type)
|
||||
|
||||
14
src/class.c
14
src/class.c
@@ -1918,8 +1918,8 @@ const char *title_male(int chclass, int level)
|
||||
case 20: return "the Cut-Throat";
|
||||
/* no one ever thought up these titles 21-30 */
|
||||
case LVL_IMMORT: return "the Immortal Assassin";
|
||||
case LVL_GOD: return "the Demi God of thieves";
|
||||
case LVL_GRGOD: return "the God of thieves and tradesmen";
|
||||
case LVL_GOD: return "the Demi God of Thieves";
|
||||
case LVL_GRGOD: return "the God of Thieves and Tradesmen";
|
||||
default: return "the Thief";
|
||||
}
|
||||
break;
|
||||
@@ -1949,7 +1949,7 @@ const char *title_male(int chclass, int level)
|
||||
/* no one ever thought up these titles 21-30 */
|
||||
case LVL_IMMORT: return "the Immortal Warlord";
|
||||
case LVL_GOD: return "the Extirpator";
|
||||
case LVL_GRGOD: return "the God of war";
|
||||
case LVL_GRGOD: return "the God of War";
|
||||
default: return "the Warrior";
|
||||
}
|
||||
break;
|
||||
@@ -2033,7 +2033,7 @@ const char *title_female(int chclass, int level)
|
||||
/* no one ever thought up these titles 21-30 */
|
||||
case LVL_IMMORT: return "the Immortal Priestess";
|
||||
case LVL_GOD: return "the Inquisitress";
|
||||
case LVL_GRGOD: return "the Goddess of good and evil";
|
||||
case LVL_GRGOD: return "the Goddess of Good and Evil";
|
||||
default: return "the Cleric";
|
||||
}
|
||||
break;
|
||||
@@ -2062,8 +2062,8 @@ const char *title_female(int chclass, int level)
|
||||
case 20: return "the Cut-Throat";
|
||||
/* no one ever thought up these titles 21-30 */
|
||||
case LVL_IMMORT: return "the Immortal Assassin";
|
||||
case LVL_GOD: return "the Demi Goddess of thieves";
|
||||
case LVL_GRGOD: return "the Goddess of thieves and tradesmen";
|
||||
case LVL_GOD: return "the Demi Goddess of Thieves";
|
||||
case LVL_GRGOD: return "the Goddess of Thieves and Tradesmen";
|
||||
default: return "the Thief";
|
||||
}
|
||||
break;
|
||||
@@ -2093,7 +2093,7 @@ const char *title_female(int chclass, int level)
|
||||
/* no one ever thought up these titles 21-30 */
|
||||
case LVL_IMMORT: return "the Immortal Lady of War";
|
||||
case LVL_GOD: return "the Queen of Destruction";
|
||||
case LVL_GRGOD: return "the Goddess of war";
|
||||
case LVL_GRGOD: return "the Goddess of War";
|
||||
default: return "the Warrior";
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* @todo cpp_extern isn't needed here (or anywhere) as the extern reserved word
|
||||
* works correctly with C compilers (at least in my Experience)
|
||||
* Jeremy Osborne 1/28/2008 */
|
||||
cpp_extern const char *tbamud_version = "tbaMUD 3.57";
|
||||
cpp_extern const char *tbamud_version = "tbaMUD 3.58";
|
||||
|
||||
/* strings corresponding to ordinals/bitvectors in structs.h */
|
||||
/* (Note: strings for class definitions in class.c instead of here) */
|
||||
|
||||
@@ -864,7 +864,7 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig,
|
||||
if (IS_NPC(c))
|
||||
strcpy(str, "0");
|
||||
else {
|
||||
if ((GET_QUEST(c) != NOTHING) && (real_quest(GET_QUEST(c)) == NOTHING))
|
||||
if ((GET_QUEST(c) != NOTHING) && (real_quest(GET_QUEST(c)) != NOTHING))
|
||||
snprintf(str, slen, "%d", GET_QUEST(c));
|
||||
else
|
||||
strcpy(str, "0");
|
||||
|
||||
16
src/genqst.c
16
src/genqst.c
@@ -82,6 +82,7 @@ void free_quest(struct aq_data *quest)
|
||||
int add_quest(struct aq_data *nqst)
|
||||
{
|
||||
qst_rnum rnum;
|
||||
mob_rnum qmrnum;
|
||||
zone_rnum rznum = real_zone_by_thing(nqst->vnum);
|
||||
|
||||
/* The quest already exists, just update it. */
|
||||
@@ -105,12 +106,13 @@ int add_quest(struct aq_data *nqst)
|
||||
}
|
||||
copy_quest(&aquest_table[rnum], nqst, FALSE);
|
||||
}
|
||||
qmrnum = real_mobile(QST_MASTER(rnum));
|
||||
/* Make sure we assign spec procs to the questmaster */
|
||||
if (QST_MASTER(rnum) != NOBODY && mob_index[QST_MASTER(rnum)].func &&
|
||||
mob_index[QST_MASTER(rnum)].func != questmaster)
|
||||
QST_FUNC(rnum) = mob_index[QST_MASTER(rnum)].func;
|
||||
if(QST_MASTER(rnum) != NOBODY)
|
||||
mob_index[QST_MASTER(rnum)].func = questmaster;
|
||||
if (qmrnum != NOBODY && mob_index[qmrnum].func &&
|
||||
mob_index[qmrnum].func != questmaster)
|
||||
QST_FUNC(rnum) = mob_index[qmrnum].func;
|
||||
if(qmrnum != NOBODY)
|
||||
mob_index[qmrnum].func = questmaster;
|
||||
|
||||
/* And make sure we save the updated quest information to disk */
|
||||
if (rznum != NOWHERE)
|
||||
@@ -128,7 +130,7 @@ int delete_quest(qst_rnum rnum)
|
||||
{
|
||||
qst_rnum i;
|
||||
zone_rnum rznum;
|
||||
mob_rnum qm = QST_MASTER(rnum);
|
||||
mob_vnum qm = QST_MASTER(rnum);
|
||||
SPECIAL (*tempfunc);
|
||||
int quests_remaining = 0;
|
||||
|
||||
@@ -235,7 +237,7 @@ int save_quests(zone_rnum zone_num)
|
||||
quest_done, STRING_TERMINATOR,
|
||||
quest_quit, STRING_TERMINATOR,
|
||||
QST_TYPE(rnum),
|
||||
QST_MASTER(rnum) == NOBODY ? -1 : mob_index[QST_MASTER(rnum)].vnum,
|
||||
QST_MASTER(rnum) == NOBODY ? -1 : QST_MASTER(rnum),
|
||||
quest_flags,
|
||||
QST_TARGET(rnum) == NOTHING ? -1 : QST_TARGET(rnum),
|
||||
QST_PREV(rnum) == NOTHING ? -1 : QST_PREV(rnum),
|
||||
|
||||
13
src/medit.c
13
src/medit.c
@@ -340,10 +340,7 @@ static void medit_disp_mob_flags(struct descriptor_data *d)
|
||||
get_char_colors(d->character);
|
||||
clear_screen(d);
|
||||
|
||||
column_list(buf, sizeof(buf), 0, 0,
|
||||
2, action_bits, NUM_MOB_FLAGS, 0,
|
||||
"%s$2i%s) $20l", grn, nrm);
|
||||
write_to_output(d, "%s", buf);
|
||||
column_list(d->character, 2, action_bits, NUM_MOB_FLAGS, TRUE);
|
||||
|
||||
sprintbitarray(MOB_FLAGS(OLC_MOB(d)), action_bits, AF_ARRAY_MAX, buf);
|
||||
write_to_output(d, "\r\nCurrent flags : %s%s%s\r\nEnter mob flags (0 to quit) : ",
|
||||
@@ -357,11 +354,9 @@ static void medit_disp_aff_flags(struct descriptor_data *d)
|
||||
|
||||
get_char_colors(d->character);
|
||||
clear_screen(d);
|
||||
|
||||
column_list(buf, sizeof(buf), 0, 0,
|
||||
2, affected_bits, NUM_AFF_FLAGS, 1,
|
||||
"%s$2i%s) $20l", grn, nrm);
|
||||
write_to_output(d, "%s", buf);
|
||||
|
||||
/* +1 since AFF_FLAGS don't start at 0. */
|
||||
column_list(d->character, 2, affected_bits + 1, NUM_AFF_FLAGS, TRUE);
|
||||
|
||||
sprintbitarray(AFF_FLAGS(OLC_MOB(d)), affected_bits, AF_ARRAY_MAX, buf);
|
||||
write_to_output(d, "\r\nCurrent flags : %s%s%s\r\nEnter aff flags (0 to quit) : ",
|
||||
|
||||
@@ -90,7 +90,7 @@ void mobile_activity(void)
|
||||
}
|
||||
|
||||
/* Aggressive Mobs */
|
||||
if (MOB_FLAGGED(ch, MOB_HELPER) && (!AFF_FLAGGED(ch, AFF_BLIND) || !AFF_FLAGGED(ch, AFF_CHARM))) {
|
||||
if (!MOB_FLAGGED(ch, MOB_HELPER) && (!AFF_FLAGGED(ch, AFF_BLIND) || !AFF_FLAGGED(ch, AFF_CHARM))) {
|
||||
found = FALSE;
|
||||
for (vict = world[IN_ROOM(ch)].people; vict && !found; vict = vict->next_in_room) {
|
||||
if (IS_NPC(vict) || !CAN_SEE(ch, vict) || PRF_FLAGGED(vict, PRF_NOHASSLE))
|
||||
|
||||
@@ -329,8 +329,8 @@ static void qedit_disp_menu(struct descriptor_data *d)
|
||||
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->qm == NOBODY ? -1 : quest->qm,
|
||||
real_mobile(quest->qm) == NOBODY ? "Invalid Mob" : mob_proto[(real_mobile(quest->qm))].player.short_descr,
|
||||
quest->target == NOBODY ? -1 : quest->target, targetname,
|
||||
quest->value[6],
|
||||
quest->value[0], quest->value[1],
|
||||
@@ -605,7 +605,7 @@ void qedit_parse(struct descriptor_data *d, char *arg)
|
||||
break;
|
||||
case QEDIT_QUESTMASTER:
|
||||
if (number != -1)
|
||||
if ((number = real_mobile(number)) == NOBODY) {
|
||||
if (real_mobile(number) == NOBODY) {
|
||||
write_to_output(d, "That mobile does not exist, try again : ");
|
||||
return;
|
||||
}
|
||||
|
||||
27
src/quest.c
27
src/quest.c
@@ -81,7 +81,7 @@ int is_complete(struct char_data *ch, qst_vnum vnum)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
qst_vnum find_quest_by_qmnum(struct char_data *ch, mob_rnum qm, int num)
|
||||
qst_vnum find_quest_by_qmnum(struct char_data *ch, mob_vnum qm, int num)
|
||||
{
|
||||
qst_rnum rnum;
|
||||
int found=0;
|
||||
@@ -166,7 +166,7 @@ void parse_quest(FILE *quest_f, int nr)
|
||||
exit(1);
|
||||
}
|
||||
aquest_table[i].type = t[0];
|
||||
aquest_table[i].qm = real_mobile(t[1]);
|
||||
aquest_table[i].qm = (real_mobile(t[1]) == NOBODY) ? NOBODY : 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];
|
||||
@@ -211,6 +211,7 @@ void parse_quest(FILE *quest_f, int nr)
|
||||
void assign_the_quests(void)
|
||||
{
|
||||
qst_rnum rnum;
|
||||
mob_rnum mrnum;
|
||||
|
||||
cmd_tell = find_command("tell");
|
||||
|
||||
@@ -219,10 +220,14 @@ void assign_the_quests(void)
|
||||
log("SYSERR: Quest #%d has no questmaster specified.", QST_NUM(rnum));
|
||||
continue;
|
||||
}
|
||||
if ((mrnum = real_mobile(QST_MASTER(rnum))) == NOBODY) {
|
||||
log("SYSERR: Quest #%d has an invalid questmaster.", 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;
|
||||
mob_index[(mrnum)].func != questmaster)
|
||||
QST_FUNC(rnum) = mob_index[(mrnum)].func;
|
||||
mob_index[(mrnum)].func = questmaster;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,7 +444,7 @@ void list_quests(struct char_data *ch, zone_rnum zone, qst_vnum vmin, qst_vnum v
|
||||
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),
|
||||
QST_MASTER(rnum) == NOBODY ? 0 : mob_index[QST_MASTER(rnum)].vnum);
|
||||
QST_MASTER(rnum) == NOBODY ? 0 : QST_MASTER(rnum));
|
||||
if (!counter)
|
||||
send_to_char(ch, "None found.\r\n");
|
||||
}
|
||||
@@ -455,7 +460,7 @@ void quest_hist(struct char_data *ch)
|
||||
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)]));
|
||||
++counter, QST_DESC(rnum), (real_mobile(QST_MASTER(rnum)) == NOBODY) ? "Unknown" : GET_NAME(&mob_proto[(real_mobile(QST_MASTER(rnum)))]));
|
||||
else
|
||||
send_to_char(ch,
|
||||
"@g%4d@n) @cUnknown Quest (it no longer exists)@n\r\n", ++counter);
|
||||
@@ -598,7 +603,7 @@ void quest_progress(struct char_data *ch)
|
||||
}
|
||||
}
|
||||
|
||||
void quest_show(struct char_data *ch, mob_rnum qm)
|
||||
void quest_show(struct char_data *ch, mob_vnum qm)
|
||||
{
|
||||
qst_rnum rnum;
|
||||
int counter = 0;
|
||||
@@ -619,6 +624,7 @@ void quest_show(struct char_data *ch, mob_rnum qm)
|
||||
void quest_stat(struct char_data *ch, char argument[MAX_STRING_LENGTH])
|
||||
{
|
||||
qst_rnum rnum;
|
||||
mob_rnum qmrnum;
|
||||
char buf[MAX_STRING_LENGTH];
|
||||
char targetname[MAX_STRING_LENGTH];
|
||||
|
||||
@@ -657,6 +663,7 @@ void quest_stat(struct char_data *ch, char argument[MAX_STRING_LENGTH])
|
||||
snprintf(targetname, sizeof(targetname), "Unknown");
|
||||
break;
|
||||
}
|
||||
qmrnum = real_mobile(QST_MASTER(rnum));
|
||||
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"
|
||||
@@ -769,7 +776,7 @@ SPECIAL(questmaster)
|
||||
|
||||
/* check that qm mob has quests assigned */
|
||||
for (rnum = 0; (rnum < total_quests &&
|
||||
QST_MASTER(rnum) != GET_MOB_RNUM(qm)) ; rnum ++);
|
||||
QST_MASTER(rnum) != GET_MOB_VNUM(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)))
|
||||
@@ -784,7 +791,7 @@ SPECIAL(questmaster)
|
||||
switch (tp) {
|
||||
case SCMD_QUEST_LIST:
|
||||
if (!*arg2)
|
||||
quest_show(ch, GET_MOB_RNUM(qm));
|
||||
quest_show(ch, GET_MOB_VNUM(qm));
|
||||
else
|
||||
quest_list(ch, qm, arg2);
|
||||
break;
|
||||
|
||||
@@ -44,7 +44,7 @@ struct aq_data {
|
||||
char *quit; /* Message displayed when quit quest */
|
||||
long flags; /* Flags (repeatable, etc */
|
||||
int type; /* Quest type */
|
||||
mob_rnum qm; /* questmaster offering quest */
|
||||
mob_vnum qm; /* questmaster offering quest */
|
||||
int target; /* Target value */
|
||||
obj_vnum prereq; /* Object required to undertake quest */
|
||||
int value[7]; /* Quest values */
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* on an older version. You are supposed to compare this with the macro
|
||||
* TBAMUD_VERSION() in utils.h.
|
||||
* It is read as Major/Minor/Patchlevel - MMmmPP */
|
||||
#define _TBAMUD 0x030570
|
||||
#define _TBAMUD 0x030580
|
||||
|
||||
/** If you want equipment to be automatically equipped to the same place
|
||||
* it was when players rented, set the define below to 1 because
|
||||
|
||||
230
src/utils.c
230
src/utils.c
@@ -16,6 +16,7 @@
|
||||
#include "utils.h"
|
||||
#include "db.h"
|
||||
#include "comm.h"
|
||||
#include "modify.h"
|
||||
#include "screen.h"
|
||||
#include "spells.h"
|
||||
#include "handler.h"
|
||||
@@ -932,194 +933,65 @@ void char_from_furniture(struct char_data *ch)
|
||||
}
|
||||
|
||||
|
||||
/* Helper function for column_list. */
|
||||
void process_column_list_format(char **out_buffer, const char *format,
|
||||
int buf_left, int index_data, const char *item)
|
||||
{
|
||||
/* Initialize the index format with a % */
|
||||
char index_format[80] = {'%'};
|
||||
int i;
|
||||
/* column_list
|
||||
The list is output in a fixed format, and only the number of columns can be adjusted
|
||||
This function will output the list to the player
|
||||
Vars:
|
||||
ch - the player
|
||||
num_cols - the desired number of columns
|
||||
list - a pointer to a list of strings
|
||||
list_length - So we can work with lists that don't end with /n
|
||||
show_nums - when set to TRUE, it will show a number before the list entry.
|
||||
*/
|
||||
void column_list(struct char_data *ch, int num_cols, const char **list, int list_length, bool show_nums)
|
||||
{
|
||||
int num_per_col, col_width,r,c,i, offset=0, len=0, temp_len, max_len=0;
|
||||
char buf[MAX_STRING_LENGTH];
|
||||
|
||||
/* Copy the format to the output buffer character by character. */
|
||||
while (*format && buf_left >= 2) {
|
||||
/* Ensure that the number of columns is in the range 1-10 */
|
||||
num_cols = MIN(MAX(num_cols,1), 10);
|
||||
|
||||
/* A '$' signifies a 'control-code'. */
|
||||
if (*format == '$') {
|
||||
++format;
|
||||
/* Work out the longest list item */
|
||||
for (i=0; i<list_length; i++)
|
||||
if (max_len < strlen(list[i]))
|
||||
max_len = strlen(list[i]);
|
||||
|
||||
/*
|
||||
* Begin by assuming the caller has supplied a number here
|
||||
* (something that looks like $3i). Then collect this number
|
||||
* into the index_format after the %.
|
||||
*/
|
||||
i = 1;
|
||||
while (isdigit(*format) && i < 78)
|
||||
index_format[i++] = *(format++);
|
||||
index_format[i++] = 'd';
|
||||
index_format[i] = '\0';
|
||||
/* Calculate the width of each column */
|
||||
col_width = (GET_SCREEN_WIDTH(ch)) / num_cols;
|
||||
if (show_nums) col_width-=4;
|
||||
|
||||
/* There may not be enough space left for the index. */
|
||||
if (buf_left < 12)
|
||||
break;
|
||||
if (col_width < max_len)
|
||||
log("Warning: columns too narrow for correct output to %s in simple_column_list (utils.c)", GET_NAME(ch));
|
||||
|
||||
/*
|
||||
* Okay, output the current index using the index format
|
||||
* we already constructed above.
|
||||
*/
|
||||
else if (*format == 'i')
|
||||
*out_buffer += sprintf(*out_buffer, index_format, index_data);
|
||||
/* Calculate how many list items there should be per column */
|
||||
num_per_col = (list_length / num_cols) + ((list_length % num_cols) ? 1 : 0);
|
||||
|
||||
/*
|
||||
* Or output the current list item. Use part of the
|
||||
* index format collected above to decide how wide the
|
||||
* list item should be displayed.
|
||||
*/
|
||||
else if (*format == 'l') {
|
||||
/* skip the %. atoi ignores the d too */
|
||||
i = atoi(index_format + 1);
|
||||
/* if no width, set to -1 (any width) */
|
||||
if (!i) --i;
|
||||
/* Fill 'buf' with the columnised list */
|
||||
for (r=0; r<num_per_col; r++)
|
||||
{
|
||||
for (c=0; c<num_cols; c++)
|
||||
{
|
||||
offset = (c*num_per_col)+r;
|
||||
if (offset < list_length)
|
||||
{
|
||||
if (show_nums)
|
||||
temp_len = snprintf(buf+len, sizeof(buf) - len, "%2d) %-*s", offset+1, col_width, list[(offset)]);
|
||||
else
|
||||
temp_len = snprintf(buf+len, sizeof(buf) - len, "%-*s", col_width, list[(offset)]);
|
||||
len += temp_len;
|
||||
}
|
||||
}
|
||||
temp_len = snprintf(buf+len, sizeof(buf) - len, "\r\n");
|
||||
len += temp_len;
|
||||
}
|
||||
|
||||
/* copy the list item to the output buffer */
|
||||
while (*item && buf_left >= 2 && i != 0) {
|
||||
*((*out_buffer)++) = *(item++);
|
||||
--buf_left;
|
||||
--i;
|
||||
}
|
||||
if (len >= sizeof(buf))
|
||||
snprintf((buf + MAX_STRING_LENGTH) - 22, 22, "\r\n*** OVERFLOW ***\r\n");
|
||||
|
||||
/* if width was specified above, pad the list item */
|
||||
while (i-- > 0 && buf_left >= 2) {
|
||||
*((*out_buffer)++) = ' ';
|
||||
--buf_left;
|
||||
}
|
||||
}
|
||||
/* Send the list to the player */
|
||||
page_string(ch->desc, buf, TRUE);
|
||||
}
|
||||
|
||||
/* Or just output a $ */
|
||||
else if (*format == '$') {
|
||||
*((*out_buffer)++) = '$';
|
||||
--buf_left;
|
||||
}
|
||||
|
||||
/* Whoa, at the end of the format already? */
|
||||
else if (!*format)
|
||||
break;
|
||||
|
||||
++format;
|
||||
}
|
||||
|
||||
/* Not a '$' control code. Simply copy the character. */
|
||||
else {
|
||||
*((*out_buffer)++) = *(format++);
|
||||
--buf_left;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure it's nul-terminated. */
|
||||
**out_buffer = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a list of strings and a display format, and formats them
|
||||
* in a list by column (sequential items in the list are aligned
|
||||
* vertically, then horizontally). This function supports varargs
|
||||
* for the format string that describes how each item should look.
|
||||
* @param[out] out_buffer The buffer to write to.
|
||||
* @param[in] buf_left The size of the buffer.
|
||||
* @param[in] page_length How many lines per page? 0 means no paging.
|
||||
* @param[in] skip_lines How many lines to skip on the first page?
|
||||
* @param[in] columns How many columns should be displayed?
|
||||
* @param[in] list The array of strings to format.
|
||||
* @param[in] list_length How many elements are in the list? We won't rely on
|
||||
* lists ending with a newline element.
|
||||
* @param[in] list_offset Is the list offset and by how much? For instance,
|
||||
* affect flags are offset by one when displayed in medit.
|
||||
* @param[in] format The format string for displaying each
|
||||
* item in the list. Use "$#i" and "$#l" in the format string to determine
|
||||
* how wide the index position and list item should be. For instance,
|
||||
* "$2i $20l" would be equivalent to a printf "%2d %-20.20s".
|
||||
* @param[in] ... Additional args for formatting the list display.
|
||||
*/
|
||||
void column_list(char *out_buffer, int buf_left, int page_length,
|
||||
int skip_lines, int columns, const char **list,
|
||||
int list_length, int list_offset,
|
||||
const char *format, ...)
|
||||
{
|
||||
int i, j = 0, k, rows, visited = 0;
|
||||
char line[80];
|
||||
va_list args;
|
||||
|
||||
--buf_left;
|
||||
|
||||
/* We only need to parse the given format string for %'s once. */
|
||||
va_start(args, format);
|
||||
vsnprintf(line, sizeof(line), format, args);
|
||||
va_end(args);
|
||||
|
||||
/* A page_length <= 0 means don't page output. */
|
||||
if (page_length <= 0)
|
||||
page_length = list_length;
|
||||
|
||||
/*
|
||||
* The list index jumps around, since we want to display
|
||||
* the list items by columns. For instance, in the first
|
||||
* row, the second column's item will be approximately
|
||||
* page_length positions in the list away from the item
|
||||
* in the first column of the same row.
|
||||
* So we use this macro.
|
||||
*/
|
||||
#define LIST_INDEX (page_length * columns * k + rows * j + i - \
|
||||
(k == 0 ? 0 : skip_lines * columns))
|
||||
|
||||
/* Traverse by page... */
|
||||
for (k = 0; k <= list_length / (page_length * columns); ++k) {
|
||||
rows = MIN(page_length, (list_length - visited) / columns + 1);
|
||||
if (k == 0)
|
||||
rows -= skip_lines;
|
||||
/* And then by row... */
|
||||
for (i = 0; i < rows; ++i) {
|
||||
/* And then by column... */
|
||||
for (j = 0; j < columns; ++j) {
|
||||
/* If the index is too high, break out. */
|
||||
if (LIST_INDEX >= list_length)
|
||||
break;
|
||||
|
||||
/*
|
||||
* If space still remains in the buffer, process the next
|
||||
* list item and print it to the buffer. Otherwise,
|
||||
* complain about an overflow.
|
||||
*/
|
||||
if (buf_left > sizeof(line)) {
|
||||
/*
|
||||
* Now the real magic. Replace $i and $l with the index
|
||||
* and list item. Don't let each displayed list item be wider
|
||||
* than (an arbitrary) 80 characters. Also, allow a list
|
||||
* offset in case we want to skip the first list item or
|
||||
* something (like for affection flags).
|
||||
*/
|
||||
process_column_list_format(&out_buffer, line, sizeof(line),
|
||||
LIST_INDEX + 1,
|
||||
list[LIST_INDEX + list_offset]);
|
||||
++visited;
|
||||
}
|
||||
else {
|
||||
strcpy(out_buffer + (buf_left < 17 ? buf_left - 17 : 0),
|
||||
"\r\n**OVERFLOW**\r\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We're at the end of a row. Print a newline, advance the
|
||||
* buffer, and decrement the amount of space left in the buffer.
|
||||
*/
|
||||
strcpy(out_buffer, "\r\n");
|
||||
out_buffer += 2;
|
||||
buf_left -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
#undef LIST_INDEX
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Search through a string array of flags for a particular flag.
|
||||
|
||||
@@ -58,10 +58,7 @@ int levenshtein_distance(const char *s1, const char *s2);
|
||||
struct time_info_data *real_time_passed(time_t t2, time_t t1);
|
||||
struct time_info_data *mud_time_passed(time_t t2, time_t t1);
|
||||
void prune_crlf(char *txt);
|
||||
void column_list(char *out_buffer, int buf_left, int page_length,
|
||||
int skip_lines, int columns, const char **list,
|
||||
int list_length, int list_offset, const char *format,
|
||||
...) __attribute__ ((format (printf, 9, 10)));
|
||||
void column_list(struct char_data *ch, int num_cols, const char **list, int list_length, bool show_nums);
|
||||
int get_flag_by_name(const char *flag_list[], char *flag_name);
|
||||
int file_head( FILE *file, char *buf, size_t bufsize, int lines_to_read );
|
||||
int file_tail( FILE *file, char *buf, size_t bufsize, int lines_to_read );
|
||||
|
||||
Reference in New Issue
Block a user