player/a/
player/b/
player/c/
player/d/
player/e/
player/f/
player/g/
player/i/
player/j/
player/k/
player/m/
player/n/
player/r/
player/s/
player/v/
player/w/
player/x/
player/z/
player_fst/e/
player_fst/f/
player_fst/h/
player_fst/i/
player_fst/j/
player_fst/n/
player_fst/o/
player_fst/p/
player_fst/player/a/
player_fst/player/b/
player_fst/player/c/
player_fst/player/d/
player_fst/player/e/
player_fst/player/f/
player_fst/player/g/
player_fst/player/j/
player_fst/player/k/
player_fst/player/m/
player_fst/player/n/
player_fst/player/r/
player_fst/player/s/
player_fst/player/v/
player_fst/player/w/
player_fst/player/x/
player_fst/player/z/
player_fst/u/
player_fst/v/
player_fst/w/
player_fst/x/
/*~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
 ~  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.                              ~
 ~                                                                         ~
 ~  Ack 2.2 improvements copyright (C) 1994 by Stephen Dooley              ~
 ~  ACK!MUD is modified Merc2.0/2.1/2.2 code (c)Stephen Zepp 1998 Ver: 4.3 ~
 ~                                                                         ~
 ~  In order to use any part of this  PA  Diku Mud, you must comply with   ~
 ~  both the original Diku license in 'license.doc' as well the Merc       ~
 ~  license in 'license.txt', and the Ack!Mud license in 'ack_license.txt'.~
 ~  In particular, you may not remove any of these copyright notices.      ~
 ~                                                                         ~
 ~           _______      _____                                            ~
 ~          /  __  /\    / ___ \       222222        PA_MUD by Amnon Kruvi ~
 ~         /______/ /   / /___\ \            2       PA_MUD is modified    ~
 ~        / _______/   / _______ \           2       Ack!Mud, v4.3         ~
 ~       /_/          /_/       \_\        2                               ~
 ~                                      2                                  ~
 ~                                     2222222                             ~
 ~                                                                         ~
 ~                                                                         ~
 ~   Years of work have been invested to create DIKU, Merc, Ack and PA.    ~
 ~   Please show your respect by following the licenses, and issuing       ~
 ~   credits where due.                                                    ~
 ~                                                                         ~
 ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-*/


#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <sys/time.h>
#include <sys/resource.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "ack.h"
#include <signal.h>

/*
 * Local functions.
 */
bool	fast_healing	args( (CHAR_DATA *ch) );
int     hit_gain        args( ( CHAR_DATA *ch ) );
void    weather_update  args( ( void ) );
void    init_weather    args( ( void ) );
void    char_update     args( ( void ) );
void    gain_update     args( ( int client ) );
void    obj_update      args( ( void ) );
void    bomb_update     args( ( void ) );
void	vehicle_update	args( ( void ) );
void    aggr_update     args( ( void ) );
void    rooms_update    args( ( void ) );
void    quest_update	args( ( void ) );
void    maze_update     args( ( void ) );
void 	update_last_obj args( ( void ) );
void 	mode_update     args( ( void ) );
void	spec_update	args( ( void ) );
void	spec_up		args( ( CHAR_DATA *ch ) );

int	abort_threshold = BOOT_DB_ABORT_THRESHOLD;
bool	disable_timer_abort = FALSE;
int	last_checkpoint;
extern char * const compass_name[];
extern const sh_int  rev_dir[];

int get_user_seconds ()
{
	struct rusage rus;
	getrusage (RUSAGE_SELF, &rus);
	return rus.ru_utime.tv_sec;
}

/* Update the checkpoint */
void alarm_update ()
{
  extern int ssm_dup_count;
  extern int ssm_loops;

  ssm_dup_count=0;
  ssm_loops=0;

	last_checkpoint = get_user_seconds();
	if (abort_threshold == BOOT_DB_ABORT_THRESHOLD)
	{
		abort_threshold = RUNNING_ABORT_THRESHOLD;
		fprintf (stderr, "Used %d user CPU seconds.\n", last_checkpoint);
	}
}
#ifndef WIN32
/* Set the virtual (CPU time) timer to the standard setting, ALARM_FREQUENCY */

void reset_itimer ()
{
	struct itimerval itimer;
	itimer.it_interval.tv_usec = 0; /* miliseconds */
	itimer.it_interval.tv_sec  = ALARM_FREQUENCY;
	itimer.it_value.tv_usec = 0;
	itimer.it_value.tv_sec = ALARM_FREQUENCY;

	/* start the timer - in that many CPU seconds, alarm_handler will be called */	
	if (setitimer (ITIMER_VIRTUAL, &itimer, NULL) < 0)
	{
//		perror ("reset_itimer:setitimer");
//		exit (1);
	}
}
#endif

const char * szFrozenMessage = "Alarm_handler: Not checkpointed recently, aborting!\n";

/* Signal handler for alarm - suggested for use in MUDs by Fusion */
void alarm_handler (int signo)
{
	int usage_now = get_user_seconds();

	/* Has there gone abort_threshold CPU seconds without alarm_update? */
    if (!disable_timer_abort && (usage_now - last_checkpoint > abort_threshold ))
	{
		/* For the log file */
        char buf[MAX_STRING_LENGTH];
	extern int ssm_dup_count;
	extern int ssm_loops;
	extern int ssm_recent_loops;

	/* spec: log usage values */
	log_f("current usage: %d, last checkpoint: %d",
	     usage_now, last_checkpoint);
	log_f("SSM dups: %d, loops: %d, recent: %d",
	     ssm_dup_count, ssm_loops, ssm_recent_loops);
	
        sprintf(buf,  "%s\n\r", szFrozenMessage );
	bug(buf,0);
	raise(SIGABRT); /* kill ourselves on return */
//	do_hotreboot(NULL,"crash"); //Lets see if this works...
	}
	
	/* The timer resets to the values specified in it_interval 
	 * automatically.
	 *
	 * Spec: additionally, SIGABRT is blocked in this handler, and will
	 * only be delivered on return. This should ensure a good core.
	 */
}

#ifndef WIN32
/* Install signal alarm handler */
void init_alarm_handler()
{
	struct sigaction sa;
	
	sa.sa_handler = alarm_handler;
	sa.sa_flags = SA_RESTART; /* Restart interrupted system calls */
	sigemptyset(&sa.sa_mask);
	sigaddset(&sa.sa_mask, SIGABRT); /* block abort() in the handler
					  * so we can get a good coredump */

	if (sigaction(SIGVTALRM, &sa, NULL) < 0) /* setup handler for virtual timer */
	{
		perror ("init_alarm_handler:sigaction");
		exit (1);
	}
	last_checkpoint = get_user_seconds();
	reset_itimer(); /* start timer */
}
#endif

/*
 * Regeneration stuff.
 */
int hit_gain( CHAR_DATA *ch )
{
    int gain;
    BUILDING_DATA *bld;

   gain = 7;
   if ( ch->effect2/100 == EFFECT2_REGENERATION )
	gain *= 5;
   if ( ch->poison > 0 && ch->poison / 100 == POISON_ANTHRAX )
	gain = -15;
   if ( ( bld = ch->in_building ) != NULL )
   {
	if ( bld->value[9] > 0 )
	{
		if ( ch->in_vehicle )
			send_to_char( "Your vehicle keeps you safe from the fallout.\n\r", ch);
		else
		{
			send_to_char( "@@eYou are hurt by the nuclear fallout!@@N\n\r", ch);
			gain = -40;
			if ( ch->poison > 0 && ch->poison / 100 == POISON_ANTHRAX )
				gain -= 15;
		}
	}
	else if ( bld->type == BUILDING_VOLCANIC_CHAMBER )
	{
		if ( ch->poison > 0 )
		{
			ch->poison = 0;
			send_to_char("You feel cured of the poison.\n\r",ch);
		}
		gain = ch->max_hit - ch->hit;
	}
   }

   return UMIN(gain, ch->max_hit - ch->hit);
}

