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)
@
[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
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)

View File

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

View File

@@ -1331,6 +1331,10 @@ ACMD(do_who)
send_to_char(ch, "One lonely character displayed.\r\n");
else
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 \

View File

@@ -859,3 +859,116 @@ ACMD(do_gen_tog)
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 */
ush_int port;
socket_t mother_desc;
int next_tick = SECS_PER_MUD_HOUR; /* Tick countdown */
/* used with do_tell and handle_webster_file utility */
long last_webster_teller = -1L;
@@ -942,6 +943,10 @@ void heartbeat(int heart_pulse)
if (!(heart_pulse % PULSE_DG_SCRIPT))
script_trigger_check();
if (!(heart_pulse % PASSES_PER_SEC)) { /* EVERY second */
next_tick--;
}
if (!(heart_pulse % PULSE_ZONE))
zone_update();
@@ -955,6 +960,7 @@ void heartbeat(int heart_pulse)
perform_violence();
if (!(heart_pulse % (SECS_PER_MUD_HOUR * PASSES_PER_SEC))) { /* Tick ! */
next_tick = SECS_PER_MUD_HOUR; /* Reset tick coundown */
weather_and_time(1);
check_time_triggers();
affect_update();
@@ -2328,6 +2334,28 @@ static void signal_setup(void)
#endif /* CIRCLE_UNIX || CIRCLE_MACINTOSH */
/* 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, ...)
{
if (ch->desc && messg && *messg) {

View File

@@ -18,6 +18,7 @@
/* comm.c */
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__
((format (printf, 2, 3)));
void send_to_all(const char *messg, ...) __attribute__ ((format (printf, 1,
@@ -75,6 +76,7 @@ extern FILE *logfile;
extern unsigned long pulse;
extern ush_int port;
extern socket_t mother_desc;
extern int next_tick;
#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 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 */
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 qst_rnum total_quests;
/* Happyhour global */
extern struct happyhour happy_data;
/* begin previously located in players.c, returned to db.c */
extern struct player_index_element *player_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,
struct char_data *victim)
{
int share;
int share, hap_share;
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)
send_to_char(ch, "You receive your share of experience -- %d points.\r\n", share);
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)
{
int exp;
int exp, happy_exp;
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);
if (IS_HAPPYHOUR && IS_HAPPYEXP) {
happy_exp = exp + (int)((float)exp * ((float)HAPPY_EXP / (float)(100)));
exp = MAX(happy_exp, 1);
}
if (exp > 1)
send_to_char(ch, "You receive %d experience points.\r\n", exp);
else
@@ -659,7 +670,7 @@ int skill_message(int dam, struct char_data *ch, struct char_data *vict,
* > 0 How much damage done. */
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];
struct char_data *tmp_char;
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 */
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);
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 },
{ "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 },
{ "hindex" , "hind" , POS_DEAD , do_hindex , 0, 0 },
{ "helpcheck", "helpch" , POS_DEAD , do_helpcheck, LVL_GOD, 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 },
{ "hcontrol" , "hcontrol", POS_DEAD , do_hcontrol , LVL_GRGOD, 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 */
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);
STATE(d) = CON_MENU;
break;

View File

@@ -230,6 +230,9 @@ void gain_exp(struct char_data *ch, int gain)
return;
}
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 */
GET_EXP(ch) += gain;
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 num_levels = 0;
if ((IS_HAPPYHOUR) && (IS_HAPPYEXP))
gain += (int)((float)gain * ((float)HAPPY_EXP / (float)(100)));
GET_EXP(ch) += gain;
if (GET_EXP(ch) < 0)
GET_EXP(ch) = 0;
@@ -448,4 +454,15 @@ void point_update(void)
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_vnum vnum = GET_QUEST(ch);
struct obj_data *new_obj;
int happy_qp, happy_gold, happy_exp;
if (--GET_QUEST_COUNTER(ch) <= 0) {
rnum = real_quest(vnum);
GET_QUESTPOINTS(ch) += QST_POINTS(rnum);
send_to_char(ch,
if (IS_HAPPYHOUR && IS_HAPPYQP) {
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",
QST_DONE(rnum), QST_POINTS(rnum));
}
if (QST_GOLD(rnum)) {
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 ((IS_HAPPYHOUR) && (IS_HAPPYGOLD)) {
happy_gold = (int)(QST_GOLD(rnum) * (((float)(100+HAPPY_GOLD))/(float)100));
happy_gold = MAX(happy_gold, 0);
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)) {
gain_exp(ch, QST_EXP(rnum));
send_to_char(ch,
"You have been awarded %d experience points for your service.\r\n",
QST_EXP(rnum));
if ((IS_HAPPYHOUR) && (IS_HAPPYEXP)) {
happy_exp = (int)(QST_EXP(rnum) * (((float)(100+HAPPY_EXP))/(float)100));
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 (real_object(QST_OBJ(rnum)) != NOTHING) {

View File

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

View File

@@ -851,6 +851,19 @@ do \
/** Defines if ch is outdoors or not. */
#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 */
#ifndef NULL
/** Just in case NULL is not defined. */