diff --git a/src/act.wizard.c b/src/act.wizard.c index 22a7d20..c9ccb6a 100644 --- a/src/act.wizard.c +++ b/src/act.wizard.c @@ -1237,6 +1237,7 @@ static void do_stat_character(struct char_data *ch, struct char_data *k) } send_to_char(ch, "D-Desc:\r\n %s", k->player.description ? k->player.description : "\r\n"); + send_to_char(ch, "Background:\r\n %s", k->player.background ? k->player.background : "\r\n"); if (!IS_NPC(k)) { char buf1[64], buf2[64]; diff --git a/src/db.c b/src/db.c index 4154177..16e427d 100644 --- a/src/db.c +++ b/src/db.c @@ -589,10 +589,12 @@ void destroy_db(void) free(mob_proto[cnt].player.name); if (mob_proto[cnt].player.short_descr) free(mob_proto[cnt].player.short_descr); - if (mob_proto[cnt].player.long_descr) - free(mob_proto[cnt].player.long_descr); - if (mob_proto[cnt].player.description) - free(mob_proto[cnt].player.description); + if (mob_proto[cnt].player.long_descr) + free(mob_proto[cnt].player.long_descr); + if (mob_proto[cnt].player.description) + free(mob_proto[cnt].player.description); + if (mob_proto[cnt].player.background) + free(mob_proto[cnt].player.background); /* free script proto list */ free_proto_script(&mob_proto[cnt], MOB_TRIGGER); @@ -1776,6 +1778,33 @@ void parse_mobile(FILE *mob_f, int nr) *tmpptr = LOWER(*tmpptr); mob_proto[i].player.long_descr = fread_string(mob_f, buf2); mob_proto[i].player.description = fread_string(mob_f, buf2); + mob_proto[i].player.background = NULL; + + /* Optional background block signaled by a leading 'B' marker */ + { + int letter; + + do { + letter = fgetc(mob_f); + if (letter == EOF) + break; + } while (letter == '\n' || letter == '\r'); + + if (letter == 'B') { + mob_proto[i].player.background = fread_string(mob_f, buf2); + + /* consume trailing newlines before numeric section */ + do { + letter = fgetc(mob_f); + if (letter == EOF) + break; + } while (letter == '\n' || letter == '\r'); + + if (letter != EOF) + ungetc(letter, mob_f); + } else if (letter != EOF) + ungetc(letter, mob_f); + } /* Numeric data */ if (!get_line(mob_f, line)) { @@ -3393,6 +3422,8 @@ void free_char(struct char_data *ch) free(ch->player.long_descr); if (ch->player.description) free(ch->player.description); + if (ch->player.background) + free(ch->player.background); for (i = 0; i < NUM_HIST; i++) if (GET_HISTORY(ch, i)) free_history(ch, i); @@ -3413,6 +3444,8 @@ void free_char(struct char_data *ch) free(ch->player.long_descr); if (ch->player.description && ch->player.description != mob_proto[i].player.description) free(ch->player.description); + if (ch->player.background && ch->player.background != mob_proto[i].player.background) + free(ch->player.background); /* free script proto list if it's not the prototype */ if (ch->proto_script && ch->proto_script != mob_proto[i].proto_script) free_proto_script(ch, MOB_TRIGGER); @@ -3655,6 +3688,7 @@ void init_char(struct char_data *ch) ch->player.short_descr = NULL; ch->player.long_descr = NULL; ch->player.description = NULL; + ch->player.background = NULL; GET_NUM_QUESTS(ch) = 0; ch->player_specials->saved.completed_quests = NULL; diff --git a/src/dg_mobcmd.c b/src/dg_mobcmd.c index ba5e25d..1ded8cb 100644 --- a/src/dg_mobcmd.c +++ b/src/dg_mobcmd.c @@ -948,6 +948,8 @@ ACMD(do_mtransform) tmpmob.player.long_descr = strdup(m->player.long_descr); if(m->player.description) tmpmob.player.description = strdup(m->player.description); + if(m->player.background) + tmpmob.player.background = strdup(m->player.background); tmpmob.script_id = ch->script_id; tmpmob.affected = ch->affected; diff --git a/src/genmob.c b/src/genmob.c index b02d531..9d7ea51 100644 --- a/src/genmob.c +++ b/src/genmob.c @@ -123,6 +123,10 @@ static void extract_mobile_all(mob_vnum vnum) if (ch->player.description && ch->player.description != mob_proto[i].player.description) free(ch->player.description); ch->player.description = NULL; + + if (ch->player.background && ch->player.background != mob_proto[i].player.background) + free(ch->player.background); + ch->player.background = NULL; /* free script proto list if it's not the prototype */ if (ch->proto_script && ch->proto_script != mob_proto[i].proto_script) @@ -201,6 +205,8 @@ int copy_mobile_strings(struct char_data *t, struct char_data *f) t->player.long_descr = strdup(f->player.long_descr); if (f->player.description) t->player.description = strdup(f->player.description); + if (f->player.background) + t->player.background = strdup(f->player.background); return TRUE; } @@ -214,6 +220,8 @@ int update_mobile_strings(struct char_data *t, struct char_data *f) t->player.long_descr = f->player.long_descr; if (f->player.description) t->player.description = f->player.description; + if (f->player.background) + t->player.background = f->player.background; return TRUE; } @@ -227,6 +235,8 @@ int free_mobile_strings(struct char_data *mob) free(mob->player.long_descr); if (mob->player.description) free(mob->player.description); + if (mob->player.background) + free(mob->player.background); return TRUE; } @@ -253,6 +263,8 @@ int free_mobile(struct char_data *mob) free(mob->player.long_descr); if (mob->player.description && mob->player.description != mob_proto[i].player.description) free(mob->player.description); + if (mob->player.background && mob->player.background != mob_proto[i].player.background) + free(mob->player.background); /* free script proto list if it's not the prototype */ if (mob->proto_script && mob->proto_script != mob_proto[i].proto_script) free_proto_script(mob, MOB_TRIGGER); @@ -377,12 +389,18 @@ int write_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd) { char ldesc[MAX_STRING_LENGTH]; char ddesc[MAX_STRING_LENGTH]; + char bdesc[MAX_STRING_LENGTH]; char buf[MAX_STRING_LENGTH]; ldesc[MAX_STRING_LENGTH - 1] = '\0'; ddesc[MAX_STRING_LENGTH - 1] = '\0'; + bdesc[MAX_STRING_LENGTH - 1] = '\0'; strip_cr(strncpy(ldesc, GET_LDESC(mob), MAX_STRING_LENGTH - 1)); strip_cr(strncpy(ddesc, GET_DDESC(mob), MAX_STRING_LENGTH - 1)); + if (GET_BDESC(mob)) + strip_cr(strncpy(bdesc, GET_BDESC(mob), MAX_STRING_LENGTH - 1)); + else + bdesc[0] = '\0'; int n = snprintf(buf, MAX_STRING_LENGTH, "#%d\n" @@ -390,13 +408,16 @@ int write_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd) "%s%c\n" "%s%c\n" "%s%c\n" + "%s%c\n" + "B\n" "%s%c\n", mvnum, GET_NAME(mob), STRING_TERMINATOR, GET_KEYWORDS(mob), STRING_TERMINATOR, GET_SDESC(mob), STRING_TERMINATOR, ldesc, STRING_TERMINATOR, - ddesc, STRING_TERMINATOR); + ddesc, STRING_TERMINATOR, + bdesc, STRING_TERMINATOR); if (n >= MAX_STRING_LENGTH) { mudlog(BRF, LVL_BUILDER, TRUE, diff --git a/src/genmob.h b/src/genmob.h index 971fbaa..e32a0fd 100644 --- a/src/genmob.h +++ b/src/genmob.h @@ -34,6 +34,7 @@ int write_mobile_mobprog(mob_vnum mvnum, struct char_data *mob, FILE *fd); #define GET_SDESC(mob) ((mob)->player.short_descr) #define GET_LDESC(mob) ((mob)->player.long_descr) #define GET_DDESC(mob) ((mob)->player.description) +#define GET_BDESC(mob) ((mob)->player.background) #define GET_ATTACK(mob) ((mob)->mob_specials.attack_type) #endif /* _GENMOB_H_ */ diff --git a/src/genolc.c b/src/genolc.c index 66a4249..dd6a419 100644 --- a/src/genolc.c +++ b/src/genolc.c @@ -594,22 +594,31 @@ static int export_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd) char ldesc[MAX_STRING_LENGTH]; char ddesc[MAX_STRING_LENGTH]; + char bdesc[MAX_STRING_LENGTH]; ldesc[MAX_STRING_LENGTH - 1] = '\0'; ddesc[MAX_STRING_LENGTH - 1] = '\0'; + bdesc[MAX_STRING_LENGTH - 1] = '\0'; strip_cr(strncpy(ldesc, GET_LDESC(mob), MAX_STRING_LENGTH - 1)); strip_cr(strncpy(ddesc, GET_DDESC(mob), MAX_STRING_LENGTH - 1)); + if (GET_BDESC(mob)) + strip_cr(strncpy(bdesc, GET_BDESC(mob), MAX_STRING_LENGTH - 1)); + else + bdesc[0] = '\0'; fprintf(fd, "#QQ%02d\n" "%s%c\n" "%s%c\n" "%s%c\n" + "%s%c\n" + "B\n" "%s%c\n", mvnum%100, GET_KEYWORDS(mob), STRING_TERMINATOR, GET_SDESC(mob), STRING_TERMINATOR, ldesc, STRING_TERMINATOR, - ddesc, STRING_TERMINATOR + ddesc, STRING_TERMINATOR, + bdesc, STRING_TERMINATOR ); fprintf(fd, "%d %d %d %d %d %d %d %d %d E\n" diff --git a/src/interpreter.c b/src/interpreter.c index 908dc61..6686e57 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -1803,6 +1803,41 @@ case CON_QCLASS: } } + if (!GET_BACKGROUND(d->character) || !*GET_BACKGROUND(d->character)) { + write_to_output(d, + "\r\nBefore stepping into Athas, share a bit of your character's background.\r\n" + "Guideline: aim for at least four lines that hint at where they came from,\r\n" + "who shaped them, and why they now walk the Tyr region. Touch on things like:\r\n" + " - The city-state, tribe, or caravan that claimed them.\r\n" + " - Mentors, slavers, or patrons who left a mark.\r\n" + " - A defining hardship, triumph, oath, or secret.\r\n" + " - The goal, vengeance, or hope that drives them back into the wastes.\r\n" + "\r\nExample 1:\r\n" + " Raised beneath the ziggurat of Tyr, I learned to barter gossip between\r\n" + " templars and gladiators just to stay alive. Freedom came when Kalak fell,\r\n" + " but the slave-scar on my shoulder still aches. I now search the desert\r\n" + " for the relic my clutch mates died protecting, hoping to buy their kin peace.\r\n" + "\r\nExample 2:\r\n" + " I rode caravan outrider routes from Balic until giants shattered our train.\r\n" + " Two nights buried in silt taught me to whisper with the wind and trust only\r\n" + " my erdlu. I hunt the warlord who sold us out, yet coin and company on the\r\n" + " road must come first.\r\n" + "\r\nExample 3:\r\n" + " Born outside Raam, I was tempered by obsidian shards and psionic murmurs.\r\n" + " A defiler ruined our oasis, so I swore to hound such spell-scars wherever\r\n" + " they bloom. Rumor of a hidden well near Tyr is the lone hope that guides me.\r\n" + "\r\nType your background now. Use '/s' on a blank line when you finish.\r\n" + "If you'd rather keep it secret, just save immediately and we'll note the mystery.\r\n\r\n"); + d->backstr = NULL; + if (GET_BACKGROUND(d->character) && *GET_BACKGROUND(d->character)) + d->backstr = strdup(GET_BACKGROUND(d->character)); + d->str = &d->character->player.background; + d->max_str = PLR_DESC_LENGTH; + STATE(d) = CON_PLR_BACKGROUND; + send_editor_help(d); + return; + } + /* Proceed into the world */ load_result = enter_player_game(d); send_to_char(d->character, "%s", CONFIG_WELC_MESSG); diff --git a/src/medit.c b/src/medit.c index f8537b9..76e7a09 100644 --- a/src/medit.c +++ b/src/medit.c @@ -191,6 +191,7 @@ static void medit_setup_new(struct descriptor_data *d) GET_SDESC(mob) = strdup("the unfinished npc"); GET_LDESC(mob) = strdup("An unfinished npc stands here.\r\n"); GET_DDESC(mob) = strdup("It looks unfinished.\r\n"); + GET_BACKGROUND(mob) = strdup("No background has been recorded.\r\n"); SCRIPT(mob) = NULL; mob->proto_script = OLC_SCRIPT(d) = NULL; @@ -412,10 +413,12 @@ static void medit_disp_menu(struct descriptor_data *d) { struct char_data *mob; char flags[MAX_STRING_LENGTH], flag2[MAX_STRING_LENGTH]; + const char *background; mob = OLC_MOB(d); get_char_colors(d->character); clear_screen(d); + background = GET_BACKGROUND(mob) ? GET_BACKGROUND(mob) : "\r\n"; write_to_output(d, "-- Mob Number: [%s%d%s]\r\n" @@ -442,11 +445,12 @@ static void medit_disp_menu(struct descriptor_data *d) "%s8%s) Default : %s%s\r\n" "%s9%s) Attack : %s%s\r\n" "%s0%s) Stats Menu...\r\n" - "%s-%s) Skills Menu...\r\n" + "%s-%s) Skills Menu...\r\n" "%sA%s) NPC Flags : %s%s\r\n" "%sB%s) AFF Flags : %s%s\r\n" - "%sS%s) Script : %s%s\r\n" - "%sW%s) Copy mob\r\n" + "%sC%s) Background:-\r\n%s%s\r\n" + "%sS%s) Script : %s%s\r\n" + "%sW%s) Copy mob\r\n" "%sX%s) Delete mob\r\n" "%sQ%s) Quit\r\n" "Enter choice : ", @@ -458,7 +462,8 @@ static void medit_disp_menu(struct descriptor_data *d) grn, nrm, grn, nrm, cyn, flags, grn, nrm, cyn, flag2, - grn, nrm, cyn, OLC_SCRIPT(d) ?"Set.":"Not Set.", + grn, nrm, yel, background, + grn, nrm, cyn, OLC_SCRIPT(d) ?"Set.":"Not Set.", grn, nrm, grn, nrm, grn, nrm @@ -686,6 +691,18 @@ void medit_parse(struct descriptor_data *d, char *arg) OLC_MODE(d) = MEDIT_AFF_FLAGS; medit_disp_aff_flags(d); return; + case 'c': + case 'C': + OLC_MODE(d) = MEDIT_BACKGROUND; + send_editor_help(d); + write_to_output(d, "Enter mob background:\r\n\r\n"); + if (OLC_MOB(d)->player.background) { + write_to_output(d, "%s", OLC_MOB(d)->player.background); + oldtext = strdup(OLC_MOB(d)->player.background); + } + string_write(d, &OLC_MOB(d)->player.background, MAX_MOB_DESC, 0, oldtext); + OLC_VAL(d) = 1; + return; case 'w': case 'W': write_to_output(d, "Copy what mob? "); @@ -990,6 +1007,11 @@ void medit_parse(struct descriptor_data *d, char *arg) mudlog(BRF, LVL_BUILDER, TRUE, "SYSERR: OLC: medit_parse(): Reached D_DESC case!"); write_to_output(d, "Oops...\r\n"); break; + case MEDIT_BACKGROUND: + cleanup_olc(d, CLEANUP_ALL); + mudlog(BRF, LVL_BUILDER, TRUE, "SYSERR: OLC: medit_parse(): Reached BACKGROUND case!"); + write_to_output(d, "Oops...\r\n"); + break; case MEDIT_NPC_FLAGS: if ((i = atoi(arg)) <= 0) @@ -1181,6 +1203,7 @@ void medit_string_cleanup(struct descriptor_data *d, int terminator) switch (OLC_MODE(d)) { case MEDIT_D_DESC: + case MEDIT_BACKGROUND: default: medit_disp_menu(d); break; diff --git a/src/modify.c b/src/modify.c index 8b270bc..ffd8bd3 100644 --- a/src/modify.c +++ b/src/modify.c @@ -32,6 +32,7 @@ static char *next_page(char *str, struct char_data *ch); static int count_pages(char *str, struct char_data *ch); static void playing_string_cleanup(struct descriptor_data *d, int action); static void exdesc_string_cleanup(struct descriptor_data *d, int action); +static void background_string_cleanup(struct descriptor_data *d, int action); /* Local (file scope) global variables */ /* @deprecated string_fields appears to be no longer be used. @@ -217,6 +218,7 @@ void string_add(struct descriptor_data *d, char *str) { CON_TEDIT , tedit_string_cleanup }, { CON_TRIGEDIT, trigedit_string_cleanup }, { CON_PLR_DESC , exdesc_string_cleanup }, + { CON_PLR_BACKGROUND , background_string_cleanup }, { CON_PLAYING, playing_string_cleanup }, { CON_HEDIT, hedit_string_cleanup }, { CON_QEDIT , qedit_string_cleanup }, @@ -302,6 +304,27 @@ static void exdesc_string_cleanup(struct descriptor_data *d, int action) STATE(d) = CON_MENU; } +static void background_string_cleanup(struct descriptor_data *d, int action) +{ + if (d->character) { + if (!GET_BACKGROUND(d->character) || !*GET_BACKGROUND(d->character)) { + if (GET_BACKGROUND(d->character)) + free(GET_BACKGROUND(d->character)); + GET_BACKGROUND(d->character) = strdup("This character prefers to keep their past unspoken.\r\n"); + if (action == STRINGADD_ABORT) + write_to_output(d, "Background entry canceled. We'll note that your past remains a mystery.\r\n"); + else + write_to_output(d, "No background submitted. We'll note that your past remains a mystery.\r\n"); + } else if (action == STRINGADD_ABORT) + write_to_output(d, "Background entry canceled.\r\n"); + else + write_to_output(d, "Background saved.\r\n"); + } + + write_to_output(d, "%s", CONFIG_MENU); + STATE(d) = CON_MENU; +} + /* By Michael Buselli. Traverse down the string until the begining of the next * page has been reached. Return NULL if this is the last page of the string. */ static char *next_page(char *str, struct char_data *ch) diff --git a/src/oasis.h b/src/oasis.h index c7a21fd..e55a2fd 100644 --- a/src/oasis.h +++ b/src/oasis.h @@ -258,38 +258,39 @@ extern const char *nrm, *grn, *cyn, *yel; #define MEDIT_S_DESC 3 #define MEDIT_L_DESC 4 #define MEDIT_D_DESC 5 -#define MEDIT_NPC_FLAGS 6 -#define MEDIT_AFF_FLAGS 7 -#define MEDIT_CONFIRM_SAVESTRING 8 -#define MEDIT_STATS_MENU 9 -#define MEDIT_SKILL_MENU 10 -#define MEDIT_SKILL_EDIT 11 +#define MEDIT_BACKGROUND 6 +#define MEDIT_NPC_FLAGS 7 +#define MEDIT_AFF_FLAGS 8 +#define MEDIT_CONFIRM_SAVESTRING 9 +#define MEDIT_STATS_MENU 10 +#define MEDIT_SKILL_MENU 11 +#define MEDIT_SKILL_EDIT 12 /* Numerical responses. */ -#define MEDIT_NUMERICAL_RESPONSE 12 -#define MEDIT_SEX 13 -#define MEDIT_NUM_HP_DICE 14 -#define MEDIT_SIZE_HP_DICE 15 -#define MEDIT_ADD_HP 16 -#define MEDIT_POS 17 -#define MEDIT_DEFAULT_POS 18 -#define MEDIT_ATTACK 19 -#define MEDIT_LEVEL 20 -#define MEDIT_ALIGNMENT 21 -#define MEDIT_DELETE 22 -#define MEDIT_COPY 23 -#define MEDIT_STR 24 -#define MEDIT_INT 25 -#define MEDIT_WIS 26 -#define MEDIT_DEX 27 -#define MEDIT_CON 28 -#define MEDIT_CHA 29 -#define MEDIT_SAVE_STR 30 -#define MEDIT_SAVE_DEX 31 -#define MEDIT_SAVE_CON 32 -#define MEDIT_SAVE_INT 33 -#define MEDIT_SAVE_WIS 34 -#define MEDIT_SAVE_CHA 35 +#define MEDIT_NUMERICAL_RESPONSE 13 +#define MEDIT_SEX 14 +#define MEDIT_NUM_HP_DICE 15 +#define MEDIT_SIZE_HP_DICE 16 +#define MEDIT_ADD_HP 17 +#define MEDIT_POS 18 +#define MEDIT_DEFAULT_POS 19 +#define MEDIT_ATTACK 20 +#define MEDIT_LEVEL 21 +#define MEDIT_ALIGNMENT 22 +#define MEDIT_DELETE 23 +#define MEDIT_COPY 24 +#define MEDIT_STR 25 +#define MEDIT_INT 26 +#define MEDIT_WIS 27 +#define MEDIT_DEX 28 +#define MEDIT_CON 29 +#define MEDIT_CHA 30 +#define MEDIT_SAVE_STR 31 +#define MEDIT_SAVE_DEX 32 +#define MEDIT_SAVE_CON 33 +#define MEDIT_SAVE_INT 34 +#define MEDIT_SAVE_WIS 35 +#define MEDIT_SAVE_CHA 36 /* Submodes of SEDIT connectedness. */ #define SEDIT_MAIN_MENU 0 diff --git a/src/players.c b/src/players.c index f438442..811aaba 100644 --- a/src/players.c +++ b/src/players.c @@ -334,7 +334,8 @@ int load_char(const char *name, struct char_data *ch) break; case 'B': - if (!strcmp(tag, "Badp")) GET_BAD_PWS(ch) = atoi(line); + if (!strcmp(tag, "Back")) ch->player.background = fread_string(fl, buf2); + else if (!strcmp(tag, "Badp")) GET_BAD_PWS(ch) = atoi(line); else if (!strcmp(tag, "Bank")) GET_BANK_GOLD(ch) = atoi(line); else if (!strcmp(tag, "Brth")) ch->player.time.birth = atol(line); break; @@ -585,6 +586,11 @@ void save_char(struct char_data * ch) strip_cr(buf); fprintf(fl, "Desc:\n%s~\n", buf); } + if (ch->player.background && *ch->player.background) { + strcpy(buf, ch->player.background); + strip_cr(buf); + fprintf(fl, "Back:\n%s~\n", buf); + } if (POOFIN(ch)) fprintf(fl, "PfIn: %s\n", POOFIN(ch)); if (POOFOUT(ch)) fprintf(fl, "PfOt: %s\n", POOFOUT(ch)); if (GET_SEX(ch) != PFDEF_SEX) fprintf(fl, "Sex : %d\n", GET_SEX(ch)); diff --git a/src/structs.h b/src/structs.h index 51c13c0..977c2eb 100644 --- a/src/structs.h +++ b/src/structs.h @@ -338,6 +338,7 @@ #define CON_PREFEDIT 30 /**< OLC mode - preference edit */ #define CON_IBTEDIT 31 /**< OLC mode - idea/bug/typo edit */ #define CON_MSGEDIT 32 /**< OLC mode - message editor */ +#define CON_PLR_BACKGROUND 33 /**< Entering a new character background */ #define CON_GET_PROTOCOL 33 /**< Used at log-in while attempting to get protocols > */ /* OLC States range - used by IS_IN_OLC and IS_PLAYING */ @@ -880,6 +881,7 @@ struct char_player_data char *short_descr; /**< PC / NPC short description */ char *long_descr; /**< PC / NPC long description */ char *description; /**< PC / NPC main descriptions */ + char *background; /**< PC / NPC background / history text */ byte sex; /**< PC / NPC sex */ byte chclass; /**< PC / NPC class */ byte level; /**< PC / NPC level */ diff --git a/src/utils.h b/src/utils.h index 8575190..83d09f0 100644 --- a/src/utils.h +++ b/src/utils.h @@ -517,6 +517,9 @@ do \ /** Appearance-based description for displays (e.g. short look text). */ #define GET_SHORT_DESC(ch) ((ch)->player.short_descr) +/** Character background / history text. */ +#define GET_BACKGROUND(ch) ((ch)->player.background) + /** Safe name for room messages. */ #define GET_DISPLAY_NAME(ch) (GET_NAME(ch) && *GET_NAME(ch) ? GET_NAME(ch) : "someone")