/* This is code for Global Events, created by Dalsor for AWW
 *
 * http://www.aww-mud.org
 * telnet://aww-mud.org:6500
 * 
 * This should be pretty straight-forward to install. Read the
 * comments and to the end of the file before installing. Code
 * is designed for a ROM type MUD. Not all of the requisite
 * code is included. You will need to make requests in the
 * appropriate areas. The example is in fight.c where a MOB
 * is killed, it auto-drops a treasure chest (in the treasure
 * code and traps snippets).
 *
 * Example of gevent calls:

 if ( chance < chance_diff || ( gevent->running && gevent->num == 12 ) )
 {
     if (is_human(victim) && !IS_NPC(ch))
     {
         make_treasure_chest(ch, victim, victim->level);
     }
 }
 
 * If you need help installing, best way to reach me is via
 * MUD (above).
 */


/* This is the mainfile...
 * gevent.c
 */



/***************************************************************************

                      _____  __      __  __      __
                     /  _  \/  \    /  \/  \    /  \
                    /  /_\  \   \/\/   /\   \/\/   /
                   /    |    \        /  \        /
                   \____|__  /\__/\  /    \__/\  /
                           \/      \/          \/

    As the Wheel Weaves based on ROM 2.4. Original code by Dalsor.
    See changes.log for a list of changes from the original ROM code.
    Credits for code created by other authors have been left
 	intact at the head of each function.

    Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,
    Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.

    Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael
    Chastain, Michael Quan, and Mitchell Tse.

    In order to use any part of this Merc Diku Mud, you must comply with
    both the original Diku license in 'license.doc' as well the Merc
    license in 'license.txt'.  In particular, you may not remove either of
    these copyright notices.

    Much time and thought has gone into this software and you are
    benefitting.  We hope that you share your changes too.  What goes
    around, comes around.

	ROM 2.4 is copyright 1993-1998 Russ Taylor
	ROM has been brought to you by the ROM consortium
	    Russ Taylor (rtaylor@hypercube.org)
	    Gabrielle Taylor (gtaylor@hypercube.org)
	    Brian Moore (zump@rom.org)
	By using this code, you have agreed to follow the terms of the
	ROM license, in the file Rom24/doc/rom.license

 ***************************************************************************/

#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "aww.h"
#include "interp.h"
#include "recycle.h"
#include "tables.h"

void gevent_raffle args(( void ));
void stop_raffle args(( void ));
void check_raffle args(( void ));
OBJ_DATA *faire_rand_itype args(( OBJ_DATA *fObj, bool Raffle ));
#define FaireObjectVnum    15902


void gevent_echo( char *argument )
{
    DESCRIPTOR_DATA *d;

    for (d = descriptor_list; d != NULL; d = d->next)
    {
        if ( d->character != NULL && d->connected == CON_PLAYING )
	        stc( argument, d->character );
    }
}

void gevent_heal( void )
{
    DESCRIPTOR_DATA *d;
    CHAR_DATA *dc;
    int num, heal;
    char buf[MIL];

/*
    sprintf( buf, "{GDivine energy flows through the inhabitants of the world.\n\r{x" );
    gevent_echo( buf );
*/
    for (d = descriptor_list; d != NULL; d = d->next)
    {
        if ( d->character != NULL && d->connected == CON_PLAYING )
        {
			dc = d->character;
			num = number_range( 1, 7 );
			if ( d->character->hit < d->character->max_hit )
			{
			switch( num )
			{
				case 1: /* cure light */
				    heal = dice(1, 75);
				    dc->hit = UMIN( dc->hit + heal, dc->max_hit );
					stc( "{GA briefly warm feeling fills your body and you feel physically Refreshed.{x\n\r", dc );
				break;
				case 2: /* cure critical */
				    heal = dice(75, 150);
				    dc->hit = UMIN( dc->hit + heal, dc->max_hit );
					stc( "{GA mildly warm feeling fills your body and you feel physically Refreshed.{x\n\r", dc );
				break;
				case 3: /* heal */
				    heal = dice(150, 300);
				    dc->hit = UMIN( dc->hit + heal, dc->max_hit );
					stc( "{GA comfortably warm feeling fills your body and you feel physically Refreshed.{x\n\r", dc );
				break;
				case 4: /* knit flesh */
				    heal = dice(300, 1000);
				    dc->hit = UMIN( dc->hit + heal, dc->max_hit );
					stc( "{GA comforting heat fills your body and you feel physically Refreshed.{x\n\r", dc );
				break;
				case 5: /* light refresh */
				    heal = dice(100, 300);
				    dc->hit = UMIN( dc->hit + heal, dc->max_hit );
				    heal = dice(100, 300);
					dc->move = UMIN( dc->move + heal, dc->max_move );
				    heal = dice(100, 300);
					dc->mana = UMIN( dc->mana + heal, dc->max_mana );
					stc( "{GTingles run down your spine as the divine energy flows through you.{x\n\r", dc );
				break;
				case 6: /* moderate refresh */
				    heal = dice(200, 500);
				    dc->hit = UMIN( dc->hit + heal, dc->max_hit );
				    heal = dice(200, 500);
					dc->move = UMIN( dc->move + heal, dc->max_move );
				    heal = dice(200, 500);
					dc->mana = UMIN( dc->mana + heal, dc->max_mana );
					stc( "{GShivers run down your spine as the divine energy flows through you.{x\n\r", dc );
				break;
				case 7: /* major refresh */
				    heal = dice(300, 600);
					dc->move = UMIN( dc->move + heal, dc->max_move );
				    heal = dice(300, 600);
					dc->hit = UMIN( dc->hit + heal, dc->max_hit );
				    heal = dice(300, 600);
					dc->mana = UMIN( dc->mana + heal, dc->max_mana );
					stc( "{GYour body convulses as the divine energy flows through you.{x\n\r", dc );
					act( "{G$n's body convulses as divine energy flows through $m.{x", dc, NULL, NULL, TO_ROOM );
				break;
			}
			}
		}
    }
}