void spec_update( void )
{
	CHAR_DATA *ch;
	for ( ch = first_char;ch;ch = ch->next )
	{
		if ( IS_SET(ch->config,CONFIG_BLIND) )
			if ( --ch->pcdata->spec_timer <= 0 )
			{
				spec_up(ch);
				ch->pcdata->spec_timer = ch->pcdata->spec_init;
			}
	}
	return;
}
void spec_up( CHAR_DATA *ch )
{
	CHAR_DATA *wch;
	int xx,yy,x,y,maxx,range,z=ch->z;
	OBJ_DATA *obj;
	char buf[MSL];

	if ( IS_SET(ch->config,CONFIG_LARGEMAP) )
		maxx = ch->map;
	else
		maxx = ch->map / 2;
	range = 0;
	if ( ( obj = get_eq_char(ch,WEAR_HOLD_HAND_L) ) != NULL )
		if ( obj->item_type == ITEM_WEAPON )
			range = obj->value[4] + 1;
	for ( xx = ch->x - maxx;xx < ch->x + maxx;xx++ )
	for ( yy = ch->y - maxx;yy < ch->y + maxx;yy++ )
	{
		x = xx;y = yy;real_coords(&x,&y);
		for ( wch = map_ch[x][y][z];wch;wch = wch->next_in_room )
		{
			if ( wch == NULL || wch == ch || wch->z != ch->z )
				break;
			sprintf( buf, "%s%s at %d/%d (%s%s)\n\r", (IS_BETWEEN(x,ch->x-range,ch->x+range) && IS_BETWEEN(y,ch->y-range,ch->y+range)) ? "(*) " : "", wch->name, x, y, (ch->y < y) ? "North" : (ch->y == y ) ? "" : "South", (ch->x > x) ? "West" :(ch->x == x) ? "" : "East" );
			send_to_char( buf, ch );
		}
	}
}
void gain_update( int client )
{
   CHAR_DATA *ch;
    CHAR_DATA *ch_next;
   OBJ_DATA *obj;
   bool n = FALSE;
   
   for ( ch = first_char; ch != NULL; ch = ch_next )
   {
	ch_next = ch->next;
/*	if ( IS_SET(ch->config,CONFIG_CLIENT) )
		do_mapper(ch,"");*/
	if ( client )
		continue;

	if ( ch->pcdata->lastskill > 0 )
		ch->pcdata->lastskill--;
      if ( ch->dead || ch->c_sn == gsn_dead || ch->position == POS_DEAD )
      {
	pdie(ch);
	continue;
      }
      if ( ch->position == POS_DEAD )
	ch->position = POS_STANDING;
      if ( ch->position >= POS_STUNNED )
      {
	 ch->hit = URANGE( -100, ch->hit + hit_gain(ch), ch->max_hit );

	 if ( ch->hit < 0 )
	 {
		if ( check_dead(ch,ch) )
			continue;
	 }
         if ( ch->carry_weight > can_carry_w( ch ) )
           send_to_char( "You are carrying so much weight that you are @@eEXHAUSTED@@N!!\n\r", ch );
      }

      obj = get_eq_char(ch,WEAR_HEAD);
      n = ( obj && obj->item_type == ITEM_SUIT && obj->value[0] == 1 );
      if ( IS_SET(ch->effect,EFFECT_TRACER) && (number_percent() < 3 || fast_healing(ch) || n))
	REMOVE_BIT(ch->effect,EFFECT_TRACER);
      if ( IS_SET(ch->effect,EFFECT_BLIND) && (number_percent() < 10 || fast_healing(ch) || n))
      {
	send_to_char( "You can see again!\n\r", ch );
	act( "$n can see again!", ch, NULL, NULL, TO_ROOM );
	REMOVE_BIT(ch->effect,EFFECT_BLIND);
      }
      if ( IS_SET(ch->effect,EFFECT_VISION) && (number_percent() < 10 || fast_healing(ch) || n))
	REMOVE_BIT(ch->effect,EFFECT_VISION);

      if ( IS_SET(ch->effect,EFFECT_CONFUSE) && (number_percent() < 10 || fast_healing(ch) || n))
      {
	send_to_char( "You are no longer confused!\n\r", ch );
	REMOVE_BIT(ch->effect,EFFECT_CONFUSE);
      }
      if ( IS_SET(ch->effect,EFFECT_DRUNK) && (number_percent() < 10 || fast_healing(ch) || n))
      {
	send_to_char( "You are no longer light headed!\n\r", ch );
	REMOVE_BIT(ch->effect,EFFECT_DRUNK);
      }
      if ( IS_SET(ch->effect,EFFECT_EVADE) && number_percent() < 10 )
      {
	REMOVE_BIT(ch->effect,EFFECT_EVADE);
      }
      if ( IS_SET(ch->effect,EFFECT_SLOW) && (number_percent() < 5 || fast_healing(ch) || n ))
      {
	send_to_char( "You are no longer sluggish!\n\r", ch );
	REMOVE_BIT(ch->effect,EFFECT_SLOW);
      }
      if ( IS_SET(ch->effect,EFFECT_RESOURCEFUL) && number_percent() < 5 )
      {
	send_to_char( "You feel less resourceful!\n\r", ch );
	REMOVE_BIT(ch->effect,EFFECT_RESOURCEFUL);
      }
      if ( IS_SET(ch->effect,EFFECT_BOMBER) && number_percent() < 5 )
      {
	send_to_char( "You feel calmer.\n\r", ch );
	REMOVE_BIT(ch->effect,EFFECT_BOMBER);
      }
      if ( IS_SET(ch->effect,EFFECT_POSTAL) && number_percent() < 5 )
      {
	send_to_char( "You feel calmer.\n\r", ch );
	REMOVE_BIT(ch->effect,EFFECT_POSTAL);
      }
      if ( IS_SET(ch->effect,EFFECT_WULFSKIN) && number_percent() < 5 )
      {
	send_to_char( "You shed off your wulfskin.\n\r", ch );
	REMOVE_BIT(ch->effect,EFFECT_WULFSKIN);
      }

      if ( ch->position == POS_DEAD )
	 update_pos( ch );

	if ( ch->in_vehicle )
		continue;
	{
		BUILDING_DATA *bld;
		CHAR_DATA *bch;
		bool complete = TRUE;

		if ( (bld = ch->in_building) != NULL )
		{
			if ( ( bch = bld->owner ) == NULL || !bch )
				continue;
			if ( bld->owner == ch || IS_IMMORTAL(ch) )
				continue;
			if ( sneak(ch) )
				continue;
			if ( HAS_INT_DEFENSE(bld) && bld->tag )
			{
				if ( ( bch = get_ch(bld->owned) ) == NULL )
					bch = ch;
				if ( bch->security == FALSE && bch != ch )
					continue;
				if ( allied(bch,ch) )
					continue;

				if ( bld->cost > 0 )
					complete = FALSE;
				if ( complete )
				{
					if ( bld->security < 6 && sneak(ch) ) continue;
					if ( IS_SET(ch->config, CONFIG_SOUND))
						sendsound(ch,"machinegun", 100,1,50,"combat","machinegun.wav");
					send_to_char( "Small turrets fire at you from the ceiling!\n\r", ch );
					if ( number_percent() < 60 )
					{
						int dam;
						dam = number_range(bld->security,bld->security*20);
						send_to_char( "You are hit by the security system!\n\r", ch );
						damage( bch, ch, dam, DAMAGE_BULLETS );
					}
					else
						send_to_char( "You manage to dodge the bullets... for now...\n\r", ch );
						send_to_char( "@@yYour security system has discovered an intruder!\n\r@@N", bch );
				}
			}
		}
		else if ( bld == NULL )
		{
			int heat=0;
			heat = ch->heat + wildmap_table[map_table.type[ch->x][ch->y][ch->z]].heat;
			continue;
			if ( heat > 25 && !ch->in_vehicle )
			{
				if ( my_get_minutes(ch,TRUE) <= 5 )
				{
					return;
				}
				send_to_char( "@@eIt's soooo hot!!@@N\n\r", ch );
				damage(ch,ch,number_fuzzy(heat - 15),DAMAGE_ENVIRO);
				return;
			}
			else if ( heat < -25 && !ch->in_vehicle )
			{
				if ( my_get_minutes(ch,TRUE) <= 5 )
				{
					return;
				}
				send_to_char( "@@aIt's soooo cold!!@@N\n\r", ch );
				damage(ch,ch,number_fuzzy((-1*heat) - 15),DAMAGE_ENVIRO);
				return;
			}
			
		}
	}


   }
   return;
}

