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

@ -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;
@ -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();
@ -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) {

View file

@ -18,6 +18,7 @@
/* comm.c */ /* comm.c */
void close_socket(struct descriptor_data *d); void close_socket(struct descriptor_data *d);
void game_info(const char *messg, ...) __attribute__ ((format (printf, 1, 2)));
size_t send_to_char(struct char_data *ch, const char *messg, ...) __attribute__ 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,
@ -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

@ -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. */