void gevent_happiness( void )
{
    DESCRIPTOR_DATA *d;
    DESCRIPTOR_DATA *d2;
    CHAR_DATA *dc;
    CHAR_DATA *rand_char;
    int num, counter = 0, num_people = 0, drunk;
    char buf[MIL];
    bool got_rand_char = FALSE;

    sprintf( buf, "{GAlcohol flows freely through the inhabitants of the world.{x\n\r" );
    gevent_echo( buf );

    for (d = descriptor_list; d != NULL; d = d->next)
    {
        if ( d->character != NULL && d->connected == CON_PLAYING && d->character->pcdata->happiness == 1 )
        {
			num_people++;
		}
	}
	if ( num_people <= 1 )
	{
	    sprintf( buf, "{GAlas, not enough people are partaking...{x\n\r" );
	    gevent_echo( buf );
	    return;
	}

    for (d = descriptor_list; d != NULL; d = d->next)
    {
        if ( d->character != NULL && d->connected == CON_PLAYING && d->character->pcdata->happiness == 1 && num_people >= 2 )
        {
			dc = d->character;
			num = number_range( 3, 23 );
			drunk = number_range( 5, 10 );
		    act("{gA giant hand appears from the sky, opens $n's mouth and pours a mighty swig down $s throat!{x", dc, NULL, NULL, TO_ROOM);
		    stc("{gA giant hand appears from the sky, opens your mouth and pours a mighty swig down your throat!{x\n\r", dc);
			while( got_rand_char == FALSE )
			{
			    for (d2 = descriptor_list; d2 != NULL; d2 = d2->next)
			    {
			        if ( d2 != d
			        && d2->character != NULL
			        && d2->connected == CON_PLAYING
			        && d2->character->pcdata->happiness == 1
			        && chance ( 75 ) )
			        {
						rand_char = d2->character;
						got_rand_char = TRUE;
						break;
					}
				}
				if ( got_rand_char == TRUE )
					break;
			}
			got_rand_char = FALSE; // so it will pick a new one round
			switch( num-2 )
			{
				case 1:
					stc("{GYou begin to feel tipsy.{x\n\r", dc );
				break;
				case 2:
					stc("{GYou feel a good buzz coming on.{x\n\r", dc );
				break;
				case 3:
					stc("{GWalking is going to be a little difficult.{x\n\r", dc );
				break;
				case 4:
					stc("{GYou're feeling pretty toasty.{x\n\r", dc );
				break;
				case 5:
				    act("{G$n looses a massive belch! {Y** {yBELCH {Y**{x", dc, NULL, NULL, TO_ROOM);
					stc("{GYou loose a massive belch! {Y** {yBELCH {Y**{x\n\r", dc );
				break;
				case 6:
				    act("{G$n hurls everywhere! <{g*{G> {WPUKE {G<{g*{G>{x", dc, NULL, NULL, TO_ROOM);
					stc("{GYou hurl everywhere! <{g*{G> {WPUKE {G<{g*{G>{x\n\r", dc );
				break;
				case 7:
				    act("{G$n starts to dance wildly to imaginary music!{x", dc, NULL, NULL, TO_ROOM);
					stc("{GYou start to dance wildly to imaginary music!{x\n\r", dc );
				break;
				case 8:
				    act("{G$n begins to croak out a rousing drinking song and promptly forgets the words.{x", dc, NULL, NULL, TO_ROOM);
					stc("{GYou begin to croak out a rousing drinking song but promptly forget the words.{x\n\r", dc );
				break;
				case 9:
				    act("{G$n stumbles, spilling ale all over $mself and the person next to $m.{x", dc, NULL, NULL, TO_ROOM);
					stc("{GYou stumble, spilling ale all over yourself and the person next to you.{x\n\r", dc );
				break;
				case 10:
				    act("{G$n takes another drink, spilling most of it.{x", dc, NULL, NULL, TO_ROOM);
					stc("{GYou take another drink, spilling most of it.{x\n\r", dc );
				break;
				case 11:
				    act("{G$n falls asleep on the bar. {D.{wo{WO {YSNORE {WO{wo{D.{x", dc, NULL, NULL, TO_ROOM);
					stc("{GYou fall asleep on the bar. {D.{wo{WO {YSNORE {WO{wo{D.{x\n\r", dc );
				break;
				case 12:
				    act("{G$n stands up to get another drink and turns a funny shade of green.{x", dc, NULL, NULL, TO_ROOM);
					stc("{GYou stand up to get another drink and turn a funny shade of green.{x\n\r", dc );
				break;
				case 13:
				    act("{G$n offers to fight everyone with one hand behind $s back.{x", dc, NULL, NULL, TO_ROOM);
					stc("{GYou offer to fight everyone with one hand tied behind your back.{x\n\r", dc );
				break;
				case 14:
				    act("{G$n tries to get a wet breastplate show started. $N volunteers!{x", dc, NULL, rand_char, TO_ROOM);
					act("{GYou try to get a wet breastplate show started. $N volunteers!{x", dc, NULL, rand_char, TO_CHAR );
				break;
				case 15:
				    act("{G$n calls for a wet breastplate contest and pours ale down the front of $N's clothes!{x", dc, NULL, rand_char, TO_ROOM);
					act("{GYou call for a wet breastplate contest and pour ale down the front of $N's clothes!{x", dc, NULL, rand_char, TO_CHAR );
				break;
				case 16:
				    act("{G$n asks the barmaid for more roasted peas to munch.  (since they dont have peanuts){x", dc, NULL, NULL, TO_ROOM);
					stc("{GYou ask the barmaid for more roasted peas to munch.  (since they dont have peanuts){x\n\r", dc );
				break;
				case 17:
				    act("{G$n attempts to do the sa'sara but instead looks like a dancing monkey.{x", dc, NULL, NULL, TO_ROOM);
					stc("{GYou attempt to do the sa'sara but instead look like a dancing monkey.{x\n\r", dc );
				break;
				case 18:
				    act("{G$n turns to $N and says, 'You are my BEST friend!'{x", dc, NULL, rand_char, TO_ROOM);
				    act("{GYou turn to $N and say, 'You are my BEST friend!'{x", dc, NULL, rand_char, TO_CHAR);
				break;
				case 19:
				    act("{G$n turns to $N and says, 'I LOVE YOU MAN!'{x", dc, NULL, rand_char, TO_ROOM);
				    act("{GYou turn to $N and say, 'I LOVE YOU MAN!'{x", dc, NULL, rand_char, TO_CHAR);
				break;
				case 20:
				    act("{G$n hops up on the bar and begins to perform a striptease, {C-{B*{YO{WO{YH L{WA L{YA!{B*{C-{x'{x", dc, NULL, rand_char, TO_ROOM);
				    act("{GYou hop up on the bar and begin to perform a striptease, {C-{B*{YO{WO{YH L{WA L{YA!{B*{C-{x'{x", dc, NULL, rand_char, TO_CHAR);
				break;
				case 21:
				    act("{G$n bounces into $N's lap and gives $M a sultry lap dance. YAY BEER!'{x", dc, NULL, rand_char, TO_ROOM);
				    act("{G$n bounces into $N's lap and gives $M a sultry lap dance. YAY BEER!'{x", dc, NULL, rand_char, TO_CHAR);
				break;
			}
			if ( dc->pcdata->condition[COND_DRUNK] <= 30 )
			    gain_condition( dc, COND_DRUNK, num * 2 );
		}

    }
    for (d = descriptor_list; d != NULL; d = d->next)
    {
        if ( d->character != NULL && d->connected == CON_PLAYING && d->character->pcdata->happiness == 1 )
        {
			counter++;
		}
	}
	if ( counter > 10 && chance( 80 ) )
	{
		sprintf( buf, "\n\r{YThe bar gets so overloaded it crashes into splinters!{x\n\r{Y%s quickly finds a new bar and everybody climbs up!\n\r", rand_char->name );
		gevent_echo( buf );
	}
}