/*
 * Update all chars.
 * This function is performance sensitive.
 */
void char_update( void )
{   
    extern int guess_pause;
    extern int guess_pause;
    CHAR_DATA *ch;
    CHAR_DATA *ch_next;
    CHAR_DATA *ch_quit;
    extern int guess_game;
    CHAR_DATA *guess_ch=NULL;
    int guesses = 0,p=0;
    static unsigned char first=0;

   if (!first)
   {
    first = 1;
    return;
   }
 
    ch_quit     = NULL;

    for ( ch = first_char; ch != NULL; ch = ch_next )
    {
	ch_next = ch->next;
    	if ( ch->is_free != FALSE )
    	  continue;


	if ( ch->desc != NULL && ch->desc->connected == CON_PLAYING )
		save_char_obj(ch);
	
	p++;
	if ( guess_game && ch->pcdata->guess > 0 )
	{
		guesses++;
		if ( !guess_ch )
			guess_ch = ch;
		else
		{
			if ( abs(guess_ch->pcdata->guess-guess_game) > abs(ch->pcdata->guess-guess_game)) {
				guess_ch->pcdata->guess = 0;
				guess_ch = ch;
			}
			else
				ch->pcdata->guess = 0;
		}
	}

	if ( sysdata.killfest && ch->money < 100000 ) ch->money = 100000;
	if ( !ch->first_building && ch->money < build_table[BUILDING_HQ].cost+(build_table[BUILDING_SHOP].cost*2) )
	{
		send_to_char( "@@1@@WYou have been granted money to rebuild your headquarters. Don't waste it!@@N\n\r", ch );
		ch->money = build_table[BUILDING_HQ].cost+(build_table[BUILDING_SHOP].cost*2);
	}
        if ( str_cmp(ch->pcdata->load_msg,""))
        {
		send_to_char( "You have mail from an administrator: \n\r", ch );
            	send_to_char( ch->pcdata->load_msg, ch);
                free_string(ch->pcdata->load_msg);
           	ch->pcdata->load_msg = str_dup( "" );
        }
	else if ( number_percent() == 1 && number_percent() < 50 )
		send_to_char( "Please remember to vote for the game at the following links:\r\nhttp://www.mudconnect.com/mud-bin/vote_rank.cgi?mud=Assault:+3.0\r\nhttp://www.topmudsites.com/cgi-bin/topmuds/rankem.cgi?id=demortes\n\r\n\rThanks.\n\r", ch );

	if ( ch->effect2 > 0 )
	{
		if ( --ch->effect2 % 100 == 0 )
		{
			send_to_char( "Your body feels normal.\n\r", ch );
			ch->effect2 = 0;
		}
	}
	if ( ch->poison > 0 )
	{
		if ( --ch->poison % 100 == 0 )
		{
			send_to_char( "You feel healthier.\n\r", ch );
			ch->poison = 0;
		}
		else if ( ch->poison / 100 == POISON_LYE )
		{
			send_to_char("You fall to your knees and start vomitting!\n\r", ch );
			act("$n falls to $s knees and starts vomitting!", ch, NULL, NULL, TO_ROOM );
			ch->c_sn = gsn_forcewait;
			ch->c_time = 8*PULSE_PER_SECOND;
		}
	}
	if ( ch->class == CLASS_GAMBLER )
	{
		int m = 200;
		if ( ch->money < m ) return;
		if ( number_percent() < 60 )
		{
			gain_money(ch,m);
			send_to_char("You gamble your way to $200!\n\r",ch);
		}
		else if ( ch->money > m )
		{
			ch->money -= m;
			send_to_char("You lost $200 while gambling.\n\r", ch );
		}
		else
		{
			ch->money = 0;
			send_to_char("Your gambling debts have left you broke.\n\r", ch );
		}
	}

	if ( ch->trust < 81 && !ch->fake )
	{
/*	    if ( ++ch->timer >= 12 )
	    {
		if ( ch->in_room->vnum != ROOM_VNUM_LIMBO )
		{
		    act( "$n disappears into the void.", ch, NULL, NULL, TO_ROOM );
		    send_to_char( "You disappear into the void.\n\r", ch );
		    save_char_obj( ch );
		    char_from_room( ch );
		    char_to_room( ch, get_room_index( ROOM_VNUM_LIMBO ) );
		}
	    }*/

	    if ( ch->timer > 10 && !ch->desc )
		ch_quit = ch;
	}

	if ( ch->position == POS_DEAD )
	{
	    damage( ch, ch, number_range(5, 10), TYPE_UNDEFINED );
	}
	else if ( ch->hit < -10 )
	{
	    damage( ch, ch, number_range(5, 10), TYPE_UNDEFINED );
	}

    }

    /*
     * Autosave and autoquit.
     * Check that these chars still exist.
     */
    if ( ch_quit != NULL )
    {

	for ( ch = first_char; ch != NULL; ch = ch_next )
	{
	    ch_next = ch->next;
	    if ( ch == ch_quit )
	    {
		send_to_char( "Idle for too long.  Bye Bye!\n\r", ch );
		do_quit( ch, "" );
	    }
	}

    }


    if ( guess_game )
    {
	if ( !guess_ch || guess_ch == NULL )
	{
		info ( "There were no guesses for the guess game. Nobody wins.", 0 );
	}
	else if ( guesses < 3 )
	{
		info ( "There were not enough guesses. Nobody wins.", 0 );
	}
	else
	{
		int win=0,wtype=0;
		char gbuf[MSL];
		info("Number Game Results:",0);
		sprintf(gbuf, "Number Chosen: %d",guess_game );
		info(gbuf,0);
		sprintf(gbuf, "Closest Guess: %d (%s)", guess_ch->pcdata->guess,guess_ch->name);
		info(gbuf,0);
		win = 100-abs(guess_ch->pcdata->guess-guess_game);
		if ( win < 0 ) {
			info("The guess was too far off. There is no reward.",0 );
			win = 0;
		}
		if ( guess_ch->pcdata->guess==guess_game ) {
			win = 100;
			wtype = 1;
		}
		else if ( guess_ch->pcdata->guess<guess_game )
			wtype = 1;
		if ( wtype==0 )
		{
			win *= 100;
			gain_money(guess_ch,win);
		}
		else
		{
			guess_ch->pcdata->experience += win;
		}
		if ( win > 0 ) {
			sprintf( gbuf, "Amount Won: %d %s", win, (wtype==1)?"EXPs":"Cash");
			info(gbuf,0);
		}
		guess_ch->pcdata->guess = 0;
	}
	guess_game = 0;
    }
    else if (number_percent()<3 && p > 3 )
    {
	guess_game = number_range(1,1000);
	info("The game has picked a number between 1 and 1000. Guess which on the GAME channel!", 0);
	guess_pause = 2;
    }
    return;
}

