Added happyhour feature and game_info function

This commit is contained in:
JamDog
2010-11-06 18:14:07 +00:00
parent 2c912fe623
commit 88fb85b126
14 changed files with 340 additions and 98 deletions

View File

@@ -36,6 +36,8 @@ Xlist (mlist, olist, rlist, zlist, slist, tlist, qlist)
(lots of major bugfixes too) (lots of major bugfixes too)
@ @
[Nov 06 2010] - Jamdog [Nov 06 2010] - Jamdog
Added HappyHour feature
Added game_info function for sending global messages to all players
Added ability to change player/mob level or class in scripts Added ability to change player/mob level or class in scripts
The medit mob flags menu now only shows valid flags (thanks Kyle) The medit mob flags menu now only shows valid flags (thanks Kyle)
Skillset now warns imms when the player shouldn't have a skill (thanks Rumble) Skillset now warns imms when the player shouldn't have a skill (thanks Rumble)

View File

@@ -237,6 +237,7 @@ ACMD(do_use);
/* Functions without subcommands */ /* Functions without subcommands */
ACMD(do_display); ACMD(do_display);
ACMD(do_group); ACMD(do_group);
ACMD(do_happyhour);
ACMD(do_hide); ACMD(do_hide);
ACMD(do_not_here); ACMD(do_not_here);
ACMD(do_practice); ACMD(do_practice);

View File

@@ -1331,6 +1331,10 @@ ACMD(do_who)
send_to_char(ch, "One lonely character displayed.\r\n"); send_to_char(ch, "One lonely character displayed.\r\n");
else else
send_to_char(ch, "%d characters displayed.\r\n", num_can_see); send_to_char(ch, "%d characters displayed.\r\n", num_can_see);
if (IS_HAPPYHOUR > 0){
send_to_char(ch, "It's a Happy Hour! Type @Rhappyhour@W to see the current bonuses.\r\n");
}
} }
#define USERS_FORMAT \ #define USERS_FORMAT \

View File

@@ -859,3 +859,116 @@ ACMD(do_gen_tog)
return; return;
} }
void show_happyhour(struct char_data *ch)
{
char happyexp[80], happygold[80], happyqp[80];
int secs_left;
if ((IS_HAPPYHOUR) || (GET_LEVEL(ch) >= LVL_GRGOD))
{
if (HAPPY_TIME)
secs_left = ((HAPPY_TIME - 1) * SECS_PER_MUD_HOUR) + next_tick;
else
secs_left = 0;
sprintf(happyqp, "%s+%d%%%s to Questpoints per quest\r\n", CCYEL(ch, C_NRM), HAPPY_QP, CCNRM(ch, C_NRM));
sprintf(happygold, "%s+%d%%%s to Gold gained per kill\r\n", CCYEL(ch, C_NRM), HAPPY_GOLD, CCNRM(ch, C_NRM));
sprintf(happyexp, "%s+%d%%%s to Experience per kill\r\n", CCYEL(ch, C_NRM), HAPPY_EXP, CCNRM(ch, C_NRM));
send_to_char(ch, "tbaMUD Happy Hour!\r\n"
"------------------\r\n"
"%s%s%sTime Remaining: %s%d%s hours %s%d%s mins %s%d%s secs\r\n",
(IS_HAPPYEXP || (GET_LEVEL(ch) >= LVL_GOD)) ? happyexp : "",
(IS_HAPPYGOLD || (GET_LEVEL(ch) >= LVL_GOD)) ? happygold : "",
(IS_HAPPYQP || (GET_LEVEL(ch) >= LVL_GOD)) ? happyqp : "",
CCYEL(ch, C_NRM), (secs_left / 3600), CCNRM(ch, C_NRM),
CCYEL(ch, C_NRM), (secs_left % 3600) / 60, CCNRM(ch, C_NRM),
CCYEL(ch, C_NRM), (secs_left % 60), CCNRM(ch, C_NRM) );
}
else
{
send_to_char(ch, "Sorry, there is currently no happy hour!\r\n");
}
}
ACMD(do_happyhour)
{
char arg[MAX_INPUT_LENGTH], val[MAX_INPUT_LENGTH];
int num;
if (GET_LEVEL(ch) < LVL_GOD)
{
show_happyhour(ch);
return;
}
/* Only Imms get here, so check args */
two_arguments(argument, arg, val);
if (is_abbrev(arg, "experience"))
{
num = MIN(MAX((atoi(val)), 0), 1000);
HAPPY_EXP = num;
send_to_char(ch, "Happy Hour Exp rate set to +%d%%\r\n", HAPPY_EXP);
}
else if ((is_abbrev(arg, "gold")) || (is_abbrev(arg, "coins")))
{
num = MIN(MAX((atoi(val)), 0), 1000);
HAPPY_GOLD = num;
send_to_char(ch, "Happy Hour Gold rate set to +%d%%\r\n", HAPPY_GOLD);
}
else if ((is_abbrev(arg, "time")) || (is_abbrev(arg, "ticks")))
{
num = MIN(MAX((atoi(val)), 0), 1000);
if (HAPPY_TIME && !num)
game_info("Happyhour has been stopped!");
else if (!HAPPY_TIME && num)
game_info("A Happyhour has started!");
HAPPY_TIME = num;
send_to_char(ch, "Happy Hour Time set to %d ticks (%d hours %d mins and %d secs)\r\n",
HAPPY_TIME,
(HAPPY_TIME*SECS_PER_MUD_HOUR)/3600,
((HAPPY_TIME*SECS_PER_MUD_HOUR)%3600) / 60,
(HAPPY_TIME*SECS_PER_MUD_HOUR)%60 );
}
else if ((is_abbrev(arg, "qp")) || (is_abbrev(arg, "questpoints")))
{
num = MIN(MAX((atoi(val)), 0), 1000);
HAPPY_QP = num;
send_to_char(ch, "Happy Hour Questpoints rate set to +%d%%\r\n", HAPPY_QP);
}
else if (is_abbrev(arg, "show"))
{
show_happyhour(ch);
}
else if (is_abbrev(arg, "default"))
{
HAPPY_EXP = 100;
HAPPY_GOLD = 50;
HAPPY_QP = 50;
HAPPY_TIME = 48;
game_info("A Happyhour has started!");
}
else
{
send_to_char(ch, "Usage: %shappyhour %s- show usage (this info)\r\n"
" %shappyhour show %s- display current settings (what mortals see)\r\n"
" %shappyhour time <ticks> %s- set happyhour time and start timer\r\n"
" %shappyhour qp <num> %s- set qp percentage gain\r\n"
" %shappyhour exp <num> %s- set exp percentage gain\r\n"
" %shappyhour gold <num> %s- set gold percentage gain\r\n"
" @yhappyhour default @w- sets a default setting for happyhour\r\n\r\n"
"Configure the happyhour settings and start a happyhour.\r\n"
"Currently 1 hour IRL = %d ticks\r\n"
"If no number is specified, 0 (off) is assumed.\r\nThe command @yhappyhour time@n will therefore stop the happyhour timer.\r\n",
CCYEL(ch, C_NRM), CCNRM(ch, C_NRM),
CCYEL(ch, C_NRM), CCNRM(ch, C_NRM),
CCYEL(ch, C_NRM), CCNRM(ch, C_NRM),
CCYEL(ch, C_NRM), CCNRM(ch, C_NRM),
CCYEL(ch, C_NRM), CCNRM(ch, C_NRM),
CCYEL(ch, C_NRM), CCNRM(ch, C_NRM),
(3600 / SECS_PER_MUD_HOUR) );
}
}

