From cfe59d3e044d18fe7f794055b27431bec41d9091 Mon Sep 17 00:00:00 2001 From: Rumble Date: Wed, 11 Jun 2008 00:34:08 +0000 Subject: [PATCH] [Jun 11 2008] - Rumble Added notification via prompt for new MOTD and news entries. (thanks Jamdog) Added all option to the restore command. (thanks Jamdog) Added new trigger variable hasattached. (thanks Fizban) --- changelog | 7 +++++++ src/act.informative.c | 3 ++- src/act.wizard.c | 28 ++++++++++++++++++++++++---- src/comm.c | 17 +++++++++++++++++ src/db.c | 17 +++++++++++++++++ src/dg_scripts.c | 13 +++++++++++++ src/dg_scripts.h | 1 + src/dg_variables.c | 24 ++++++++++++++++++++++++ src/pfdefaults.h | 2 ++ src/players.c | 11 ++++++++++- src/spec_assign.c | 41 +++++++++++++++++++++++++++++++++++++++++ src/structs.h | 2 ++ src/tedit.c | 6 ++++++ src/utils.h | 4 +++- 14 files changed, 169 insertions(+), 7 deletions(-) diff --git a/changelog b/changelog index fb9793e..1dd69cc 100644 --- a/changelog +++ b/changelog @@ -3,6 +3,13 @@ help, find any bugs, or have ideas for improvement please stop by TBA at telnet://tbamud.com:9091 or email rumble@tbamud.com --Rumble tbaMUD 3.56 +[Jun 11 2008] - Rumble + Added notification via prompt for new MOTD and news entries. (thanks Jamdog) + Added all option to the restore command. (thanks Jamdog) + Added new trigger variable hasattached. (thanks Fizban) +[Jun 10 2008] - Rumble + Added spec proc type under stat. (thanks Jamdog) + Only allow immortals to talk while invis and be displayed as "someone." (thanks Frenze) [May 27 2008] - Rumble Fixed list_obj_to_char from only checking invisibility on first object of the same vnum. (thanks Laoris) Added object stacking when looking at a character's inventory. (thanks Jamdog) diff --git a/src/act.informative.c b/src/act.informative.c index 6e62b15..0e1dd76 100644 --- a/src/act.informative.c +++ b/src/act.informative.c @@ -251,7 +251,6 @@ static void diag_char_to_char(struct char_data *i, struct char_data *ch) static void look_at_char(struct char_data *i, struct char_data *ch) { int j, found; - struct obj_data *tmp_obj; if (!ch->desc) return; @@ -1480,6 +1479,7 @@ ACMD(do_gen_ps) page_string(ch->desc, credits, 0); break; case SCMD_NEWS: + GET_LAST_NEWS(ch) = time(0); page_string(ch->desc, news, 0); break; case SCMD_INFO: @@ -1498,6 +1498,7 @@ ACMD(do_gen_ps) page_string(ch->desc, policies, 0); break; case SCMD_MOTD: + GET_LAST_MOTD(ch) = time(0); page_string(ch->desc, motd, 0); break; case SCMD_IMOTD: diff --git a/src/act.wizard.c b/src/act.wizard.c index e059b9a..36ef965 100644 --- a/src/act.wizard.c +++ b/src/act.wizard.c @@ -47,6 +47,7 @@ static void obj_checkload(struct char_data *ch, obj_vnum ovnum); static void trg_checkload(struct char_data *ch, trig_vnum tvnum); static void mod_llog_entry(struct last_entry *llast,int type); +const char *get_spec_func_name(SPECIAL(*func)); int purge_room(room_rnum room) { @@ -496,7 +497,7 @@ static void do_stat_room(struct char_data *ch, struct room_data *rm) CCNRM(ch, C_NRM), IN_ROOM(ch), (long) rm->number + ROOM_ID_BASE, buf2); sprintbitarray(rm->room_flags, room_bits, RF_ARRAY_MAX, buf2); - send_to_char(ch, "SpecProc: %s, Flags: %s\r\n", rm->func == NULL ? "None" : "Exists", buf2); + send_to_char(ch, "SpecProc: %s, Flags: %s\r\n", rm->func == NULL ? "None" : get_spec_func_name(rm->func), buf2); send_to_char(ch, "Description:\r\n%s", rm->description ? rm->description : " None.\r\n"); @@ -583,8 +584,8 @@ static void do_stat_object(struct char_data *ch, struct obj_data *j) vnum = GET_OBJ_VNUM(j); sprinttype(GET_OBJ_TYPE(j), item_types, buf, sizeof(buf)); send_to_char(ch, "VNum: [%s%5d%s], RNum: [%5d], Idnum: [%5ld], Type: %s, SpecProc: %s\r\n", - CCGRN(ch, C_NRM), vnum, CCNRM(ch, C_NRM), GET_OBJ_RNUM(j), GET_ID(j), buf, - GET_OBJ_SPEC(j) ? "Exists" : "None"); + CCGRN(ch, C_NRM), vnum, CCNRM(ch, C_NRM), GET_OBJ_RNUM(j), GET_ID(j), buf, + GET_OBJ_SPEC(j) ? (get_spec_func_name(GET_OBJ_SPEC(j))) : "None"); send_to_char(ch, "L-Desc: '%s%s%s'\r\n", CCYEL(ch, C_NRM), j->description ? j->description : "", @@ -834,7 +835,7 @@ static void do_stat_character(struct char_data *ch, struct char_data *k) if (IS_MOB(k)) send_to_char(ch, "Mob Spec-Proc: %s, NPC Bare Hand Dam: %dd%d\r\n", - (mob_index[GET_MOB_RNUM(k)].func ? "Exists" : "None"), + (mob_index[GET_MOB_RNUM(k)].func ? get_spec_func_name(mob_index[GET_MOB_RNUM(k)].func) : "None"), k->mob_specials.damnodice, k->mob_specials.damsizedice); for (i = 0, j = k->carrying; j; j = j->next_content, i++); @@ -1517,11 +1518,30 @@ ACMD(do_restore) { char buf[MAX_INPUT_LENGTH]; struct char_data *vict; + struct descriptor_data *j; int i; one_argument(argument, buf); if (!*buf) send_to_char(ch, "Whom do you wish to restore?\r\n"); + else if (is_abbrev(buf, "all")) + { + mudlog(NRM, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "(GC) %s restored all",GET_NAME(ch)); + + for (j = descriptor_list; j; j = j->next) + { + if (!IS_PLAYING(j) || !(vict = j->character) || GET_LEVEL(vict) >= LVL_IMMORT) + continue; + + GET_HIT(vict) = GET_MAX_HIT(vict); + GET_MANA(vict) = GET_MAX_MANA(vict); + GET_MOVE(vict) = GET_MAX_MOVE(vict); + + update_pos(vict); + send_to_char(ch, "%s has been fully healed.\r\n", GET_NAME(vict)); + act("You have been fully healed by $N!", FALSE, vict, 0, ch, TO_CHAR); + } + } else if (!(vict = get_char_vis(ch, buf, NULL, FIND_CHAR_WORLD))) send_to_char(ch, "%s", CONFIG_NOPERSON); else if (!IS_NPC(vict) && ch != vict && GET_LEVEL(vict) >= GET_LEVEL(ch)) diff --git a/src/comm.c b/src/comm.c index db77817..0edce67 100644 --- a/src/comm.c +++ b/src/comm.c @@ -85,6 +85,9 @@ #define INVALID_SOCKET (-1) #endif +extern time_t motdmod; +extern time_t newsmod; + /* locally defined globals, used externally */ struct descriptor_data *descriptor_list = NULL; /* master desc list */ int buf_largecount = 0; /* # of large buffers which exist */ @@ -1212,6 +1215,20 @@ static char *make_prompt(struct descriptor_data *d) len += count; } + if (GET_LAST_NEWS(d->character) < newsmod) + { + count = snprintf(prompt + len, sizeof(prompt) - len, "(news) "); + if (count >= 0) + len += count; + } + + if (GET_LAST_MOTD(d->character) < motdmod) + { + count = snprintf(prompt + len, sizeof(prompt) - len, "(motd) "); + if (count >= 0) + len += count; + } + if (len < sizeof(prompt)) strncat(prompt, "> ", sizeof(prompt) - len - 1); /* strncat: OK */ } else if (STATE(d) == CON_PLAYING && IS_NPC(d->character)) diff --git a/src/db.c b/src/db.c index 300f3f7..43838d1 100644 --- a/src/db.c +++ b/src/db.c @@ -36,6 +36,7 @@ #include "modify.h" #include "shop.h" #include "quest.h" +#include /* declarations of most of the 'global' variables */ struct config_data config_info; /* Game configuration list. */ @@ -107,6 +108,9 @@ struct help_index_element *help_table = NULL; struct social_messg *soc_mess_list = NULL; /* list of socials */ int top_of_socialt = -1; /* number of socials */ + time_t newsmod; /* Time news file was last modified. */ + time_t motdmod; /* Time motd file was last modified. */ + struct time_info_data time_info; /* the infomation about the time */ struct weather_data weather_info; /* the infomation about the weather */ struct player_special_data dummy_mob; /* dummy spec area for mobs */ @@ -2878,6 +2882,7 @@ static int file_to_string(const char *name, char *buf) FILE *fl; char tmp[READ_SIZE + 3]; int len; + struct stat statbuf; *buf = '\0'; @@ -2886,6 +2891,18 @@ static int file_to_string(const char *name, char *buf) return (-1); } + /* Grab the date/time the file was last edited */ + if (!strcmp(name, NEWS_FILE)) + { + fstat(fileno(fl), &statbuf); + newsmod = statbuf.st_mtime; + } + if (!strcmp(name, MOTD_FILE)) + { + fstat(fileno(fl), &statbuf); + motdmod = statbuf.st_mtime; + } + for (;;) { if (!fgets(tmp, READ_SIZE, fl)) /* EOF check */ break; diff --git a/src/dg_scripts.c b/src/dg_scripts.c index c1d7d8f..1f9febc 100644 --- a/src/dg_scripts.c +++ b/src/dg_scripts.c @@ -3044,3 +3044,16 @@ bool check_flags_by_name_ar(int *array, int numflags, char *search, const char * return FALSE; } + +int trig_is_attached(struct script_data *sc, int trig_num) +{ + trig_data *t; + + if (!sc || !TRIGGERS(sc)) return 0; + + for (t = TRIGGERS(sc); t; t = t->next) + if (GET_TRIG_VNUM(t) == trig_num) + return 1; + + return 0; +} diff --git a/src/dg_scripts.h b/src/dg_scripts.h index a94d0cf..4be8433 100644 --- a/src/dg_scripts.h +++ b/src/dg_scripts.h @@ -298,6 +298,7 @@ bool check_flags_by_name_ar(int *array, int numflags, char *search, const char * void read_saved_vars_ascii(FILE *file, struct char_data *ch, int count); void save_char_vars_ascii(FILE *file, struct char_data *ch); int perform_set_dg_var(struct char_data *ch, struct char_data *vict, char *val_arg); +int trig_is_attached(struct script_data *sc, int trig_num); /* To maintain strict-aliasing we'll have to do this trick with a union */ /* Thanks to Chris Gilbert for reminding me that there are other options. */ diff --git a/src/dg_variables.c b/src/dg_variables.c index a1f4a12..87e65e0 100644 --- a/src/dg_variables.c +++ b/src/dg_variables.c @@ -669,6 +669,14 @@ void find_replacement(void *go, struct script_data *sc, trig_data *trig, else snprintf(str, slen, "%d", char_has_item(subfield, c)); } + else if (!str_cmp(field, "hasattached")) { + if (!(subfield && *subfield) || !IS_NPC(c)) + *str = '\0'; + else { + i = atoi(subfield); + snprintf(str, slen, "%d", trig_is_attached(SCRIPT(c), i)); + } + } else if (!str_cmp(field, "hisher")) snprintf(str, slen, "%s", HSHR(c)); @@ -1118,6 +1126,14 @@ o->contains) ? "1" : "0")); else strcpy(str, "0"); } + else if (!str_cmp(field, "hasattached")) { + if (!(subfield && *subfield)) + *str = '\0'; + else { + i = atoi(subfield); + snprintf(str, slen, "%d", trig_is_attached(SCRIPT(o), i)); + } + } break; case 'i': if (!str_cmp(field, "id")) @@ -1309,6 +1325,14 @@ o->contains) ? "1" : "0")); else *str = '\0'; } + else if (!str_cmp(field, "hasattached")) { + if (!(subfield && *subfield)) + *str = '\0'; + else { + i = atoi(subfield); + snprintf(str, slen, "%d", trig_is_attached(SCRIPT(r), i)); + } + } else if (!str_cmp(field, "zonenumber")) snprintf(str, slen, "%d", zone_table[r->zone].number); else if (!str_cmp(field, "zonename")) diff --git a/src/pfdefaults.h b/src/pfdefaults.h index 2c5e8db..c0eba7e 100644 --- a/src/pfdefaults.h +++ b/src/pfdefaults.h @@ -59,5 +59,7 @@ #define PFDEF_QUESTCOUNT 0 #define PFDEF_COMPQUESTS 0 #define PFDEF_CURRQUEST NOTHING +#define PFDEF_LASTMOTD 0 +#define PFDEF_LASTNEWS 0 #endif /* _PFDEFAULTS_H_ */ diff --git a/src/players.c b/src/players.c index 1f10282..5bc56f3 100644 --- a/src/players.c +++ b/src/players.c @@ -264,7 +264,9 @@ int load_char(const char *name, struct char_data *ch) GET_QUEST_COUNTER(ch) = PFDEF_QUESTCOUNT; GET_QUEST(ch) = PFDEF_CURRQUEST; GET_NUM_QUESTS(ch) = PFDEF_COMPQUESTS; - + GET_LAST_MOTD(ch) = PFDEF_LASTMOTD; + GET_LAST_NEWS(ch) = PFDEF_LASTNEWS; + for (i = 0; i < AF_ARRAY_MAX; i++) AFF_FLAGS(ch)[i] = PFDEF_AFFFLAGS; for (i = 0; i < PM_ARRAY_MAX; i++) @@ -353,6 +355,8 @@ int load_char(const char *name, struct char_data *ch) if (!strcmp(tag, "Last")) ch->player.time.logon = atol(line); else if (!strcmp(tag, "Lern")) GET_PRACTICES(ch) = atoi(line); else if (!strcmp(tag, "Levl")) GET_LEVEL(ch) = atoi(line); + else if (!strcmp(tag, "Lmot")) GET_LAST_MOTD(ch) = atoi(line); + else if (!strcmp(tag, "Lnew")) GET_LAST_NEWS(ch) = atoi(line); break; case 'M': @@ -540,6 +544,11 @@ void save_char(struct char_data * ch) fprintf(fl, "Plyd: %d\n", ch->player.time.played); fprintf(fl, "Last: %ld\n", (long)ch->player.time.logon); + if (GET_LAST_MOTD(ch) != PFDEF_LASTMOTD) + fprintf(fl, "Lmot: %d\n", (int)GET_LAST_MOTD(ch)); + if (GET_LAST_NEWS(ch) != PFDEF_LASTNEWS) + fprintf(fl, "Lnew: %d\n", (int)GET_LAST_NEWS(ch)); + if (GET_HOST(ch)) fprintf(fl, "Host: %s\n", GET_HOST(ch)); if (GET_HEIGHT(ch) != PFDEF_HEIGHT) fprintf(fl, "Hite: %d\n", GET_HEIGHT(ch)); if (GET_WEIGHT(ch) != PFDEF_HEIGHT) fprintf(fl, "Wate: %d\n", GET_WEIGHT(ch)); diff --git a/src/spec_assign.c b/src/spec_assign.c index 99d5cba..8372e74 100644 --- a/src/spec_assign.c +++ b/src/spec_assign.c @@ -19,6 +19,9 @@ #include "boards.h" #include "mail.h" +SPECIAL(questmaster); +SPECIAL(shop_keeper); + /* local (file scope only) functions */ static void ASSIGNROOM(room_vnum room, SPECIAL(fname)); static void ASSIGNMOB(mob_vnum mob, SPECIAL(fname)); @@ -161,3 +164,41 @@ void assign_rooms(void) if (ROOM_FLAGGED(i, ROOM_DEATH)) world[i].func = dump; } + +struct spec_func_data { + char *name; + SPECIAL(*func); +}; + +struct spec_func_data spec_func_list[] = { + {"Mayor", mayor }, + {"Snake", snake }, + {"Thief", thief }, + {"Magic User", magic_user }, + {"Puff", puff }, + {"Fido", fido }, + {"Janitor", janitor }, + {"Cityguard", cityguard }, + {"Postmaster", postmaster }, + {"Receptionist", receptionist }, + {"Cryogenicist", cryogenicist}, + {"Bulletin Board", gen_board }, + {"Bank", bank }, + {"Pet Shop", pet_shops }, + {"Dump", dump }, + {"Guildmaster", guild }, + {"Guild Guard", guild_guard }, + {"Questmaster", questmaster }, + {"Shopkeeper", shop_keeper }, + {"\n", NULL} +}; + +const char *get_spec_func_name(SPECIAL(*func)) +{ + int i; + for (i=0; *(spec_func_list[i].name) != '\n'; i++) { + if (func == spec_func_list[i].func) return (spec_func_list[i].name); + } + return NULL; +} + diff --git a/src/structs.h b/src/structs.h index b7e30e4..33efd67 100644 --- a/src/structs.h +++ b/src/structs.h @@ -910,6 +910,8 @@ struct player_special_data_saved int current_quest; /**< vnum of current quest */ int quest_time; /**< time left on current quest */ int quest_counter; /**< Count of targets left to get */ + time_t lastmotd; /**< Last time player read motd */ + time_t lastnews; /**< Last time player read news */ }; /** Specials needed only by PCs, not NPCs. Space for this structure is diff --git a/src/tedit.c b/src/tedit.c index 556c4e6..9ced3a0 100644 --- a/src/tedit.c +++ b/src/tedit.c @@ -17,6 +17,8 @@ #include "improved-edit.h" #include "modify.h" +extern time_t motdmod; +extern time_t newsmod; void tedit_string_cleanup(struct descriptor_data *d, int terminator) { @@ -38,6 +40,10 @@ void tedit_string_cleanup(struct descriptor_data *d, int terminator) fclose(fl); mudlog(CMP, LVL_GOD, TRUE, "OLC: %s saves '%s'.", GET_NAME(d->character), storage); write_to_output(d, "Saved.\r\n"); + if (!strcmp(storage, NEWS_FILE)) + newsmod = time(0); + if (!strcmp(storage, MOTD_FILE)) + motdmod = time(0); } break; case STRINGADD_ABORT: diff --git a/src/utils.h b/src/utils.h index 7f2c49a..4963fc4 100644 --- a/src/utils.h +++ b/src/utils.h @@ -502,6 +502,8 @@ void char_from_furniture(struct char_data *ch); #define GET_PREF(ch) ((ch)->pref) /** Get host name or ip of ch. */ #define GET_HOST(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->host)) +#define GET_LAST_MOTD(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.lastmotd)) +#define GET_LAST_NEWS(ch) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.lastnews)) /** Get channel history i for ch. */ #define GET_HISTORY(ch, i) CHECK_PLAYER_SPECIAL((ch), ((ch)->player_specials->saved.comm_hist[i])) /** Return the page length (height) for ch. */ @@ -722,7 +724,7 @@ void char_from_furniture(struct char_data *ch); CAN_SEE_OBJ((ch),(obj))) /** If vict can see ch, return ch name, else return "someone". */ -#define PERS(ch, vict) (CAN_SEE(vict, ch) ? GET_NAME(ch) : "someone") +#define PERS(ch, vict) (CAN_SEE(vict, ch) ? GET_NAME(ch) : (GET_LEVEL(ch) > LVL_IMMORT ? "an immortal" : "someone")) /** If vict can see obj, return obj short description, else return * "something". */