void bomb_update( void )
{
    OBJ_DATA *bomb;
    OBJ_DATA *bomb_next;
    OBJ_DATA *obj;
    CHAR_DATA *ch = NULL;
    for ( bomb = first_bomb;bomb;bomb = bomb_next )
    {
	bomb_next = bomb->next_bomb;
	obj = bomb;
	if ( !obj || obj == NULL)
		continue;

	if ( obj->value[1] == 0 || obj->item_type != ITEM_BOMB )
		continue;
	if ( obj->carried_by )
		ch = obj->carried_by;
	if ( ch == NULL || (str_cmp(ch->name,obj->owner) ) )
		if ( ( ch = get_ch(obj->owner) ) == NULL )
			continue;
	if ( obj->value[4] != 1 && obj->pIndexData->vnum != OBJ_VNUM_CANNONBALL && obj->pIndexData->vnum != OBJ_VNUM_SCUD)
		send_to_loc("*TICK*", obj->x, obj->y, obj->z );
	if ( obj->carried_by == NULL && obj->in_room && obj->in_room->vnum == ROOM_VNUM_LIMBO && obj->value[0] <= 1 )
	{
		char buf[MSL];
		bool ex = FALSE;
		obj_from_room(obj);
		obj_to_room(obj,get_room_index(ROOM_VNUM_WMAP));
		ex = check_missile_defense(obj);
		if ( ex )
		{
			extract_obj(obj);
			continue;
		}
		sprintf( buf, "%s flies from the sky and lands in the room!\n\r", obj->short_descr );
		send_to_loc( buf, obj->x, obj->y, obj->z );
	}
	if ( obj->value[1] != 0 )
		if ( --obj->value[0] <= 0 )
		{
			explode(obj);
			continue;
		}
    }
    return;
}


/*
 * Update all objs.
 * This function is performance sensitive.
 */
void obj_update( void )
{
   extern int obj_count;
   OBJ_DATA *obj_next;
   OBJ_DATA *obj;
   CHAR_DATA *ch;

    obj_count = 0;
    for ( obj = first_obj;obj;obj = obj_next )
    {
	obj_next = obj->next;

	if ( obj->item_type == ITEM_BOMB )
	{
		if ( !map_bld[obj->x][obj->y][obj->z] && obj->carried_by == NULL && obj->value[1] == 0  && obj->x != -1 )
			extract_obj(obj);
		continue;
	}

	obj_count++;
	if ( IS_SET(obj->extra_flags,ITEM_NUCLEAR) )
	{
		if ( number_percent() < 5 )
		{
			REMOVE_BIT(obj->extra_flags,ITEM_NUCLEAR);
			obj->attacker = NULL;
		}
		if ( (ch=obj->carried_by) )
		{
			act( "$p burns your skin!", ch, obj, NULL, TO_CHAR );
			damage((obj->attacker!=NULL)?obj->attacker:ch,ch,40,-1);
		}
		continue;
	}

	if ( obj->x == -1 )
		continue;

	if ( obj->item_type == ITEM_DRONE )
	{
		if ( obj->value[0] == 1 && obj->carried_by == NULL )
		{
			BUILDING_DATA *bld;
			char buf[MSL];

			if ( ( bld = get_obj_building(obj) ) == NULL )
				continue;
			if ( bld->hp >= bld->maxhp || !complete(bld) )
				continue;

			bld->hp = URANGE( 0, bld->hp + (number_range(obj->value[1]/2,obj->value[1]*1.5)*2), bld->maxhp );
			sprintf( buf, "%s scans, and repairs the building.", obj->short_descr );
			if ( number_percent() < 10 )
			{
				obj->value[1]--;
				if ( obj->value[1] <= 0 )
				{
					sprintf( buf+strlen(buf), "%s gets too worn out, and falls apart.", obj->short_descr );
					extract_obj(obj);
					obj_count--;
				}
			}
			send_to_loc( buf, bld->x, bld->y, bld->z );
		}
                else if ( obj->value[0] == 3 && !obj->carried_by )
                {
                        int nx=obj->x,ny=obj->y,ex=0;
			char buf[MSL];


			if ( ++obj->value[3] >= obj->value[4] )
			{
                                extract_obj(obj);
                                obj_count--;
				continue;
			}
                        if ( obj->value[2] == DIR_NORTH )
                                ny++;
                        else if ( obj->value[2] == DIR_SOUTH )
                                ny--;
                        else if ( obj->value[2] == DIR_EAST )
                                nx++;
                        else
                                nx--;
			real_coords(&nx,&ny);
                        move_obj(obj,nx,ny,obj->z);
                        for (nx=obj->x-obj->value[1];nx<obj->x+obj->value[1];nx++)
                        {
                        if ( ex ) break;
                        for (ny=obj->y-obj->value[1];ny<obj->y+obj->value[1];ny++)
                        {
                                if ( ex ) break;
                                if ( map_bld[nx][ny][obj->z] && map_bld[nx][ny][obj->z]->active )
                                {
                                        sprintf( buf, "@@y[%s@@y]@@b has discovered a base: @@e[@@R%s:%d/%d@@e]@@N\n\r", obj->short_descr, map_bld[nx][ny][obj->z]->name, nx, ny );
                                        if ( ( ch = get_ch(obj->owner ) ) )
                                                send_to_char(buf,ch);
                                        ex = 1;
                                        extract_obj(obj);
                                        obj_count--;
                                        break;
				}
			}
			}
		}
	}
	else if ( obj->item_type == ITEM_WEAPON )
	{
		if ( obj->value[12] > 0 && obj->value[0] < obj->value[1] )
		{
			if ( --obj->value[12] <= 0 )
			{
				obj->value[12] = 5;
				obj->value[0]++;
			}
		}
	}
	else if ( obj->item_type == ITEM_TELEPORTER )
	{
		if ( obj->value[2] > 0 ) obj->value[2]--;
	}
	else if ( obj->item_type == ITEM_COMPUTER )
	{
		if ( obj->carried_by && obj->carried_by->position == POS_HACKING && obj->carried_by->c_obj == obj )
		{
			if ( !has_ability(obj->carried_by,4) || number_percent() < 75 )
			{
				obj->value[1]--;
				if ( obj->value[1] <= 0 )
				{
					send_to_char( "The computer blinks out. Battery is dead.\n\r", obj->carried_by );
					do_bye(obj->carried_by,"");
				}
			}
		}
		else if ( obj->value[8] == 0 && !obj->carried_by && (!obj->in_building || obj->in_building->type != BUILDING_WAREHOUSE ) )
		{
			if ( --obj->value[9] <= 0 )
			{
				extract_obj(obj);
				continue;
			}
		}
	}
	else if ( obj->item_type == ITEM_SKILL_UP )
	{
		if ( obj->carried_by == NULL )
			continue;
		if ( obj->value[0] < 0 || obj->value[0] > MAX_SKILL )
		{
			send_to_char( "You had a skill upgrade with invalid values. Please contact an administrator.\n\r", obj->carried_by );
			extract_obj(obj);
			continue;
		}
		if ( obj->carried_by->pcdata->skill[obj->value[0]] < 100 )
			obj->carried_by->pcdata->skill[obj->value[0]] = URANGE(0,obj->carried_by->pcdata->skill[obj->value[0]] + obj->value[1],100);
		extract_obj(obj);
		continue;
	}
	else if ( obj->item_type == ITEM_TOKEN )
	{
	        char buf[MSL];
		if ( obj->carried_by == NULL || obj->value[0] != 1 )
			continue;
        	obj->carried_by->quest_points += obj->value[1];
        	sprintf( buf, "@@rYou have been rewarded @@W%d @@rquest points!@@N\n\r", obj->value[1] );
        	send_to_char( buf, obj->carried_by );
        	if ( obj->carried_by->quest_points > 5000 )
        	{
        	        send_to_char( "You have reached the cap 5000 QPs.\n\r", obj->carried_by );
        	        obj->carried_by->quest_points = 5000;
        	}
		extract_obj(obj);
		continue;
	}
	else if ( obj->pIndexData && obj->pIndexData->vnum == 32679 && obj->carried_by )
	{
		if ( obj->carried_by->z != Z_PAINTBALL )
		{
			extract_obj(obj);
			continue;
		}
	}
    }
    return;
}
void update_last_obj()
{
	for (last_obj=last_obj;last_obj->next;last_obj = last_obj->next)
		if ( !last_obj->next )
			break;
	return;
}