View File

@@ -86,7 +86,7 @@
#define INVALID_SOCKET (-1) #define INVALID_SOCKET (-1)
#endif #endif
extern time_t motdmod; extern time_t motdmod;
extern time_t newsmod; extern time_t newsmod;
/* locally defined globals, used externally */ /* locally defined globals, used externally */
@@ -102,6 +102,7 @@ FILE *logfile = NULL; /* Where to send the log messages. */
unsigned long pulse = 0; /* number of pulses since game start */ unsigned long pulse = 0; /* number of pulses since game start */
ush_int port; ush_int port;
socket_t mother_desc; socket_t mother_desc;
int next_tick = SECS_PER_MUD_HOUR; /* Tick countdown */
/* used with do_tell and handle_webster_file utility */ /* used with do_tell and handle_webster_file utility */
long last_webster_teller = -1L; long last_webster_teller = -1L;
@@ -114,7 +115,7 @@ static byte reread_wizlist; /* signal: SIGUSR1 */
/* normally signal SIGUSR2, currently orphaned in favor of Webster dictionary /* normally signal SIGUSR2, currently orphaned in favor of Webster dictionary
* lookup * lookup
static byte emergency_unban; static byte emergency_unban;
*/ */
static int dg_act_check; /* toggle for act_trigger */ static int dg_act_check; /* toggle for act_trigger */
static bool fCopyOver; /* Are we booting in copyover mode? */ static bool fCopyOver; /* Are we booting in copyover mode? */
static char *last_act_message = NULL; static char *last_act_message = NULL;
@@ -178,7 +179,7 @@ static void handle_webster_file();
/* main game loop and related stuff */ /* main game loop and related stuff */
#if defined(CIRCLE_WINDOWS) || defined(CIRCLE_MACINTOSH) #if defined(CIRCLE_WINDOWS) || defined(CIRCLE_MACINTOSH)
/* Windows and Mac do not have gettimeofday, so we'll simulate it. Borland C++ /* Windows and Mac do not have gettimeofday, so we'll simulate it. Borland C++
* warns: "Undefined structure 'timezone'" */ * warns: "Undefined structure 'timezone'" */
void gettimeofday(struct timeval *t, struct timezone *dummy) void gettimeofday(struct timeval *t, struct timezone *dummy)
{ {
@@ -200,8 +201,8 @@ int main(int argc, char **argv)
int pos = 1; int pos = 1;
const char *dir; const char *dir;
#ifdef MEMORY_DEBUG #ifdef MEMORY_DEBUG
zmalloc_init(); zmalloc_init();
#endif #endif
#if CIRCLE_GNU_LIBC_MEMORY_TRACK #if CIRCLE_GNU_LIBC_MEMORY_TRACK
@@ -216,8 +217,8 @@ int main(int argc, char **argv)
GUSIDefaultSetup(); GUSIDefaultSetup();
#endif #endif
/* Load the game configuration. We must load BEFORE we use any of the /* Load the game configuration. We must load BEFORE we use any of the
* constants stored in constants.c. Otherwise, there will be no variables * constants stored in constants.c. Otherwise, there will be no variables
* set to set the rest of the vars to, which will mean trouble --> Mythran */ * set to set the rest of the vars to, which will mean trouble --> Mythran */
CONFIG_CONFFILE = NULL; CONFIG_CONFFILE = NULL;
while ((pos < argc) && (*(argv[pos]) == '-')) { while ((pos < argc) && (*(argv[pos]) == '-')) {
@@ -295,7 +296,7 @@ int main(int argc, char **argv)
puts("Suppressing assignment of special routines."); puts("Suppressing assignment of special routines.");
break; break;
case 'h': case 'h':
/* From: Anil Mahajan. Do NOT use -C, this is the copyover mode and /* From: Anil Mahajan. Do NOT use -C, this is the copyover mode and
* without the proper copyover.dat file, the game will go nuts! */ * without the proper copyover.dat file, the game will go nuts! */
printf("Usage: %s [-c] [-m] [-q] [-r] [-s] [-d pathname] [port #]\n" printf("Usage: %s [-c] [-m] [-q] [-r] [-s] [-d pathname] [port #]\n"
" -c Enable syntax check mode.\n" " -c Enable syntax check mode.\n"
@@ -369,7 +370,7 @@ int main(int argc, char **argv)
free_ibt_lists(); /* ibt.c */ free_ibt_lists(); /* ibt.c */
} }
if (last_act_message) if (last_act_message)
free(last_act_message); free(last_act_message);
/* probably should free the entire config here.. */ /* probably should free the entire config here.. */
@@ -546,8 +547,8 @@ static socket_t init_socket(ush_int local_port)
exit(1); exit(1);
} }
/* 4 = stdin, stdout, stderr, mother_desc. Windows might keep sockets and /* 4 = stdin, stdout, stderr, mother_desc. Windows might keep sockets and
* files separate, in which case this isn't necessary, but we will err on * files separate, in which case this isn't necessary, but we will err on
* the side of caution. */ * the side of caution. */
if ((wsaData.iMaxSockets - 4) < max_players) { if ((wsaData.iMaxSockets - 4) < max_players) {
max_players = wsaData.iMaxSockets - 4; max_players = wsaData.iMaxSockets - 4;
@@ -586,7 +587,7 @@ static socket_t init_socket(ush_int local_port)
set_sendbuf(s); set_sendbuf(s);
/* The GUSI sockets library is derived from BSD, so it defines SO_LINGER, even /* The GUSI sockets library is derived from BSD, so it defines SO_LINGER, even
* though setsockopt() is unimplimented. (from Dean Takemori) */ * though setsockopt() is unimplimented. (from Dean Takemori) */
#if defined(SO_LINGER) && !defined(CIRCLE_MACINTOSH) #if defined(SO_LINGER) && !defined(CIRCLE_MACINTOSH)
{ {
@@ -816,9 +817,9 @@ void game_loop(socket_t local_mother_desc)
for (d = descriptor_list; d; d = next_d) { for (d = descriptor_list; d; d = next_d) {
next_d = d->next; next_d = d->next;
/* Not combined to retain --(d->wait) behavior. -gg 2/20/98 If no wait /* Not combined to retain --(d->wait) behavior. -gg 2/20/98 If no wait
* state, no subtraction. If there is a wait state then 1 is subtracted. * state, no subtraction. If there is a wait state then 1 is subtracted.
* Therefore we don't go less than 0 ever and don't require an 'if' * Therefore we don't go less than 0 ever and don't require an 'if'
* bracket. -gg 2/27/99 */ * bracket. -gg 2/27/99 */
if (d->character) { if (d->character) {
GET_WAIT_STATE(d->character) -= (GET_WAIT_STATE(d->character) > 0); GET_WAIT_STATE(d->character) -= (GET_WAIT_STATE(d->character) > 0);
@@ -942,6 +943,10 @@ void heartbeat(int heart_pulse)
if (!(heart_pulse % PULSE_DG_SCRIPT)) if (!(heart_pulse % PULSE_DG_SCRIPT))
script_trigger_check(); script_trigger_check();
if (!(heart_pulse % PASSES_PER_SEC)) { /* EVERY second */
next_tick--;
}
if (!(heart_pulse % PULSE_ZONE)) if (!(heart_pulse % PULSE_ZONE))
zone_update(); zone_update();
@@ -955,6 +960,7 @@ void heartbeat(int heart_pulse)
perform_violence(); perform_violence();
if (!(heart_pulse % (SECS_PER_MUD_HOUR * PASSES_PER_SEC))) { /* Tick ! */ if (!(heart_pulse % (SECS_PER_MUD_HOUR * PASSES_PER_SEC))) { /* Tick ! */
next_tick = SECS_PER_MUD_HOUR; /* Reset tick coundown */
weather_and_time(1); weather_and_time(1);
check_time_triggers(); check_time_triggers();
affect_update(); affect_update();
@@ -980,10 +986,10 @@ void heartbeat(int heart_pulse)
extract_pending_chars(); extract_pending_chars();
} }
/* new code to calculate time differences, which works on systems for which /* new code to calculate time differences, which works on systems for which
* tv_usec is unsigned (and thus comparisons for something being < 0 fail). * tv_usec is unsigned (and thus comparisons for something being < 0 fail).
* Based on code submitted by ss@sirocco.cup.hp.com. Code to return the time * Based on code submitted by ss@sirocco.cup.hp.com. Code to return the time
* difference between a and b (a-b). Always returns a nonnegative value * difference between a and b (a-b). Always returns a nonnegative value
* (floors at 0). */ * (floors at 0). */
static void timediff(struct timeval *rslt, struct timeval *a, struct timeval *b) static void timediff(struct timeval *rslt, struct timeval *a, struct timeval *b)
{ {
@@ -1217,18 +1223,18 @@ static char *make_prompt(struct descriptor_data *d)
len += count; len += count;
} }
if (GET_LAST_NEWS(d->character) < newsmod) if (GET_LAST_NEWS(d->character) < newsmod)
{ {
count = snprintf(prompt + len, sizeof(prompt) - len, "(news) "); count = snprintf(prompt + len, sizeof(prompt) - len, "(news) ");
if (count >= 0) if (count >= 0)
len += count; len += count;
} }
if (GET_LAST_MOTD(d->character) < motdmod) if (GET_LAST_MOTD(d->character) < motdmod)
{ {
count = snprintf(prompt + len, sizeof(prompt) - len, "(motd) "); count = snprintf(prompt + len, sizeof(prompt) - len, "(motd) ");
if (count >= 0) if (count >= 0)
len += count; len += count;
} }
if (len < sizeof(prompt)) if (len < sizeof(prompt))
@@ -1557,17 +1563,17 @@ static int new_descriptor(socket_t s)
newd->next = descriptor_list; newd->next = descriptor_list;
descriptor_list = newd; descriptor_list = newd;
/* This is where the greetings are actually sent to the new player */ /* This is where the greetings are actually sent to the new player */
/* Adjusted by Jamdog to show color codes on the greetings page */ /* Adjusted by Jamdog to show color codes on the greetings page */
*greet_copy = '\0'; *greet_copy = '\0';
sprintf(greet_copy, "%s", GREETINGS); sprintf(greet_copy, "%s", GREETINGS);
proc_colors(greet_copy, MAX_STRING_LENGTH, TRUE); proc_colors(greet_copy, MAX_STRING_LENGTH, TRUE);
write_to_output(newd, "%s", greet_copy); write_to_output(newd, "%s", greet_copy);
return (0); return (0);
} }
/* Send all of the output that we've accumulated for a player out to the /* Send all of the output that we've accumulated for a player out to the
* player's descriptor. 32 byte GARBAGE_SPACE in MAX_SOCK_BUF used for: * player's descriptor. 32 byte GARBAGE_SPACE in MAX_SOCK_BUF used for:
* 2 bytes: prepended \r\n * 2 bytes: prepended \r\n
* 14 bytes: overflow message * 14 bytes: overflow message
@@ -1714,7 +1720,7 @@ static ssize_t perform_socket_write(socket_t desc, const char *txt, size_t lengt
return (-1); return (-1);
} }
/* result < 0, so an error was encountered - is it transient? Unfortunately, /* result < 0, so an error was encountered - is it transient? Unfortunately,
* different systems use different constants to indicate this. */ * different systems use different constants to indicate this. */
#ifdef EAGAIN /* POSIX */ #ifdef EAGAIN /* POSIX */
@@ -1738,7 +1744,7 @@ static ssize_t perform_socket_write(socket_t desc, const char *txt, size_t lengt
#endif /* CIRCLE_WINDOWS */ #endif /* CIRCLE_WINDOWS */
/* write_to_descriptor takes a descriptor, and text to write to the descriptor. /* write_to_descriptor takes a descriptor, and text to write to the descriptor.
* It keeps calling the system-level write() until all the text has been * It keeps calling the system-level write() until all the text has been
* delivered to the OS, or until an error is encountered. Returns: * delivered to the OS, or until an error is encountered. Returns:
* >=0 If all is well and good. * >=0 If all is well and good.
* -1 If an error was encountered, so that the player should be cut off. */ * -1 If an error was encountered, so that the player should be cut off. */
@@ -1834,11 +1840,11 @@ static ssize_t perform_socket_read(socket_t desc, char *read_point, size_t space
* function is called. We must maintain that before returning. * function is called. We must maintain that before returning.
* *
* Ever wonder why 'tmp' had '+8' on it? The crusty old code could write * Ever wonder why 'tmp' had '+8' on it? The crusty old code could write
* MAX_INPUT_LENGTH+1 bytes to 'tmp' if there was a '$' as the final character * MAX_INPUT_LENGTH+1 bytes to 'tmp' if there was a '$' as the final character
* in the input buffer. This would also cause 'space_left' to drop to -1, * in the input buffer. This would also cause 'space_left' to drop to -1,
* which wasn't very happy in an unsigned variable. Argh. So to fix the * which wasn't very happy in an unsigned variable. Argh. So to fix the
* above, 'tmp' lost the '+8' since it doesn't need it and the code has been * above, 'tmp' lost the '+8' since it doesn't need it and the code has been
* changed to reserve space by accepting one less character. (Do you really * changed to reserve space by accepting one less character. (Do you really
* need 256 characters on a line?) -gg 1/21/2000 */ * need 256 characters on a line?) -gg 1/21/2000 */
static int process_input(struct descriptor_data *t) static int process_input(struct descriptor_data *t)
{ {
@@ -1868,7 +1874,7 @@ static int process_input(struct descriptor_data *t)
/* at this point, we know we got some data from the read */ /* at this point, we know we got some data from the read */
*(read_point + bytes_read) = '\0'; /* terminate the string */ *(read_point + bytes_read) = '\0'; /* terminate the string */
/* search for a newline in the data we just read */ /* search for a newline in the data we just read */
for (ptr = read_point; *ptr && !nl_pos; ptr++) for (ptr = read_point; *ptr && !nl_pos; ptr++)
if (ISNEWL(*ptr)) if (ISNEWL(*ptr))
@@ -1965,12 +1971,12 @@ static int process_input(struct descriptor_data *t)
t->history_pos = 0; t->history_pos = 0;
} }
/* The '--' command flushes the queue. */ /* The '--' command flushes the queue. */
if ( (*tmp == '-') && (*(tmp+1) == '-') && !(*(tmp+2)) ) if ( (*tmp == '-') && (*(tmp+1) == '-') && !(*(tmp+2)) )
{ {
write_to_output(t, "All queued commands cancelled.\r\n"); write_to_output(t, "All queued commands cancelled.\r\n");
flush_queues(t); /* Flush the command queue */ flush_queues(t); /* Flush the command queue */
failed_subst = 1; /* Allow the read point to be moved, but don't add to queue */ failed_subst = 1; /* Allow the read point to be moved, but don't add to queue */
} }
if (!failed_subst) if (!failed_subst)
@@ -1996,8 +2002,8 @@ static int process_input(struct descriptor_data *t)
return (1); return (1);
} }
/* Perform substitution for the '^..^' csh-esque syntax orig is the orig string, /* Perform substitution for the '^..^' csh-esque syntax orig is the orig string,
* i.e. the one being modified. subst contains the substition string, i.e. * i.e. the one being modified. subst contains the substition string, i.e.
* "^telm^tell" */ * "^telm^tell" */
static int perform_subst(struct descriptor_data *t, char *orig, char *subst) static int perform_subst(struct descriptor_data *t, char *orig, char *subst)
{ {
@@ -2005,7 +2011,7 @@ static int perform_subst(struct descriptor_data *t, char *orig, char *subst)
char *first, *second, *strpos; char *first, *second, *strpos;
/* First is the position of the beginning of the first string (the one to be /* First is the position of the beginning of the first string (the one to be
* replaced. */ * replaced. */
first = subst + 1; first = subst + 1;
@@ -2328,6 +2334,28 @@ static void signal_setup(void)
#endif /* CIRCLE_UNIX || CIRCLE_MACINTOSH */ #endif /* CIRCLE_UNIX || CIRCLE_MACINTOSH */
/* Public routines for system-to-player-communication. */ /* Public routines for system-to-player-communication. */
void game_info(const char *format, ...)
{
struct descriptor_data *i;
va_list args;
char messg[MAX_STRING_LENGTH];
if (format == NULL)
return;
sprintf(messg, "@cInfo: @y");
for (i = descriptor_list; i; i = i->next) {
if (STATE(i) != CON_PLAYING)
continue;
if (!(i->character))
continue;
write_to_output(i, "%s", messg);
va_start(args, format);
vwrite_to_output(i, format, args);
va_end(args);
write_to_output(i, "@n\r\n");
}
}
size_t send_to_char(struct char_data *ch, const char *messg, ...) size_t send_to_char(struct char_data *ch, const char *messg, ...)
{ {
if (ch->desc && messg && *messg) { if (ch->desc && messg && *messg) {
@@ -2554,9 +2582,9 @@ void perform_act(const char *orig, struct char_data *ch, struct obj_data *obj,
if ((IS_NPC(to) && dg_act_check) && (to != ch)) if ((IS_NPC(to) && dg_act_check) && (to != ch))
act_mtrigger(to, lbuf, ch, dg_victim, obj, dg_target, dg_arg); act_mtrigger(to, lbuf, ch, dg_victim, obj, dg_target, dg_arg);
if (last_act_message) if (last_act_message)
free(last_act_message); free(last_act_message);
last_act_message = strdup(lbuf); last_act_message = strdup(lbuf);
} }
char *act(const char *str, int hide_invisible, struct char_data *ch, char *act(const char *str, int hide_invisible, struct char_data *ch,
@@ -2569,11 +2597,11 @@ char *act(const char *str, int hide_invisible, struct char_data *ch,
return NULL; return NULL;
/* Warning: the following TO_SLEEP code is a hack. I wanted to be able to tell /* Warning: the following TO_SLEEP code is a hack. I wanted to be able to tell
* act to deliver a message regardless of sleep without adding an additional * act to deliver a message regardless of sleep without adding an additional
* argument. TO_SLEEP is 128 (a single bit high up). It's ONLY legal to * argument. TO_SLEEP is 128 (a single bit high up). It's ONLY legal to
* combine TO_SLEEP with one other TO_x command. It's not legal to combine * combine TO_SLEEP with one other TO_x command. It's not legal to combine
* TO_x's with each other otherwise. TO_SLEEP only works because its value * TO_x's with each other otherwise. TO_SLEEP only works because its value
* "happens to be" a single bit; do not change it to something else. In * "happens to be" a single bit; do not change it to something else. In
* short, it is a hack. */ * short, it is a hack. */
/* check if TO_SLEEP is there, and remove it if it is. */ /* check if TO_SLEEP is there, and remove it if it is. */
@@ -2582,21 +2610,21 @@ char *act(const char *str, int hide_invisible, struct char_data *ch,
/* this is a hack as well - DG_NO_TRIG is 256 -- Welcor */ /* this is a hack as well - DG_NO_TRIG is 256 -- Welcor */
/* If the bit is set, unset dg_act_check, thus the ! below */ /* If the bit is set, unset dg_act_check, thus the ! below */
if (!(dg_act_check = !IS_SET(type, DG_NO_TRIG))) if (!(dg_act_check = !IS_SET(type, DG_NO_TRIG)))
REMOVE_BIT(type, DG_NO_TRIG); REMOVE_BIT(type, DG_NO_TRIG);
if (type == TO_CHAR) { if (type == TO_CHAR) {
if (ch && SENDOK(ch)) { if (ch && SENDOK(ch)) {
perform_act(str, ch, obj, vict_obj, ch); perform_act(str, ch, obj, vict_obj, ch);
return last_act_message; return last_act_message;
} }
return NULL; return NULL;
} }
if (type == TO_VICT) { if (type == TO_VICT) {
if ((to = vict_obj) != NULL && SENDOK(to)) { if ((to = vict_obj) != NULL && SENDOK(to)) {
perform_act(str, ch, obj, vict_obj, to); perform_act(str, ch, obj, vict_obj, to);
return last_act_message; return last_act_message;
} }
return NULL; return NULL;
} }
@@ -2604,7 +2632,7 @@ char *act(const char *str, int hide_invisible, struct char_data *ch,
if (type == TO_GMOTE && !IS_NPC(ch)) { if (type == TO_GMOTE && !IS_NPC(ch)) {
struct descriptor_data *i; struct descriptor_data *i;
char buf[MAX_STRING_LENGTH]; char buf[MAX_STRING_LENGTH];
for (i = descriptor_list; i; i = i->next) { for (i = descriptor_list; i; i = i->next) {
if (!i->connected && i->character && if (!i->connected && i->character &&
!PRF_FLAGGED(i->character, PRF_NOGOSS) && !PRF_FLAGGED(i->character, PRF_NOGOSS) &&
@@ -2612,7 +2640,7 @@ char *act(const char *str, int hide_invisible, struct char_data *ch,
!ROOM_FLAGGED(IN_ROOM(i->character), ROOM_SOUNDPROOF)) { !ROOM_FLAGGED(IN_ROOM(i->character), ROOM_SOUNDPROOF)) {
sprintf(buf, "%s%s%s", CCYEL(i->character, C_NRM), str, CCNRM(i->character, C_NRM)); sprintf(buf, "%s%s%s", CCYEL(i->character, C_NRM), str, CCNRM(i->character, C_NRM));
perform_act(buf, ch, obj, vict_obj, i->character); perform_act(buf, ch, obj, vict_obj, i->character);
} }
} }
return last_act_message; return last_act_message;
@@ -2635,7 +2663,7 @@ char *act(const char *str, int hide_invisible, struct char_data *ch,
continue; continue;
if (type != TO_ROOM && to == vict_obj) if (type != TO_ROOM && to == vict_obj)
continue; continue;
perform_act(str, ch, obj, vict_obj, to); perform_act(str, ch, obj, vict_obj, to);
} }
return last_act_message; return last_act_message;
} }

View File

@@ -1,13 +1,13 @@
/** /**
* @file comm.h * @file comm.h
* Header file, prototypes of public communication functions. * Header file, prototypes of public communication functions.
* *
* Part of the core tbaMUD source code distribution, which is a derivative * Part of the core tbaMUD source code distribution, which is a derivative
* of, and continuation of, CircleMUD. * of, and continuation of, CircleMUD.
* *
* All rights reserved. See license for complete information. * All rights reserved. See license for complete information.
* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University * Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. * CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.
* *
*/ */
#ifndef _COMM_H_ #ifndef _COMM_H_
@@ -18,9 +18,10 @@
/* comm.c */ /* comm.c */
void close_socket(struct descriptor_data *d); void close_socket(struct descriptor_data *d);
size_t send_to_char(struct char_data *ch, const char *messg, ...) __attribute__ void game_info(const char *messg, ...) __attribute__ ((format (printf, 1, 2)));
size_t send_to_char(struct char_data *ch, const char *messg, ...) __attribute__
((format (printf, 2, 3))); ((format (printf, 2, 3)));
void send_to_all(const char *messg, ...) __attribute__ ((format (printf, 1, void send_to_all(const char *messg, ...) __attribute__ ((format (printf, 1,
2))); 2)));
void send_to_room(room_rnum room, const char *messg, ...) __attribute__ ((format void send_to_room(room_rnum room, const char *messg, ...) __attribute__ ((format
(printf, 2, 3))); (printf, 2, 3)));
@@ -29,8 +30,8 @@ void send_to_outdoor(const char *messg, ...) __attribute__ ((format (printf, 1,
void send_to_range(room_vnum start, room_vnum finish, const char *messg, ...) void send_to_range(room_vnum start, room_vnum finish, const char *messg, ...)
__attribute__ ((format (printf, 3, 4))); __attribute__ ((format (printf, 3, 4)));
/* Act type settings and flags */ /* Act type settings and flags */
#define TO_ROOM 1 /**< act() type: to everyone in room, except ch. */ #define TO_ROOM 1 /**< act() type: to everyone in room, except ch. */
#define TO_VICT 2 /**< act() type: to vict_obj. */ #define TO_VICT 2 /**< act() type: to vict_obj. */
#define TO_NOTVICT 3 /**< act() type: to everyone in room, not ch or vict_obj. */ #define TO_NOTVICT 3 /**< act() type: to everyone in room, not ch or vict_obj. */
#define TO_CHAR 4 /**< act() type: to ch. */ #define TO_CHAR 4 /**< act() type: to ch. */
@@ -40,7 +41,7 @@ void send_to_range(room_vnum start, room_vnum finish, const char *messg, ...)
/* act functions */ /* act functions */
void perform_act(const char *orig, struct char_data *ch, struct obj_data *obj, void *vict_obj, struct char_data *to); void perform_act(const char *orig, struct char_data *ch, struct obj_data *obj, void *vict_obj, struct char_data *to);
char * act(const char *str, int hide_invisible, struct char_data *ch, struct obj_data *obj, void *vict_obj, int type); char * act(const char *str, int hide_invisible, struct char_data *ch, struct obj_data *obj, void *vict_obj, int type);
/* I/O functions */ /* I/O functions */
@@ -75,6 +76,7 @@ extern FILE *logfile;
extern unsigned long pulse; extern unsigned long pulse;
extern ush_int port; extern ush_int port;
extern socket_t mother_desc; extern socket_t mother_desc;
extern int next_tick;
#endif /* __COMM_C__ */ #endif /* __COMM_C__ */

View File

@@ -120,6 +120,7 @@ struct weather_data weather_info; /* the infomation about the weather */
struct player_special_data dummy_mob; /* dummy spec area for mobs */ struct player_special_data dummy_mob; /* dummy spec area for mobs */
struct reset_q_type reset_q; /* queue of zones to be reset */ struct reset_q_type reset_q; /* queue of zones to be reset */
struct happyhour happy_data = {0,0,0,0};
/* declaration of local (file scope) variables */ /* declaration of local (file scope) variables */
static int converting = FALSE; static int converting = FALSE;

View File

@@ -401,6 +401,9 @@ extern struct message_list fight_messages[MAX_MESSAGES];
extern struct aq_data *aquest_table; extern struct aq_data *aquest_table;
extern qst_rnum total_quests; extern qst_rnum total_quests;
/* Happyhour global */
extern struct happyhour happy_data;
/* begin previously located in players.c, returned to db.c */ /* begin previously located in players.c, returned to db.c */
extern struct player_index_element *player_table; extern struct player_index_element *player_table;
extern int top_of_p_table; extern int top_of_p_table;

View File

@@ -379,10 +379,16 @@ void die(struct char_data * ch, struct char_data * killer)
static void perform_group_gain(struct char_data *ch, int base, static void perform_group_gain(struct char_data *ch, int base,
struct char_data *victim) struct char_data *victim)
{ {
int share; int share, hap_share;
share = MIN(CONFIG_MAX_EXP_GAIN, MAX(1, base)); share = MIN(CONFIG_MAX_EXP_GAIN, MAX(1, base));
if ((IS_HAPPYHOUR) && (IS_HAPPYEXP))
{
/* This only reports the correct amount - the calc is done in gain_exp */
hap_share = share + (int)((float)share * ((float)HAPPY_EXP / (float)(100)));
share = MIN(CONFIG_MAX_EXP_GAIN, MAX(1, hap_share));
}
if (share > 1) if (share > 1)
send_to_char(ch, "You receive your share of experience -- %d points.\r\n", share); send_to_char(ch, "You receive your share of experience -- %d points.\r\n", share);
else else
@@ -432,7 +438,7 @@ static void group_gain(struct char_data *ch, struct char_data *victim)
static void solo_gain(struct char_data *ch, struct char_data *victim) static void solo_gain(struct char_data *ch, struct char_data *victim)
{ {
int exp; int exp, happy_exp;
exp = MIN(CONFIG_MAX_EXP_GAIN, GET_EXP(victim) / 3); exp = MIN(CONFIG_MAX_EXP_GAIN, GET_EXP(victim) / 3);
@@ -444,6 +450,11 @@ static void solo_gain(struct char_data *ch, struct char_data *victim)
exp = MAX(exp, 1); exp = MAX(exp, 1);
if (IS_HAPPYHOUR && IS_HAPPYEXP) {
happy_exp = exp + (int)((float)exp * ((float)HAPPY_EXP / (float)(100)));
exp = MAX(happy_exp, 1);
}
if (exp > 1) if (exp > 1)
send_to_char(ch, "You receive %d experience points.\r\n", exp); send_to_char(ch, "You receive %d experience points.\r\n", exp);
else else
@@ -659,7 +670,7 @@ int skill_message(int dam, struct char_data *ch, struct char_data *vict,
* > 0 How much damage done. */ * > 0 How much damage done. */
int damage(struct char_data *ch, struct char_data *victim, int dam, int attacktype) int damage(struct char_data *ch, struct char_data *victim, int dam, int attacktype)
{ {
long local_gold = 0; long local_gold = 0, happy_gold = 0;
char local_buf[256]; char local_buf[256];
struct char_data *tmp_char; struct char_data *tmp_char;
struct obj_data *corpse_obj; struct obj_data *corpse_obj;
@@ -822,6 +833,12 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, int attackty
} }
/* Cant determine GET_GOLD on corpse, so do now and store */ /* Cant determine GET_GOLD on corpse, so do now and store */
if (IS_NPC(victim)) { if (IS_NPC(victim)) {
if ((IS_HAPPYHOUR) && (IS_HAPPYGOLD))
{
happy_gold = (long)(GET_GOLD(victim) * (((float)(HAPPY_GOLD))/(float)100));
happy_gold = MAX(0, happy_gold);
GET_GOLD(victim) += happy_gold;
}
local_gold = GET_GOLD(victim); local_gold = GET_GOLD(victim);
sprintf(local_buf,"%ld", (long)local_gold); sprintf(local_buf,"%ld", (long)local_gold);
} }

View File

@@ -158,10 +158,11 @@ cpp_extern const struct command_info cmd_info[] = {
{ "gtell" , "gt" , POS_SLEEPING, do_gsay , 0, 0 }, { "gtell" , "gt" , POS_SLEEPING, do_gsay , 0, 0 },
{ "help" , "h" , POS_DEAD , do_help , 0, 0 }, { "help" , "h" , POS_DEAD , do_help , 0, 0 },
{ "happyhour", "ha" , POS_DEAD , do_happyhour, 0, 0 },
{ "hedit" , "hedit" , POS_DEAD , do_oasis_hedit, LVL_GOD , 0 }, { "hedit" , "hedit" , POS_DEAD , do_oasis_hedit, LVL_GOD , 0 },
{ "hindex" , "hind" , POS_DEAD , do_hindex , 0, 0 },
{ "helpcheck", "helpch" , POS_DEAD , do_helpcheck, LVL_GOD, 0 }, { "helpcheck", "helpch" , POS_DEAD , do_helpcheck, LVL_GOD, 0 },
{ "hide" , "hi" , POS_RESTING , do_hide , 1, 0 }, { "hide" , "hi" , POS_RESTING , do_hide , 1, 0 },
{ "hindex" , "hind" , POS_DEAD , do_hindex , 0, 0 },
{ "handbook" , "handb" , POS_DEAD , do_gen_ps , LVL_IMMORT, SCMD_HANDBOOK }, { "handbook" , "handb" , POS_DEAD , do_gen_ps , LVL_IMMORT, SCMD_HANDBOOK },
{ "hcontrol" , "hcontrol", POS_DEAD , do_hcontrol , LVL_GRGOD, 0 }, { "hcontrol" , "hcontrol", POS_DEAD , do_hcontrol , LVL_GRGOD, 0 },
{ "history" , "history" , POS_DEAD , do_history, 0, 0}, { "history" , "history" , POS_DEAD , do_history, 0, 0},
@@ -1509,6 +1510,11 @@ void nanny(struct descriptor_data *d, char *arg)
case CON_RMOTD: /* read CR after printing motd */ case CON_RMOTD: /* read CR after printing motd */
write_to_output(d, "%s", CONFIG_MENU); write_to_output(d, "%s", CONFIG_MENU);
if (IS_HAPPYHOUR > 0){
write_to_output(d, "\r\n");
write_to_output(d, "@yThere is currently a Happyhour!@n\r\n");
write_to_output(d, "\r\n");
}
add_llog_entry(d->character, LAST_CONNECT); add_llog_entry(d->character, LAST_CONNECT);
STATE(d) = CON_MENU; STATE(d) = CON_MENU;
break; break;

View File

@@ -50,9 +50,9 @@ static int graf(int grafage, int p0, int p1, int p2, int p3, int p4, int p5, int
} }
/* The hit_limit, mana_limit, and move_limit functions are gone. They added an /* The hit_limit, mana_limit, and move_limit functions are gone. They added an
* unnecessary level of complexity to the internal structure, weren't * unnecessary level of complexity to the internal structure, weren't
* particularly useful, and led to some annoying bugs. From the players' point * particularly useful, and led to some annoying bugs. From the players' point
* of view, the only difference the removal of these functions will make is * of view, the only difference the removal of these functions will make is
* that a character's age will now only affect the HMV gain per tick, and _not_ * that a character's age will now only affect the HMV gain per tick, and _not_
* the HMV maximums. */ * the HMV maximums. */
/* manapoint gain pr. game hour */ /* manapoint gain pr. game hour */
@@ -180,7 +180,7 @@ void set_title(struct char_data *ch, char *title)
if (title == NULL) { if (title == NULL) {
GET_TITLE(ch) = strdup(GET_SEX(ch) == SEX_FEMALE ? GET_TITLE(ch) = strdup(GET_SEX(ch) == SEX_FEMALE ?
title_female(GET_CLASS(ch), GET_LEVEL(ch)) : title_female(GET_CLASS(ch), GET_LEVEL(ch)) :
title_male(GET_CLASS(ch), GET_LEVEL(ch))); title_male(GET_CLASS(ch), GET_LEVEL(ch)));
} else { } else {
if (strlen(title) > MAX_TITLE_LENGTH) if (strlen(title) > MAX_TITLE_LENGTH)
@@ -230,6 +230,9 @@ void gain_exp(struct char_data *ch, int gain)
return; return;
} }
if (gain > 0) { if (gain > 0) {
if ((IS_HAPPYHOUR) && (IS_HAPPYEXP))
gain += (int)((float)gain * ((float)HAPPY_EXP / (float)(100)));
gain = MIN(CONFIG_MAX_EXP_GAIN, gain); /* put a cap on the max gain per kill */ gain = MIN(CONFIG_MAX_EXP_GAIN, gain); /* put a cap on the max gain per kill */
GET_EXP(ch) += gain; GET_EXP(ch) += gain;
while (GET_LEVEL(ch) < LVL_IMMORT - CONFIG_NO_MORT_TO_IMMORT && while (GET_LEVEL(ch) < LVL_IMMORT - CONFIG_NO_MORT_TO_IMMORT &&
@@ -266,6 +269,9 @@ void gain_exp_regardless(struct char_data *ch, int gain)
int is_altered = FALSE; int is_altered = FALSE;
int num_levels = 0; int num_levels = 0;
if ((IS_HAPPYHOUR) && (IS_HAPPYEXP))
gain += (int)((float)gain * ((float)HAPPY_EXP / (float)(100)));
GET_EXP(ch) += gain; GET_EXP(ch) += gain;
if (GET_EXP(ch) < 0) if (GET_EXP(ch) < 0)
GET_EXP(ch) = 0; GET_EXP(ch) = 0;
@@ -448,4 +454,15 @@ void point_update(void)
timer_otrigger(j); timer_otrigger(j);
} }
} }
/* Take 1 from the happy-hour tick counter, and end happy-hour if zero */
if (HAPPY_TIME > 1) HAPPY_TIME--;
else if (HAPPY_TIME == 1) /* Last tick - set everything back to zero */
{
HAPPY_QP = 0;
HAPPY_EXP = 0;
HAPPY_GOLD = 0;
HAPPY_TIME = 0;
game_info("Happy hour has ended!");
}
} }

View File

@@ -294,24 +294,51 @@ void generic_complete_quest(struct char_data *ch)
qst_rnum rnum; qst_rnum rnum;
qst_vnum vnum = GET_QUEST(ch); qst_vnum vnum = GET_QUEST(ch);
struct obj_data *new_obj; struct obj_data *new_obj;
int happy_qp, happy_gold, happy_exp;
if (--GET_QUEST_COUNTER(ch) <= 0) { if (--GET_QUEST_COUNTER(ch) <= 0) {
rnum = real_quest(vnum); rnum = real_quest(vnum);
GET_QUESTPOINTS(ch) += QST_POINTS(rnum); if (IS_HAPPYHOUR && IS_HAPPYQP) {
send_to_char(ch, happy_qp = (int)(QST_POINTS(rnum) * (((float)(100+HAPPY_QP))/(float)100));
happy_qp = MAX(happy_qp, 0);
GET_QUESTPOINTS(ch) += happy_qp;
send_to_char(ch,
"%s\r\nYou have been awarded %d quest points for your service.\r\n",
QST_DONE(rnum), happy_qp);
} else {
GET_QUESTPOINTS(ch) += QST_POINTS(rnum);
send_to_char(ch,
"%s\r\nYou have been awarded %d quest points for your service.\r\n", "%s\r\nYou have been awarded %d quest points for your service.\r\n",
QST_DONE(rnum), QST_POINTS(rnum)); QST_DONE(rnum), QST_POINTS(rnum));
}
if (QST_GOLD(rnum)) { if (QST_GOLD(rnum)) {
GET_GOLD(ch) += QST_GOLD(rnum); if ((IS_HAPPYHOUR) && (IS_HAPPYGOLD)) {
send_to_char(ch, happy_gold = (int)(QST_GOLD(rnum) * (((float)(100+HAPPY_GOLD))/(float)100));
"You have been awarded %d gold coins for your service.\r\n", happy_gold = MAX(happy_gold, 0);
QST_GOLD(rnum)); GET_GOLD(ch) += happy_gold;
send_to_char(ch,
"You have been awarded %d gold coins for your service.\r\n",
happy_gold);
} else {
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)) { if (QST_EXP(rnum)) {
gain_exp(ch, QST_EXP(rnum)); gain_exp(ch, QST_EXP(rnum));
send_to_char(ch, if ((IS_HAPPYHOUR) && (IS_HAPPYEXP)) {
"You have been awarded %d experience points for your service.\r\n", happy_exp = (int)(QST_EXP(rnum) * (((float)(100+HAPPY_EXP))/(float)100));
QST_EXP(rnum)); happy_exp = MAX(happy_exp, 0);
send_to_char(ch,
"You have been awarded %d experience for your service.\r\n",
happy_exp);
} else {
send_to_char(ch,
"You have been awarded %d experience points for your service.\r\n",
QST_EXP(rnum));
}
} }
if (QST_OBJ(rnum) && QST_OBJ(rnum) != NOTHING) { if (QST_OBJ(rnum) && QST_OBJ(rnum) != NOTHING) {
if (real_object(QST_OBJ(rnum)) != NOTHING) { if (real_object(QST_OBJ(rnum)) != NOTHING) {

View File

@@ -1232,6 +1232,14 @@ struct guild_info_type
int direction; int direction;
}; };
/** Happy Hour Data */
struct happyhour {
int qp_rate;
int exp_rate;
int gold_rate;
int ticks_left;
};
/* Config structs */ /* Config structs */
/** The game configuration structure used for configurating the game play /** The game configuration structure used for configurating the game play

View File

@@ -851,6 +851,19 @@ do \
/** Defines if ch is outdoors or not. */ /** Defines if ch is outdoors or not. */
#define OUTSIDE(ch) (!ROOM_FLAGGED(IN_ROOM(ch), ROOM_INDOORS)) #define OUTSIDE(ch) (!ROOM_FLAGGED(IN_ROOM(ch), ROOM_INDOORS))
/* Happy-hour defines */
#define IS_HAPPYQP (happy_data.qp_rate > 0)
#define IS_HAPPYEXP (happy_data.exp_rate > 0)
#define IS_HAPPYGOLD (happy_data.gold_rate > 0)
#define HAPPY_EXP happy_data.exp_rate
#define HAPPY_GOLD happy_data.gold_rate
#define HAPPY_QP happy_data.qp_rate
#define HAPPY_TIME happy_data.ticks_left
#define IS_HAPPYHOUR ((IS_HAPPYEXP || IS_HAPPYGOLD || IS_HAPPYQP) && (HAPPY_TIME > 0))
/* OS compatibility */ /* OS compatibility */
#ifndef NULL #ifndef NULL
/** Just in case NULL is not defined. */ /** Just in case NULL is not defined. */