void check_raffle( void )
{
	int i;
	char buf[MSL];
    DESCRIPTOR_DATA *d;
	if ( gevent->num == 2 )
	{
		if ( raffle->total_tickets <= 0 )
		{
			sprintf( buf, "{W-{R>{Y No one bought any tickets at the raffle!{x" );
			gevent_echo( buf );
			return;
		}
		else if ( raffle->total_tickets == 1 )
		{
			i = 1;
			sprintf( buf, "{W-{R>{Y And the winning ticket number is 1!{x" );
			gevent_echo( buf );
		}
		else
		{
			i = number_range( 1, raffle->total_tickets );
			sprintf( buf, "{W-{R>{Y And the winning ticket number is %d!{x", i );
			gevent_echo( buf );
		}
	    for (d = descriptor_list; d != NULL; d = d->next)
	    {
	        if ( d->character != NULL
	        && d->character->pcdata != NULL
	        && d->connected == CON_PLAYING
	        && d->character->pcdata->ticket_number == i )
	        {
				sprintf( buf, "\n\r{W-{R>{Y %s holds the winning ticket!{x\n\r", capit2(d->character->name) );
				gevent_echo( buf );
				ptc( d->character, "\n\r{w%s appears in your hands!\n\r", capit2(raffle->obj->short_descr) );
				obj_to_char( raffle->obj, d->character );
			}
	    }
		stop_raffle();
	}
}
void stop_raffle( void )
{
    DESCRIPTOR_DATA *d;

    for (d = descriptor_list; d != NULL; d = d->next)
    {
        if ( d->character != NULL && d->character->pcdata != NULL && d->connected == CON_PLAYING )
	        d->character->pcdata->ticket_number = -1;
    }
    raffle->running = FALSE;
    raffle->total_tickets = -1;
}
void gevent_update( void )
{
	int timer = 1, runtime = 0;
	char buf[MSL];

	if ( gevent == NULL )
		return;
	if ( gevent->running == FALSE )
		return;
	if ( gevent->timer == -1 )
	{
		gevent->timer = 0;
		return;
	}

	timer = gevent->timer;
	runtime = gevent->runtime;

	/* the gevent runs until stopped
	 * this is the case for invasions, false dragons, etc
	 */
	if ( runtime <= 0 )
	{
		return;
	}

	if ( gevent->num == 6 ) /* free heals */
		gevent_heal();
	if ( gevent->num == 9 ) /* happy hour */
		gevent_happiness();

	/* the gevent is still running, let it keep running */
	if ( timer <= runtime )
	{
		/*sprintf( buf, "{R[{WG{wlobal {WE{wvent{R]{w: %s{w is still running.{x\n\r", gevent->cname );
		gevent_echo( buf );*/
	}
	/* the gevent needs stopping since the run timer has been reached */
	else if ( timer >= runtime )
	{
		buf[0] = '\0';
		sprintf( buf, "{R[{WG{wlobal {WE{wvent{R]{w: %s{w has come to an end!{x\n\r", gevent->cname );
		gevent_echo( buf );

		check_raffle();

		gevent->running = FALSE;

		free_string( gevent->name );
		gevent->name = NULL;

		free_string( gevent->cname );
		gevent->cname = NULL;

		gevent->loc = -1;
		gevent->num = -1;
		gevent->power = -1;
		gevent->timer = -1;
		gevent->runtime = -1;
		/*free( gevent );*/

		return;
	}

	gevent->timer++;
	return;
}
void gevent_create( CHAR_DATA *ch, int gnum, bool begin, int option2, int option3 )
{
	char buf[MSL];
	ROOM_INDEX_DATA * groom;
	int gvnum, settimer = 1;

	groom = ch->in_room;
	gvnum = groom->vnum;

	if ( option3 > 0 )
		settimer = option3;

	if ( begin )
	{
		stc( "Starting the event...\n\r", ch );
		gevent->running = TRUE;
		gevent->loc = gvnum;
		gevent->name = str_dup( gevent_table[gnum].name );
		gevent->cname = str_dup( gevent_table[gnum].cname );
		gevent->timer = 0;
		if ( settimer > 0 )
			gevent->runtime = settimer;
		else
			gevent->runtime = gevent_table[gnum].deftime;
		gevent->num = gnum;
	}
	else
	{
		stc( "Stopping the event...\n\r", ch );
		buf[0] = '\0';
		sprintf( buf, "{R[{WG{wlobal {WE{wvent{R]{w: %s{w has been stopped!{x\n\r", gevent_table[gnum].cname );
		gevent_echo( buf );
		gevent->running = FALSE;
		free_string( gevent->name );
		gevent->name = NULL;
		free_string( gevent->cname );
		gevent->cname = NULL;
		check_raffle();
		return;
	}


	switch( gnum )
	{
		case 0: /* shadows embrace */
			ptc( ch, "%s placed in %s [%d]\n\r", gevent->name, groom->name, gvnum );
			if ( option2 < 1 || option2 > 3 )
			{
				stc( "Power level for this event is out of range.\n\r", ch );
				gevent_create( ch, gnum, FALSE, -1, 0 );
				return;
			}
			gevent->power = option2;
			gevent->timer = 1;
			gevent->runtime = 10;
		break;
		case 1: /* false dragon */
		break;
		case 2: /* raffle */
			gevent_raffle();
			ptc( ch, "%s started with a %s\n\r", gevent->name, raffle->obj->short_descr, gvnum );
			sprintf( buf, "\n\r{R-{W> {YRa{yffli{Yng{x %s.\n\r{R-{W> {YTi{yck{Yet {yC{Yos{yt{w:{W %d silver marks{x.\n\r", raffle->obj->short_descr, raffle->ticket_cost );
			gevent_echo( buf );
		break;
		case 3: /* free xps */
		break;
		case 4: /* free qps */
		break;
		case 5: /* treasure hunt */
		break;
		case 6: /* free heals */
		break;
		case 7: /* hawkwing's revenge */
		break;
		case 8: /* avenging malkier */
		break;
		case 9: /* happy hour */
			sprintf( buf, "\n\r{R-{W> To participate in this event type GEvent Get Happy{x.\n\r" );
			gevent_echo( buf );
		break;
		case 10: /* matrim's luck */
		break;
		case 11: /* creator's blessing */
		break;
	}
	return;
}
void do_gevent( CHAR_DATA *ch, char *argument )
{
	char arg1[MIL], arg2[MIL], arg3[MIL], arg4[MIL];
	int option2 = 0, option3 = 0;
	char buf[MSL];

	argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );
	argument = one_argument( argument, arg3 );
	argument = one_argument( argument, arg4 );

	if ( arg1[0] == '\0' )
	{
		stc( "Syntax:\n\r", ch );
		stc( "GEvent (Lists possible GEvents)\n\r", ch );
		if ( IS_IMMORTAL( ch ) )
			stc( "GEvent Help\n\r", ch );
		return;
	}

	if ( IS_IMMORTAL( ch ) && !str_cmp( arg1, "help" ) )
	{
		int x;
		stc( "[#]  Event Name      Time  Options\n\r", ch );
		stc( "------------------------------------------------------------\n\r", ch );
		for ( x = 0; gevent_table[x].name != NULL; x++ )
		{
			ptc( ch, "[%d] %-16s [%2dm] %s\n\r     %s\n\r",
				gevent_table[x].num,
				gevent_table[x].name,
				gevent_table[x].deftime,
				gevent_table[x].immopt,
				gevent_table[x].descr );
		}
		stc( "\n\rSyntax:  GEvent <#> <start|stop> <option1> <option2>\n\r", ch );
		stc( "Example: GEvent 0 start 3 10\n\r", ch );
		stc( "         Run gevent #0 at 3 strength for 10 pulses.\n\r", ch );
		stc( "Example: GEvent 4 stop -1\n\r", ch );
		stc( "         Stop gevent #4.\n\r", ch );
		return;
	}
	else if ( !str_cmp( arg1, "list" ) )
	{
		int x;
		stc( "Event Name          Time  Description\n\r", ch );
		stc( "----------------------------------\n\r", ch );
		for ( x = 0; gevent_table[x].name != NULL; x++ )
		{
			ptc( ch, "%19s -- %s\n\r",
				gevent_table[x].name,
				gevent_table[x].descr );
		}
		return;
	}
	/* players must opt in for the happy hour event */
	else if ( !str_cmp( arg1, "get" ) )
	{
		if ( gevent->running == FALSE || gevent->num != 9 )
		{
			stc("There is no Happy Hour event occuring right now.\n\r", ch);
			return;
		}
		if ( !str_cmp( arg2, "happy" ) )
		{
			if ( ch->pcdata->condition[COND_DRUNK] > 10 )
			{
				stc("You're already wasted.\n\r", ch);
				return;
			}
			if ( ch->pcdata->happiness == 1 )
			{
				stc("You're already partying!\n\r", ch);
				return;
			}
			stc("{GWoo hoo! Where's the party!?{x\n\r", ch);
			sprintf( buf, "{G%s jumps up on the nearest bar and starts to PARTY!{x\n\r", ch->name );
			gevent_echo( buf );
			ch->pcdata->happiness = 1;
			return;
		}
	}
	else if ( !str_cmp( arg1, "raffle" ) )
	{
		if ( gevent->running == FALSE || gevent->num != 2 || raffle->running == FALSE )
		{
			stc("There is no raffle event occuring right now.\n\r", ch);
			return;
		}
		if ( !str_cmp( arg2, "info" ) )
		{
			identify_obj( ch, raffle->obj );
			return;
		}
		if ( !str_cmp( arg2, "ticket" ) )
		{
			int cost = raffle->ticket_cost;
			if (!IS_SET(ch->in_room->room_flags, ROOM_BANK))
			{
				stc("You are not in a bank.\n\r",ch);
				return;
			}
			if ( !check_coins( ch, cost, 0, 0 ) && !check_coins( ch, cost, 1, 1 ) )
			{
				ptc( ch, "You can't afford a raffle ticket for this item.\n\rYou need %d coins.\n\r", cost );
				return;
			}
			else if ( ch->pcdata->ticket_number >= 0 )
			{
				stc( "You already have a raffle ticket!\n\r", ch );
				ptc( ch, "Your ticket number is %d.\n\r", ch->pcdata->ticket_number );
				return;
			}
			else
			{
				if ( raffle->total_tickets <= 0 )
					raffle->total_tickets = 1;
				else
					raffle->total_tickets++;
				if ( check_coins( ch, cost, 0, 0 ) )
				{
					deduct_cost( ch, cost, 0 );
					ptc( ch, "You purchase a raffle ticket for %d coins from your pocket.\n\rYour ticket number is %d.\n\r", cost, raffle->total_tickets );
				}
				else
				{
					deduct_cost( ch, cost, 1 );
					ptc( ch, "You purchase a raffle ticket for %d coins from your bank account.\n\rYour ticket number is %d.\n\r", cost, raffle->total_tickets );
				}
				ch->pcdata->ticket_number = raffle->total_tickets;
			}
		}
	}
	else if ( IS_IMMORTAL( ch ) && is_number( arg1 ) )
	{
		int gnum = atoi( arg1 );
		if ( gevent_table[gnum].name == NULL )
		{
			stc( "An invalid number for the gevent was specified.\n\r", ch );
			return;
		}
		else if ( arg2[0] == '\0' )
		{
			stc( "You did not specify a valid start or stop option.\n\r", ch );
			return;
		}
		if ( !str_cmp( arg2, "start" ) )
		{
			if ( gevent->running )
			{
				ptc( ch, "Global Event: %s is already running.\n\r", gevent->name );
				return;
			}
			if ( arg3[0] == '\0' )
			{
				stc( "You did not specify any event options.\n\r", ch );
				return;
			}
			if ( !is_number( arg3 ) )
			{
				stc( "You did not specify a valid event option.\n\r", ch );
				return;
			}
			if ( !gevent_table[gnum].working )
			{
				ptc( ch, "Global event %s does not currently work.\n\r", gevent_table[gnum].cname );
				return;
			}
			if ( arg4[0] != '\0' && is_number( arg4 ) )
				option3 = atoi( arg4 );
			option2 = atoi( arg3 );
			buf[0] = '\0';
			sprintf( buf, "{R[{WG{wlobal {WE{wvent{R]{w: %s{w has started.{x\n\r", gevent_table[gnum].cname );
			gevent_echo( buf );
			buf[0] = '\0';
			sprintf( buf, "{G%s{w\n\r", gevent_table[gnum].longd );
			gevent_echo( buf );
			gevent_create( ch, gnum, TRUE, option2, option3 );
			return;
		}
		else if ( !str_cmp( arg2, "stop" ) )
		{
			gevent_create( ch, gnum, FALSE, option2, option3 );
			return;
		}
		else
		{
			stc( "You did not specify a valid stop or start option.\n\r", ch );
			return;
		}
		return;
	}
	else
		do_function( ch, &do_gevent, "" );
	return;
}
void gevent_raffle( void )
{
	OBJ_DATA *obj, *rObj;

	obj = create_object( get_obj_index( FaireObjectVnum ), 1 );
	rObj = faire_rand_itype( obj, TRUE );

	raffle->running = TRUE;
	raffle->obj = rObj;
	raffle->ticket_cost = 50;
	return;
}
void gevent_makeghost( CHAR_DATA *bubble )
{
    char nbuf[MSL], sbuf[MSL], lbuf[MSL];
    int i = 0;

	if ( gevent->num != 0 ) /* not in shadows embrace */
	{
		bug( "Gevent_MakeGhost: Making a ghost but no gevent is running!", 0 );
		return;
	}

	sprintf( nbuf, "spirit %s", bubble->name );
	sprintf( sbuf, "the spirit of %s", bubble->short_descr );
	sprintf( lbuf, "The avenging spirit of %s.\n\r", bubble->short_descr );

	free_string( bubble->name );
	    bubble->short_descr	= str_dup( nbuf );
	free_string( bubble->short_descr );
	    bubble->short_descr	= str_dup( sbuf );
	free_string( bubble->long_descr );
	    bubble->long_descr	= str_dup( lbuf );
	free_string(bubble->description);
	    bubble->description	= str_dup("");

	if ( gevent->power == 1 )      /* less than bubble */
	    bubble->level	= bubble->level / 1.5;
	else if ( gevent->power == 2 ) /* equal to bubble */
	    bubble->level	= bubble->level;
	else                          /* greater than bubble */
	    bubble->level	= bubble->level * 1.5;

	if ( gevent->power == 1 )
	    bubble->hit		= bubble->max_hit / 1.5;
	else if ( gevent->power == 2 )
	    bubble->hit		= bubble->max_hit;
	else
	    bubble->hit		= bubble->max_hit * 1.5;
	bubble->max_hit = bubble->hit;

	if ( gevent->power == 1 )
	    bubble->mana		= bubble->max_mana / 1.5;
	else if ( gevent->power == 2 )
	    bubble->mana		= bubble->max_mana;
	if ( gevent->power == 1 )
	    bubble->mana		= bubble->max_mana * 1.5;
    bubble->max_mana = bubble->mana;

	if ( gevent->power == 1 )
	    bubble->move		= bubble->max_move / 1.5;
	else if ( gevent->power == 2 )
	    bubble->move		= bubble->max_move;
	else
	    bubble->move		= bubble->max_move * 1.5;
    bubble->max_move = bubble->move;

	if ( gevent->power == 1 )
	    bubble->hitroll	= bubble->hitroll / 1.5;
	else if ( gevent->power == 2 )
	    bubble->hitroll	= bubble->hitroll;
	else
	    bubble->hitroll	= bubble->hitroll * 1.5;

	if ( gevent->power == 1 )
	    bubble->damroll	= bubble->damroll / 1.5;
	else if ( gevent->power == 2 )
	    bubble->damroll	= bubble->damroll;
	else
	    bubble->damroll	= bubble->damroll * 1.5;

    for (i = 0; i < 4; i++)
    	bubble->armor[i]	= bubble->armor[i];

    for (i = 0; i < MAX_STATS; i++)
    {
		if ( gevent->power == 1 )
			bubble->perm_stat[i]	= bubble->perm_stat[i] / 1.5;
		else if ( gevent->power == 2 )
			bubble->perm_stat[i]	= bubble->perm_stat[i];
		else
			bubble->perm_stat[i]	= bubble->perm_stat[i] * 1.5;
		bubble->mod_stat[i]	= bubble->perm_stat[i];
    }

    for (i = 0; i < 3; i++)
    {
		if ( gevent->power == 1 )
			bubble->damage[i]	= bubble->damage[i] / 1.5;
		else if ( gevent->power == 2 )
			bubble->damage[i]	= bubble->damage[i];
		else
			bubble->damage[i]	= bubble->damage[i] * 1.5;
	}
	return;
}