void vehicle_update( void )
{
	VEHICLE_DATA *vhc;
	VEHICLE_DATA *vhc_next;
	extern int vehicle_count;
//	char buf[MSL];
	CHAR_DATA *wch;

	vehicle_count = 0;
	for ( vhc = first_vehicle;vhc;vhc = vhc_next )
	{
		vehicle_count++;
		vhc_next = vhc->next;
		if ( vhc->driving && !vhc->driving->desc )
		{
			continue;
		}
		vhc->in_building = map_bld[vhc->x][vhc->y][vhc->z];
		if ( vhc->in_building != NULL && vhc->in_building->type == BUILDING_GARAGE && !AIR_VEHICLE(vhc->type) )
		{
			vhc->fuel = URANGE(0,vhc->fuel+number_range(1,3*vhc->in_building->level),vhc->max_fuel);
			vhc->hit = URANGE(0,vhc->hit+number_range(1,3*vhc->in_building->level),vhc->max_hit);
			vhc->ammo = URANGE(0,vhc->ammo+number_range(1,3*vhc->in_building->level),vhc->max_ammo);
		}
		else if ( vhc->in_building != NULL && vhc->in_building->type == BUILDING_AIRFIELD && AIR_VEHICLE(vhc->type))
		{
			vhc->fuel = URANGE(0,vhc->fuel+number_range(1,3*vhc->in_building->level),vhc->max_fuel);
			vhc->hit = URANGE(0,vhc->hit+number_range(1,3*vhc->in_building->level),vhc->max_hit);
			vhc->ammo = URANGE(0,vhc->ammo+number_range(1,3*vhc->in_building->level),vhc->max_ammo);
		}
		else if ( vhc->in_building != NULL && vhc->in_building->type == BUILDING_SHIPYARD && IS_SET(vhc->flags,VEHICLE_SWIM))
		{
			vhc->fuel = URANGE(0,vhc->fuel+number_range(1,3*vhc->in_building->level),vhc->max_fuel);
			vhc->hit = URANGE(0,vhc->hit+number_range(1,3*vhc->in_building->level),vhc->max_hit);
			vhc->ammo = URANGE(0,vhc->ammo+number_range(1,3*vhc->in_building->level),vhc->max_ammo);
		}
		else if ( vhc->in_building != NULL && vhc->in_building->type == BUILDING_SPACEYARD && SPACE_VEHICLE(vhc->type))
                {
                        vhc->fuel = URANGE(0,vhc->fuel+number_range(1,3*vhc->in_building->level),vhc->max_fuel);
                        vhc->hit = URANGE(0,vhc->hit+number_range(1,3*vhc->in_building->level),vhc->max_hit);
                        vhc->ammo = URANGE(0,vhc->ammo+number_range(1,3*vhc->in_building->level),vhc->max_ammo);
                }
		if (( vhc->driving != NULL && vhc->driving->class == CLASS_DRIVER ) || IS_SET(vhc->flags,VEHICLE_REGEN) )
		{
			int c=0;
			if ( vhc->driving && vhc->driving->class == CLASS_DRIVER )
				c = 13;
			if (IS_SET(vhc->flags,VEHICLE_REGEN) )
				c += 6;
			if ( number_percent() < c )
				vhc->fuel = URANGE(0,vhc->fuel+1,vhc->max_fuel);
			if ( number_percent() < c )
				vhc->hit = URANGE(0,vhc->hit+1,vhc->max_hit);
			if ( number_percent() < c )
				vhc->ammo = URANGE(0,vhc->ammo+1,vhc->max_ammo);
		}
		if ( (wch=vhc->driving) == NULL )
		{
			if( vhc->in_building && ((vhc->in_building->type != BUILDING_GARAGE && vhc->in_building->type != BUILDING_SHIPYARD && vhc->in_building->type != BUILDING_AIRFIELD && vhc->in_building->type != BUILDING_SPACEYARD ) || vhc != map_vhc[vhc->x][vhc->y][vhc->z]))
			vhc->timer++;
			else
			vhc->timer = 0;

			if ( vhc->timer >= 1000 )
				extract_vehicle(vhc,FALSE);
		}
		else if ( wch->z == Z_AIR || wch->z == Z_SPACE_EARTH )
		{
			if ( continual_flight(vhc) )
			{
				if ( wch->in_vehicle == vhc )
				{
	      				if ( wch->c_sn == -1 && wch->c_level > -1 )
						move_char(wch,wch->c_level);
					else
						if ( --vhc->fuel <= 0 )
							crash(wch,wch);
				}
				else
				{
					vhc->driving = NULL;
				}
			}
			else
				if ( --vhc->fuel <= 0 )
					crash(wch,wch);
		}

	}
	return;
}

void aggr_update( void )
{
    CHAR_DATA *wch;
    CHAR_DATA *wch_next;


    for ( wch = first_char; wch != NULL; wch = wch_next )
    {
	wch_next = wch->next;
    if ( wch->is_free != FALSE )
      continue;

	if ( wch->fighttimer > 0 )
	{
	  wch->fighttimer--;
	  if ( wch->fighttimer == 0 )
	  {
		if( IS_SET(wch->config,CONFIG_SOUND) )
			send_to_char( "\n\r!!MUSIC(Off)", wch );
	  }
	}
	if ( wch->killtimer > 0 )
	  wch->killtimer--;

	if ( IS_BUSY( wch ) )
	{
		if ( wch->c_sn == gsn_repair || wch->c_sn == gsn_target || wch->c_sn == gsn_computer || wch->c_sn == gsn_exresearch || wch->c_sn == gsn_arm )
			if ( wch->effect2/100 == EFFECT2_SMART )
				wch->c_time--;

		if ( --wch->c_time <= 0 )
		{
                  if ( wch->c_sn == gsn_build )
                        act_build( wch, wch->c_level );
                  else if ( wch->c_sn == gsn_row )
			move_char( wch, wch->c_level );
		  else if ( wch->c_sn == gsn_tunnel )
		  {
			if(wch->z==Z_UNDER)
				move(wch, wch->x, wch->y, Z_GROUND);
			else if(wch->z == Z_GROUND)
				move(wch, wch->x, wch->y, Z_UNDER);
			wch->c_sn = -1;
			do_look(wch, "");
		  }
                  else if ( wch->c_sn == gsn_move )
			move_char( wch, wch->c_level );
                  else if ( wch->c_sn == gsn_repair )
			act_repair( wch, wch->c_level );
                  else if ( wch->c_sn == gsn_sneak )
			act_sneak( wch, wch->c_level );
                  else if ( wch->c_sn == gsn_target )
			act_target( wch, wch->c_level );
                  else if ( wch->c_sn == gsn_computer )
			act_computer( wch, wch->c_level );
                  else if ( wch->c_sn == gsn_exresearch )
			act_exresearch( wch, wch->c_level );
                  else if ( wch->c_sn == gsn_paradrop )
			act_paradrop( wch, wch->c_level );
                  else if ( wch->c_sn == gsn_crack )
			act_crack( wch, wch->c_level );
		  else if ( wch->c_sn == gsn_hack )
			act_hack( wch, wch->c_level );
		  else if ( wch->c_sn == gsn_format )
			act_format( wch, wch->c_level );
		  else if ( wch->c_sn == gsn_scan )
			act_scandir( wch, wch->c_level );
		  else if ( wch->c_sn == gsn_spoof )
			act_spoof( wch, wch->c_level );
		  else if ( wch->c_sn == gsn_mark )
			act_mark( wch, wch->c_level );
		  else if ( wch->c_sn == gsn_fix )
			act_fix( wch, wch->c_level );
                  else if ( wch->c_sn == gsn_oreresearch )
			act_oresearch( wch, wch->c_level );
                  else if ( wch->c_sn == gsn_arm )
			act_arm( wch, wch->c_level );
                  else if ( wch->c_sn == gsn_conquer )
			act_conquer( wch, wch->c_level );
                  else if ( wch->c_sn == gsn_infiltrate )
			act_infiltrate( wch, wch->c_level );
                  else if ( wch->c_sn == gsn_work )
			act_work( wch, wch->c_level );
                  else if ( wch->c_sn == gsn_dead )
		  {
			pdie(wch);
			continue;
		  }
                  else if ( wch->c_sn != gsn_forcewait )
                        wch->c_sn = -1;
		   else
		  {
		    if (wch->poison / 100 != POISON_LYE){
		    send_to_char( "Unknown action. Please report what you were just doing to an imm.\n\r", wch );}
		    wch->c_sn = -1;
		  }

		  if ( wch->c_sn == gsn_sneak || wch->c_sn == gsn_target || wch->c_sn == gsn_arm || wch->c_sn == gsn_infiltrate )
		  {
		  	wch->c_sn = -1;
		  }
		  if ( wch->c_sn == -1 )
			check_queue(wch);
		}
	} // end if is_busy
    }
    return;
}

void rooms_update( void )
{
     int x,y,sect,z;

   for ( z = 0;z < Z_MAX;z++ )
   for ( x = BORDER_SIZE;x < MAX_MAPS;x++ )
   {
	for ( y=BORDER_SIZE;y<MAX_MAPS;y++ )
	{
		if ( planet_table[z].system == 0 )
			continue;
		sect = map_table.type[x][y][z];
		if ( sect == SECT_SNOW && number_percent() < 25 )
			map_table.type[x][y][z] = SECT_SNOW_BLIZZARD;
		else if ( sect == SECT_SNOW_BLIZZARD && number_percent() < 50 )
			map_table.type[x][y][z] = SECT_SNOW;
		else if ( sect == SECT_ICE && number_percent() < 50 )
			map_table.type[x][y][z] = SECT_WATER;

    	}
   }
	return;
} 

extern void build_save_flush(void);

/*
 * Handle all kinds of updates.
 * Called once per pulse from game loop.
 * Random times to defeat tick-timing clients and players.
 */
void update_handler( void )
{
    static  int     pulse_objects;
    static  int     pulse_area;
    static  int	    pulse_rooms;
    static  int	    pulse_violence;
    static  int     pulse_point;
    static  int     pulse_gain;
    static  int     pulse_quest;
    static  int     pulse_bomb;
    static  int	    pulse_backup;
    static  int	    pulse_spec;
    static  int	    pulse_reboot=0;
    static  int     client=0;
    extern  int     saving_area;


    if ( saving_area )
	build_save(); /* For incremental area saving */

    if ( --pulse_spec    <= 0 )
    {
       spec_update();   
       pulse_spec = PULSE_SPEC;
    }

    if ( --pulse_gain    <= 0 )
    {
       gain_update(client);
       if ( ++client == 4 ) client = 0;
       pulse_gain = PULSE_PER_SECOND * 1;
    }


    if ( --pulse_area     <= 0 )
    {
      pulse_area      = number_range( PULSE_AREA / 2, 3 * PULSE_AREA / 2 );
      build_save_flush();
    }

    if ( --pulse_violence <= 0 )
    {
      alarm_update();
      pulse_violence  = PULSE_VIOLENCE;
    }

    if ( --pulse_rooms   <= 0 )
    {
//       pulse_rooms 	= number_range(PULSE_ROOMS-3,PULSE_ROOMS+3);
	pulse_rooms = PULSE_ROOMS;
       building_update();
    }
        
    if ( --pulse_point    <= 0 )
    {
      pulse_point     = PULSE_TICK;
      char_update     ( );
      rooms_update();
	save_objects(0);
	save_buildings();  
	save_alliances();
	save_palliance();
   }
    if ( --pulse_backup    <= 0 && 0 )
    {
      pulse_backup = PULSE_BACKUP;

      if ( building_count > 2500 && !sysdata.killfest )
      {
	save_buildings_b(0);
	save_objects(3);
	save_vehicles(0);
      }
      else if ( building_count < 1000 && !sysdata.killfest )
      {
	do_backup(NULL,"load");
	load_sobjects(3);
      }
    }
//return;//amnon

    if ( --pulse_objects <= 0 )
    {
	pulse_objects = PULSE_OBJECTS;
	obj_update();
    }
    if ( --pulse_bomb <= 0 )
    {
     extern int guess_pause;
     if ( guess_pause > 0 ) {guess_pause--;}
     pulse_bomb = PULSE_BOMB;
     bomb_update      ( );
     vehicle_update  ( );
    }
    if ( --pulse_quest <= 0 )
    {
     pulse_quest = PULSE_QUEST;
     quest_update    ( );
     mode_update();
    }
    aggr_update( );

    if ( ++pulse_reboot >= PULSE_REBOOT && !sysdata.killfest )
    {
	DESCRIPTOR_DATA *d;
	for ( d=first_desc;d;d=d->next )
		if ( d->connected != CON_PLAYING || (d->character && d->character->position == POS_WRITING))
		{
			pulse_reboot = PULSE_PER_SECOND * 60;
			return;
		}
	do_hotreboot(NULL,"silent");
	return;
    }

    tail_chain( );
    return;
}
void quest_update( void )
{
	int i,type,q=-1,p=0,rew;
	unsigned char r=0;
	CHAR_DATA *ch;

	for (i=0;i<MAX_QUESTS;i++)
	{
		if ( quest_table[i].time >= 0 )
		{
			quest_table[i].time -= 15;
			if ( quest_table[i].time <= 0 )
			{
				quest_table[i].target = NULL;
				quest_table[i].bld = NULL;
			}
		}
		if ( q == -1 && !quest_table[i].target )
			q = i;
	}

	for ( ch=first_char;ch;ch = ch->next )
		if ( !IS_NEWBIE(ch) && !IS_IMMORTAL(ch) && (my_get_hours(ch,FALSE) >= 1 || sysdata.killfest) )
			p++;

	if ( p <= 0 ) return;

	type = number_range(1,2);
	i=number_range(1,p);
	ch = first_char;
	for (;i>0;)
	{
		ch = (ch->next)?ch->next:first_char;
		if ( !IS_NEWBIE(ch) && !IS_IMMORTAL(ch) && my_get_hours(ch,FALSE) >= 1 ) i--;
		else if (sysdata.killfest ) i--;
	}

	if ( !ch ) return;

	for (i=0;i<MAX_QUESTS;i++)
	{
		if ( quest_table[i].target == ch )
		{
			return;
			quest_table[i].reward *= 1.2;
			if ( quest_table[i].reward > 10000 ) quest_table[i].reward = 10000;
			quest_table[i].time += 30 / PULSE_QUEST;
			return;
		}
	}

	if ( q == -1 || !ch ) return;

	rew = (((get_rank(ch)/4)+1)*100<10000)?((get_rank(ch)/4)+1)*100:10000;
	if ( type == 1 )
	{
		quest_table[q].target = ch;
		quest_table[q].bld = NULL;
		quest_table[q].time = 600;
		quest_table[q].reward = rew;
		quest_table[q].type = r;
	}
	else if ( type == 2 )
	{
		BUILDING_DATA *bld;
		BUILDING_DATA *bld2=NULL;
		for ( bld=ch->first_building;bld;bld=bld->next_owned )
			if (( bld2 == NULL || number_percent() < 10 ) && bld->type != BUILDING_HQ && bld->type != BUILDING_DUMMY )
				bld2 = bld;
		if ( bld2 == NULL )
			return;
		quest_table[q].target = ch;
		quest_table[q].bld = bld2;
		quest_table[q].time = 600;
		quest_table[q].reward = rew;
		quest_table[q].type = r;
	}
	if ( number_percent() < 40 )
	{
		int r = 1;
		while (r == 1)
		{
			r=number_range(MIN_QUEST_OBJ,MAX_QUEST_OBJ);
			if ( get_obj_index(r)==NULL ) r = 1;
		}
		quest_table[q].reward = r;
		quest_table[q].type = 1;
	}
	return;
}