/* end mainfile...
 * gevent.c
 */

/* This is the main header file...
 * aww.h, mud.h, etc
 */

#define stc send_to_char
#define ptc printf_to_char

typedef struct  gevent_data          GEVENT_DATA;

/* in PC data ... */
sh_int      ticket_number; /* gevent raffle -- Dalsor */
sh_int      happiness; /* gevent Happy Hour -- Dalsor */

struct gevent_data
{
	bool running;     /* is the event running? */
	char * name;      /* name of the gevent */
	char * cname;     /* color name of the gevent */
	long loc;          /* vnum location of event set when started */
	sh_int num;       /* number of event for easy identifying */
	sh_int power;     /* 1 2 3 for shadows embrace gevent */
	sh_int timer;     /* how long is/has it been running */
	sh_int runtime;   /* the time it is supposed to run for */
};

extern GEVENT_DATA *gevent;

/* gevent.c */
void gevent_echo        args( ( char *argument ) );
void gevent_create      args( ( CHAR_DATA *ch, int gnum, bool begin, int option2, int option3 ) );

typedef struct  gevent_data          GEVENT_DATA;

/* in tables.c */
const   struct  gevent_type gevent_table [] =
{
	{ /* 0 */
		0, "Shadows Embrace", "{bSh{Badows {bEm{Bbrace{x", 15,
		"The Dark One raises ghosts to strengthen his armies.",
		"Ghosts are raised by the Dark One to strengthen his armies.\n\r" \
		"As creatures die they are replaced by avenging spirits\n\r" \
		"which seek to carry out the Dark One's work.\n\r",
		"<1|2|3> Set strength to 1 lesser, 2 equal, 3 greater.",
		TRUE,
	},
	{ /* 1 */
		1, "False Dragon", "{RFal{rse {RDra{rgon{x", -1,
		"A False Dragon has arisen to claim control of the lands.",
		"A False Dragon has arisen to claim control of the lands,\n\r" \
		"bringing with him many fell followers who seek to convert\n\r" \
		"the masses to the False Dragon's cause and slay any who\n\r" \
		"attempt to resist.\n\r",
		"<#> Sets number of followers the False Dragon Has.",
		FALSE,
	},
	{ /* 2 */
		2, "Raffle", "{YRa{yff{Yle{x", 3,
		"A powerful item is raffled.",
		"A powerful item is raffled. You may purchase tickets at your\n\r" \
		"local bank clerk, who has an unlimited supply. Once the time\n\r" \
		"for this event has ended the the person with the winning ticket\n\r" \
		"will receive the item that has been raffled. Note: To buy a ticket\n\r" \
		"from the bank clerk, type {yGevent Raffle Ticket{x\n\r",
		"<Item> Sets the item to be raffled.",
		TRUE,
	},
	{ /* 3 */
		3, "Free XP", "{wFree {WXP{x", 60,
		"A number of free experience points are given per kill.",
		"A number of free experience points are given per kill. While this\n\r" \
		"event is going on any kill will generate additional XP and trains.\n\r",
		"<#> Sets the number of free XPs per kill.",
		TRUE,
	},
	{ /* 4 */
		4, "Free QP", "{wFree {WQP{x", 60,
		"A number of free quest points are given per quest.",
		"A number of free quest points are given per quest. While this event\n\r" \
		"is running any quest that is completed will generate an additional\n\r" \
		"quest point reward which is added to the normal reward.\n\r",
		"<#> Sets the number of free XPs per kill.",
		TRUE,
	},
	{ /* 5 */
		5, "Treasure Hunt", "{CTr{Ceasu{Cre {CH{cun{Ct{x", 20,
		"Random items are made part of a treasure hunt.",
		"A number of random items in the MUD are made part of a treasure\n\r" \
		"hunt. When the event ends, whoever has the most items will win a\n\r" \
		"reward of gold coins.\n\r",
		"<#> Sets the reward in gold coins.",
		FALSE,
	},
	{ /* 6 */
		6, "Free Heals", "{gF{Gree {gH{Geals{x", 20,
		"Characters receive free heals of random types.",
		"Characters receive free heals of random types for the duration of\n\r" \
		"the event. Each heal for each character is randomly determined each\n\r" \
		"time a heal occurs.\n\r",
		"<#> No special options.",
		TRUE,
	},
	{ /* 7 */
		7, "Hawkwing's Revenge", "{RH{ya{Ywk{Rw{yi{Yng{R'{ys {rRevenge{x", 20,
		"Hawkwing's followers return to finish their assault.",
		"Characters choose to follow Hawkwing's armies or defend Tar Valon.\n\r" \
		"Once the last attacker or defender is dead, the battle is decided\n\r" \
		"and rewards are metted out.\n\r\n\rThis is a PK event.",
		"<#> No special options.",
		FALSE,
	},
	{ /* 8 */
		8, "Avenging Malkier", "{RAvenging {WMa{wl{Dk{wie{Wr{x", 20,
		"The Golden Crane has been raised.",
		"Characters choose to follow into the Blight to avenge the fallen.\n\r" \
		"nation of Malkier. Only those in the Shadow guilds may choose to\n\r" \
		"to defend the Shadow-overrun nation. Once the last attacker or\n\r" \
		"defender is dead, the battle is decided and the rewards are metted\n\r" \
		"out.\n\r\n\rThis is a PK event.",
		"<#> No special options.",
		FALSE,
	},
	{ /* 9 */
		9, "Happy Hour", "{GH{gapp{Gy {GH{gou{Gr{x", 20,
		"Let the Party Start!",
		"The Dark One and the Creator have finally agreed on something: You\n\r" \
		"people need to party more!\n\r",
		"<#> No special options.",
		TRUE,
	},
	{ /* 10 */
		10, "Matrim's Luck", "{DM{ga{Gtr{gi{Dm{w's {DL{gu{Gc{Dk{x", 20,
		"Mat's luck spreads briefly through the world's people.",
		"Characters are given a Ta'veren's luck for a brief while. Bonuses are\n\r" \
		"given to many different things while this event is in place.\n\r",
		"<#> No special options.",
		FALSE,
	},
	{ /* 11 */
		11, "Creator's Blessing", "{WC{wr{Ce{Wa{wt{Co{Wr{w's {WB{wl{Ce{Ws{wsi{Cn{Wg{x", 20,
		"The Creator's Light shines upon the people of the world.",
		"Characters are given special bonuses and enhancements while this event is\n\r" \
		"running. In some cases, the bonuses may last even after the event has ended.\n\r",
		"<#> No special options.",
		FALSE,
	},
	{ /* 12 */
		12, "Ton 'o Chests", "{GT{Yo{Gn {G'o {YCh{Ge{Ws{Gt{Ys{x", 20,
		"Treasure chests drop at every kill.",
		"When a mobile is killed it will automatically drop a treasure chest so long\n\r" \
		"as it is a human type mobile.\n\r",
		"<#> No special options.",
		TRUE,
	},
	{ /* ender */
		0, NULL, NULL, -1,
		"Nothingness. The void of the event table.",
		"Nothingness. The void of the event table.",
		"Nothingness. The void of the event table.",
		FALSE
	},
};

/* tables.h */
extern  const   struct  gevent_type gevent_table[];

struct gevent_type
{
	sh_int num;       /* number of the gevent */
	char * name;      /* name of the gevent */
	char * cname;     /* color name of the gevent */
	sh_int deftime;   /* default run time */
	char * descr;     /* generic description of the event */
	char * longd;     /* long description, shown when event starts */
	char * immopt;    /* immortal options, shown in gevent help */
	bool   working;   /* if it doesn't work don't let it run. */
};

/* update.c / update_handler */

if ( --pulse_minute <= 0 )
{
    pulse_minute = PULSE_MINUTE;
    gevent_update();
}