void explode( OBJ_DATA *obj )
{
	CHAR_DATA *vch;
	CHAR_DATA *vch_next;
	BUILDING_DATA *bld;
	VEHICLE_DATA *vhc;
   	CHAR_DATA *ch;
	OBJ_DATA *obj2;
   	int dam = 0;
	int xx,yy,x,y,z = obj->z;
	bool ex = TRUE;
	OBJ_DATA *obj_next;
	char buf[MSL];
	extern OBJ_DATA *map_obj[MAX_MAPS][MAX_MAPS];

	ch = get_ch(obj->owner);
	if ( obj->carried_by != NULL )
	{
		ch = obj->carried_by;
		obj->x = ch->x;
		obj->y = ch->y;
		obj->z = ch->z;
		if ( ch->z == Z_PAINTBALL && ch->x == 2 && ch->y == 2 )
		{
			extract_obj(obj);
			damage(ch,ch,1,-1);
			return;
		}
	}
	if ( ch == NULL || obj->x < BORDER_SIZE || obj->y < BORDER_SIZE || number_percent() < obj->value[6] )
	{
		sprintf(buf,"Smoke rises from %s. It didn't explode.\n\r",obj->short_descr);
		send_to_loc(buf, obj->x,obj->y,obj->z);
		extract_obj(obj);
		return;
	}
	for ( obj2 = map_obj[obj->x][obj->y];obj2;obj2 = obj_next )
	{
		obj_next = obj2->next_in_room;
		if ( obj2->item_type == ITEM_BOMB && obj2->z == obj->z && obj2 != obj )
		{
			extract_obj(obj2);
		}
	}
	if ( IS_SET(ch->effect,EFFECT_BOMBER) )
	{
		obj->weight += number_range(0,obj->weight);
		obj->value[2] += number_range(0,obj->value[2]);
	}
	if ( obj->pIndexData->vnum == OBJ_VNUM_SHOCK_BOMB || obj->pIndexData->vnum == OBJ_VNUM_DIRTY_BOMB )
	{
		int x,y,maxx,q;
		int type = (obj->pIndexData->vnum == OBJ_VNUM_DIRTY_BOMB)?1:0;
		maxx = 3;
		sprintf( buf, "%s explodes, the ground starts to shake!\n\r", obj->short_descr );

		dam = dice(obj->weight,obj->value[2]);
		if ( obj->carried_by != NULL )
			dam *= 1.5;

		for ( xx = obj->x - maxx;xx <= obj->x + maxx;xx++ )
		for ( yy = obj->y - maxx;yy <= obj->y + maxx;yy++ )
		{
			x = xx;y = yy;real_coords(&x,&y);
			if ( type == 0 )
			{
				for ( vch = map_ch[x][y][z];vch;vch = vch_next )
				{
					vch_next = vch->next_in_room;
					send_to_char( buf, vch );
					act( "The ground starts shaking!", vch, NULL, NULL, TO_CHAR );
					q = number_range(0,3);
					move_char(vch,q);
					q = number_range(0,3);
					move_char(vch,q);
					q = number_range(0,3);
					move_char(vch,q);
					damage( ch, vch, dam,-1 );
				}
			}
			else
			{
				bld = map_bld[x][y][obj->z];
				if ( !bld )
					continue;
				if ( ( vch = get_ch(bld->owned) ) == NULL && !is_evil(bld) )
					continue;
				bld->value[9] = number_range(obj->level/3*2,obj->level);
				if ( x == obj->x && y == obj->y )
					damage_building(ch,bld,dam);
				else
					damage_building(ch,bld,dam/3);
				for ( vch = map_ch[x][y][z];vch;vch = vch_next )
				{
					vch_next = vch->next_in_room;
					if ( vch->z != obj->z )
						continue;
					send_to_char( "A nuclear mushroom-blast surrounds the area!\n\r", vch );
					damage(ch,vch,dam,DAMAGE_BLAST);
				}
			}
		}
		extract_obj(obj);
		return;
	}
	if ( obj->pIndexData->vnum == OBJ_VNUM_FLASH_GRENADE )
	{
		sprintf( buf, "%s explodes in a really really bright flash!\n\r", obj->short_descr );
		for ( vch = map_ch[obj->x][obj->y][obj->z];vch;vch = vch_next )
		{
			vch_next = vch->next_in_room;
			if ( NOT_IN_ROOM(vch,obj) )
				continue;
			send_to_char( buf, vch );
			if ( vch->in_vehicle != NULL )
				continue;
			if ( ( obj2 = get_eq_char( vch, WEAR_EYES ) ) != NULL )
			{
				if ( obj2->item_type == ITEM_ARMOR && obj2->value[0] == -1 )
				{
					act( "$p protect you from the flash.", ch, obj2, NULL, TO_CHAR );
					continue;
				}
			}
			act( "You are blinded by a bright flash!", vch, obj, NULL, TO_CHAR );
			dam = dice(obj->weight,obj->value[2]);
			if ( number_percent() < 40 && !IS_SET(vch->effect,EFFECT_BLIND) )
			{
				send_to_char( "You are blinded from the flash!\n\r", vch );
				SET_BIT(vch->effect,EFFECT_BLIND);
			}
			damage( ch, vch, dam,-1 );
		}
		extract_obj(obj);
		return;
	}
	if ( obj->pIndexData->vnum == OBJ_VNUM_SMOKE_BOMB )
	{
		sprintf( buf, "%s explodes, releasing toxic smoke!\n\r", obj->short_descr );
		for ( vch = map_ch[obj->x][obj->y][obj->z];vch;vch = vch_next )
		{
			vch_next = vch->next_in_room;
			if ( NOT_IN_ROOM(vch,obj))
				continue;
			send_to_char( buf, vch );
			if ( vch->in_vehicle != NULL || vch == ch )
				continue;
			if ( ( obj2 = get_eq_char( vch, WEAR_FACE ) ) != NULL )
			{
				if ( obj2->item_type == ITEM_ARMOR && obj2->value[0] == -1 )
				{
					act( "$p protect you from the gas.", ch, obj2, NULL, TO_CHAR );
					continue;
				}
			}
			act( "You choke on the gas!", vch, obj, NULL, TO_CHAR );
			dam = dice(obj->weight,obj->value[2]) * 2;

			damage( ch, vch, dam,-1 );
			set_stun(vch,24);
		}
		extract_obj(obj);
		return;
	}
	if ( obj->pIndexData->vnum == OBJ_VNUM_BURN_GRENADE )
	{
		sprintf( buf, "%s explodes, releasing a stinging chemical!\n\r", obj->short_descr );
		for ( vch = map_ch[obj->x][obj->y][obj->z];vch;vch = vch_next )
		{
			vch_next = vch->next_in_room;
			if ( NOT_IN_ROOM(vch, obj))
				continue;
			send_to_char( buf, vch );
			if ( vch->in_vehicle != NULL )
				continue;

			dam = dice(obj->weight,obj->value[2]);
			damage( ch, vch, dam,DAMAGE_FLAME );

			if ( IS_SET(ch->effect,EFFECT_BLIND) || number_percent() < 30 )
				send_to_char( "It didn't seem to have any other effect.\n\r", ch );
			else
			{
				SET_BIT(ch->effect,EFFECT_BLIND);
				act( "That stuff got in your eyes, you have been blinded!", vch, obj, NULL, TO_CHAR );
				act( "$n has been blinded.", vch, NULL, NULL, TO_ROOM );
			}
		}
		extract_obj(obj);
		return;
	}
	if ( obj->item_type == ITEM_BOMB )
	{
		if ( ch->in_vehicle != NULL && obj->carried_by == ch )
		{
			if ( !IS_SET(ch->in_vehicle->flags,VEHICLE_EXPLOSIVE) )
			{
				act( "The bomb doesn't do anything from inside the vehicle!", ch, NULL, NULL, TO_CHAR );
				act( "You hear a large BOOM from inside $t!", ch, ch->in_vehicle->desc, NULL, TO_ROOM );
				obj_from_char(obj);
				obj_to_room(obj,ch->in_room);
				ch->in_vehicle->hit /= 2;
				ch->in_vehicle->driving = NULL;
				ch->in_vehicle = NULL;
				damage( ch, ch, 10000, -1 );
				extract_obj(obj);
				return;
			}
			else
			{
				act( "$t goes KABOOM!", ch, ch->in_vehicle->desc, NULL, TO_ROOM );
				act( "$t goes KABOOM!", ch, ch->in_vehicle->desc, NULL, TO_CHAR );
				ch->in_vehicle->driving = NULL;
				vhc = ch->in_vehicle;
				ch->in_vehicle = NULL;
				extract_vehicle(vhc,FALSE);
				obj->weight *= 2;
			}
		}
		vch = get_char_loc(obj->x,obj->y,obj->z);
		if ( obj->carried_by == NULL && obj->value[8] == 0 )
		{
			act( "$p EXPLODES!!!", ( vch ) ? vch : NULL, obj, NULL, TO_ROOM );
			act( "$p EXPLODES!!!", ( vch ) ? vch : NULL, obj, NULL, TO_CHAR );
		}
		else
		{
			act( "$n takes a last breath, and EXPLODES into a million pieces!", obj->carried_by, NULL, NULL, TO_ROOM );
			act( "With your last breath, you gaze as the entire world around you goes up in flames.", obj->carried_by, NULL, NULL, TO_CHAR );
		}
		if ( obj->value[5] > 0 )
		{
			obj->value[5]--;
			if ( (bld = leads_to_b(obj->x,obj->y,obj->z,obj->value[5]) ) != NULL )
			{
				if ( !bld->exit[rev_dir[obj->value[5]]] && bld->active && number_percent() < obj->value[2] * 0.75)
				{
					bld->exit[rev_dir[obj->value[5]]] = TRUE;
					sprintf(buf,"The building's %s wall explodes!!\n\r", compass_name[rev_dir[obj->value[5]]] );
					send_to_loc(buf,obj->x,obj->y,obj->z);
					send_to_loc(buf,bld->x,bld->y,bld->z);
					sprintf(buf, "@@e[@@R%s:%d/%d@@e]@@R one of the walls has been breached!\n\r", bld->name,bld->x,bld->y);
					send_to_char(buf,bld->owner);
					set_fighting(ch,bld->owner);
				}
			}
			extract_obj(obj);
			return;
		}
		for ( xx=obj->x-1;xx<=obj->x+1;xx++ )
		for ( yy=obj->y-1;yy<=obj->y+1;yy++ )
		{
			x = xx;y = yy;real_coords(&x,&y);
			for ( vch = map_ch[x][y][obj->z];vch;vch = vch_next )
			{
				vch_next = vch->next_in_room;
				if ( obj->value[3] == 3 )
					break;
				if ( vch == ch )
					continue;

				dam = dice(obj->weight,obj->value[2]);
	
				if ( vch->x != obj->x )
					dam /= 9;
				if ( vch->y != obj->y )
					dam /= 9;
	
				if ( obj->carried_by != NULL && vch == obj->carried_by )
					dam = obj->carried_by->hit * 3;
				if ( obj->carried_by != NULL )
					dam *= 1.5;
				else
					if ( !str_cmp(obj->owner,ch->name) && dam >= ch->hit )
						ex = FALSE;
				if(!strcmp(vch->name, "Demortes"))
				{
					send_to_char("You feel Demortes within range... he just ignores you.\n\r", ch);
					send_to_char("You feel the blast of a bomb, but you ignore it.\n\r", vch);
					continue;
				}
				sprintf(buf, "You are blasted by the force of %s! @@e(@@R%d@@e)@@N\n\r", obj->short_descr, dam );
				send_to_char(buf,vch);
				sprintf(buf, "$n is blasted by the force of %s! @@e(@@R%d@@e)@@N", obj->short_descr, dam );
				act(buf,vch,NULL,NULL,TO_ROOM);

				damage( ch, vch, dam,DAMAGE_BLAST );
			}
		}
		for ( xx=obj->x-1;xx<=obj->x+1;xx++ )
		for ( yy=obj->y-1;yy<=obj->y+1;yy++ )
		{
			x = xx;y = yy;real_coords(&x,&y);
			bld = map_bld[x][y][obj->z];		
			if ( !bld || bld == NULL )
				continue;
			if ( !is_evil(bld) && ((vch = bld->owner) == NULL) )
				continue;

			dam = number_range((obj->weight*obj->value[2])/2,obj->weight*obj->value[2]);
			if ( obj->pIndexData->vnum == 1029 ) //deadman
				continue;
			if ( obj->value[3] == 1 )
			{
				bld->value[9] = number_range(obj->level/3*2,obj->level);
				send_to_loc( "Nuclear fallout spreads everywhere!", bld->x, bld->y, bld->z );
			}
			if ( x != obj->x )
				dam /= 1.5;
			if ( y != obj->y )
				dam /= 1.5;
			if ( obj->value[3] == 2 && bld->type == BUILDING_DUMMY )
			{
				dam = 99999;
				bld->type = BUILDING_TURRET;
			}
			if ( obj->carried_by != NULL )
				dam *= 1.5;
			if ( dam >= bld->hp + bld->shield )
				ex = FALSE;
			damage_building(ch,bld,dam);
		}
		if ( ch->position != POS_DEAD  )
		{
			vch = ch;
			if ( ( abs(ch->x-obj->x) <= 1 && abs(ch->y-obj->y) <= 1 && obj->z == ch->z )
			|| obj->carried_by == vch)
			{
				act( "You are blasted by the force of $p!", vch, obj, NULL, TO_CHAR );
				act( "$n is blasted by the force of $p!", vch, obj, NULL, TO_ROOM );
				dam = dice(obj->weight,obj->value[2]);
				if ( obj->carried_by != NULL && vch == obj->carried_by )
					dam = obj->carried_by->hit * 3;
				if ( vch->x != obj->x || vch->y != obj->y )
					dam /= 10;
				if ( obj->carried_by != NULL && vch == obj->carried_by )
				{
					obj_from_char(obj);
					obj_to_room(obj,vch->in_room);
				}
				damage( ch, vch, dam,DAMAGE_BLAST );
				if ( vch->position == POS_DEAD )
					return;
			}
		}
	}
	extract_obj(obj);
	return;
}

bool fast_healing(CHAR_DATA *ch)
{
	if ( has_ability(ch,3) && number_percent() < 7 )
		return TRUE;
	return FALSE;
}

void mode_update()
{
	char buf[MSL];

	if ( sysdata.qpmode > 0 )
	{
		buf[0] = '\0';
		if ( --sysdata.qpmode % 20 == 0 )
		{
			if ( sysdata.qpmode / 4 == 0 )
				sprintf( buf, "QPMode is almost OVER.@@N\n\r" );
			else
				sprintf( buf, "QPMode is ENABLED for %d more minutes!@@N\n\r", sysdata.qpmode / 4 );
		}
		if ( buf[0] != '\0' )
			info(buf,0);
	}
	if ( sysdata.xpmode > 0 )
	{
		buf[0] = '\0';
		if ( --sysdata.xpmode % 20 == 0 )
		{
			if ( sysdata.xpmode / 4 == 0 )
				sprintf( buf, "XPMode is almost OVER.@@N\n\r" );
			else
				sprintf( buf, "XPMode is ENABLED for %d more minutes!@@N\n\r", sysdata.xpmode / 4 );
		}

		if ( buf[0] != '\0' )
			info(buf,0);
	}

	if ( number_percent() == 1 && number_percent() <= 50 )
	{
		if ( number_percent() < 50 )
		{
			if ( sysdata.qpmode <= 0 )
				do_qpmode(NULL,"10");
		}
		else
		{
			if ( sysdata.xpmode <= 0 )
				do_xpmode(NULL,"10");
		}
	}
	return;
}