area/
build/testing/
log/
player/
player/backup/
/***************************************************************************
 *  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.                                                  *
 ***************************************************************************/
#include <glib.h>

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <merc.h>
#include <tables.h>
#include <interp.h>
#include <recycle.h>
#include <power.h>



/*
 * Local functions.
 */
int	hit_gain	args( ( CHAR_DATA *ch ) );
int	mana_gain	args( ( CHAR_DATA *ch ) );
int	move_gain	args( ( CHAR_DATA *ch ) );
void	mobile_update	args( ( void ) );
void    pet_update args( ( CHAR_DATA *ch ));
void	weather_update	args( ( void ) );
void	char_update	args( ( void ) );
void	obj_update	args( ( void ) );
void	aggr_update	args( ( void ) );
void	quest_update	args( ( void ) );
void    room_update args( ( void ) );
void    caern_update args( ( void ) );
void	update_damcap		args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
extern int     count_snoopers	args((DESCRIPTOR_DATA *ch));
/*
void    ww_update       args( ( void ) );
*/
extern void call_guards args((CHAR_DATA *ch));


/*
 * Mob autonomous action.
 * This function takes 25% to 35% of ALL Merc cpu time.
 * -- Furey
 */
void mobile_update( void )
{
	CHAR_DATA *ch;
	CHAR_DATA *ch_next;
	EXIT_DATA *pexit;
	int door;

	/* Examine all mobs. */

	for ( ch = char_list; ch != NULL; ch = ch_next )
	{
		ch_next = ch->next;

		if ( ch->in_room == NULL ) 
			continue;
		/*
		   if ( ch->hunting != NULL && ch->hunting != '\0' && 
		   strlen(ch->hunting) > 1 )
		   {
		   check_hunt( ch );
		   continue;
		   }
		 */
		/*
		 * Check triggers only if mobile still in default position
		 */
		if ( IS_NPC(ch) )
		{
			//If they are in the city.. have a chance to call the guards!
			if (ch->in_room->sector_type == SECT_CITY) {
				call_guards(ch);
			}
			if ( ch->fighting && ch->pk_timer == 0 )
			{
				if (IS_SET(ch->mob_fight,FIGHT_RANDOM))
				{
					act("$n relaxes from $s fighting stance.",ch,NULL,NULL,TO_ROOM);
					set_random_stance(ch);
				}
				if (IS_SET(ch->mob_fight,FIGHT_MASTER))
				{
					act("$n relaxes from $s fighting stance.",ch,NULL,NULL,TO_ROOM);
					set_master_stance(ch);
				}
			}
			/* Delay */
			if ( HAS_TRIGGER( ch, TRIG_DELAY) 
					&&   ch->mprog_delay > 0 )
			{
				if ( --ch->mprog_delay <= 0 )
				{
					mp_percent_trigger( ch, NULL, NULL, NULL, TRIG_DELAY );
					continue;
				}
			} 
			if ( HAS_TRIGGER( ch, TRIG_RANDOM) )
			{
				if( mp_percent_trigger( ch, NULL, NULL, NULL, TRIG_RANDOM ) )
					continue;
			}

		}

		if ( !IS_NPC(ch) )
		{
			if (ch->pcdata->condition[COND_DRUNK] > 10 && number_range(1,10) == 1)
			{
				send_to_char("You hiccup loudly.\n\r",ch);
				act("$n hiccups.",ch,NULL,NULL,TO_ROOM);
			}
			if (ch->pcdata->stage[0] > 0 || ch->pcdata->stage[2] > 0)
			{
				CHAR_DATA *vch;
				if (ch->pcdata->stage[1] > 0 && ch->pcdata->stage[2] >= 225)
				{
					ch->pcdata->stage[2] += 1;
					if ( ( vch = ch->pcdata->partner ) != NULL &&
							!IS_NPC(vch) && vch->pcdata->partner == ch &&
							((vch->pcdata->stage[2] >= 200 && vch->sex == SEX_FEMALE) ||
							 (ch->pcdata->stage[2] >= 200 && ch->sex == SEX_FEMALE)))
					{
						if (ch->in_room != vch->in_room) continue;
						if (vch->pcdata->stage[2] >= 225 &&
								ch->pcdata->stage[2] >= 225 &&
								vch->pcdata->stage[2] < 240 &&
								ch->pcdata->stage[2] < 240)
						{
							ch->pcdata->stage[2] = 240;
							vch->pcdata->stage[2] = 240;
						}
						if (ch->sex == SEX_MALE && vch->pcdata->stage[2] >= 240)
						{
							act("You thrust deeply between $N's warm, damp thighs.",ch,NULL,vch,TO_CHAR);
							act("$n thrusts deeply between your warm, damp thighs.",ch,NULL,vch,TO_VICT);
							act("$n thrusts deeply between $N's warm, damp thighs.",ch,NULL,vch,TO_NOTVICT);
							if (vch->pcdata->stage[2] > ch->pcdata->stage[2])
								ch->pcdata->stage[2] = vch->pcdata->stage[2];
						}
						else if (ch->sex == SEX_FEMALE && vch->pcdata->stage[2] >= 240)
						{
							act("You squeeze your legs tightly around $N, moaning loudly.",ch,NULL,vch,TO_CHAR);
							act("$n squeezes $s legs tightly around you, moaning loudly.",ch,NULL,vch,TO_VICT);
							act("$n squeezes $s legs tightly around $N, moaning loudly.",ch,NULL,vch,TO_NOTVICT);
							if (vch->pcdata->stage[2] > ch->pcdata->stage[2])
								ch->pcdata->stage[2] = vch->pcdata->stage[2];
						}
					}
					if (ch->pcdata->stage[2] >= 250)
					{
						if ( ( vch = ch->pcdata->partner ) != NULL &&
								!IS_NPC(vch) && vch->pcdata->partner == ch &&
								ch->in_room == vch->in_room)
						{
							vch->pcdata->stage[2] = 250;
							if (ch->sex == SEX_MALE)
							{
								stage_update(ch,vch,2);
								stage_update(vch,ch,2);
							}
							else
							{
								stage_update(vch,ch,2);
								stage_update(ch,vch,2);
							}
							ch->pcdata->stage[0] = 0;
							vch->pcdata->stage[0] = 0;
							if (!IS_EXTRA(ch, EXTRA_EXP))
							{
								send_to_char("Congratulations on achieving a simultanious orgasm!  Recieve 10000 exp!\n\r",ch);
								SET_BIT(ch->extra, EXTRA_EXP);
								ch->exp += 10000;
							}
							if (!IS_EXTRA(vch, EXTRA_EXP))
							{
								send_to_char("Congratulations on achieving a simultanious orgasm!  Recieve 10000 exp!\n\r",vch);
								SET_BIT(vch->extra, EXTRA_EXP);
								vch->exp += 10000;
							}
						}
					}
				}
				else
				{
					if (ch->pcdata->stage[0] > 0 && ch->pcdata->stage[2] < 1 &&
							ch->position != POS_RESTING) 
					{
						if (ch->pcdata->stage[0] > 1)
							ch->pcdata->stage[0] -= 1;
						else
							ch->pcdata->stage[0] = 0;
					}
					else if (ch->pcdata->stage[2]>0 && ch->pcdata->stage[0] < 1)
					{
						if (ch->pcdata->stage[2] > 10)
							ch->pcdata->stage[2] -= 10;
						else
							ch->pcdata->stage[2] = 0;
						if (ch->sex == SEX_MALE && ch->pcdata->stage[2] == 0)
							send_to_char("You feel fully recovered.\n\r",ch);
					}
				}
			}
			if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE) && IS_HERO(ch))
			{
				if ( ch->position == POS_FIGHTING && ch->pcdata->stats[UNI_RAGE] > 0 
						&& ch->pcdata->stats[UNI_RAGE] < 25 && !IS_ITEMAFF(ch, ITEMA_RAGER) )
					ch->pcdata->stats[UNI_RAGE] += 1;
				else if (ch->pcdata->stats[UNI_RAGE] > 0 && !IS_ITEMAFF(ch, ITEMA_RAGER))
					ch->pcdata->stats[UNI_RAGE] -= 1;
				if (ch->pcdata->stats[UNI_RAGE] < 1) continue;
				if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
						ch->move < ch->max_move )
					werewolf_regen(ch);
				if (ch->loc_hp[6] > 0)
				{
					int sn = skill_lookup( "clot" );
					(*skill_table[sn].spell_fun) (sn,ch->level,ch,ch);
				}
				else
				{
					if ((ch->loc_hp[0] + ch->loc_hp[1] + ch->loc_hp[2] +
								ch->loc_hp[3] + ch->loc_hp[4] + ch->loc_hp[5]) != 0)
						reg_mend(ch);
				}
			}
			//Werewolf updates... 
			else if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_WEREWOLF) && IS_HERO(ch))
			{
				/* GONE! - Spiral
				   if (ch->position == POS_FIGHTING && !IS_ITEMAFF(ch, ITEMA_RAGER))
				   {
				   if (ch->pcdata->stats[UNI_RAGE] < 300)
				   ch->pcdata->stats[UNI_RAGE] += number_range(5,10);
				   if (ch->pcdata->stats[UNI_RAGE] < 300 && ch->pcdata->powers[WPOWER_WOLF] > 3)
				   ch->pcdata->stats[UNI_RAGE] += number_range(5,10);
				   if (!IS_SET(ch->special, SPC_WOLFMAN) && 
				   ch->pcdata->stats[UNI_RAGE] >= 100)
				   {
				   do_werewolf(ch,"");
				   update_damcap(ch,ch);
				   }
				   }*/
				if (ch->pcdata->stats[UNI_RAGE] > 0 && !IS_ITEMAFF(ch, ITEMA_RAGER))
				{
					ch->pcdata->stats[UNI_RAGE] -= 1;
					if (ch->pcdata->stats[UNI_RAGE] < 100) do_unwerewolf(ch,"");
				}
				if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
						ch->move < ch->max_move )
					werewolf_regen(ch);

				if (IS_CLASS(ch,CLASS_WEREWOLF) && ch->position == POS_SLEEPING
						&& ch->pcdata->powers[WPOWER_BEAR] > 3 && ch->hit > 0)
				{
					if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
							ch->move < ch->max_move )
						werewolf_regen(ch);
					if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
							ch->move < ch->max_move )
						werewolf_regen(ch);
					if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
							ch->move < ch->max_move )
						werewolf_regen(ch);
					if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
							ch->move < ch->max_move )
						werewolf_regen(ch);
				}
				if (ch->loc_hp[6] > 0)
				{
					int sn = skill_lookup( "clot" );
					(*skill_table[sn].spell_fun) (sn,ch->level,ch,ch);
				}
				else
				{
					if ((ch->loc_hp[0] + ch->loc_hp[1] + ch->loc_hp[2] +
								ch->loc_hp[3] + ch->loc_hp[4] + ch->loc_hp[5]) != 0)
						reg_mend(ch);
				}
			}
			else if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_MAGE) 
					&& (has_sphere(ch,SPHERE_LIFE) >= 6) && IS_HERO(ch) && IS_SET(ch->sphere_spaffect,AFSPHERE_REGEN) )
			{
				if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana ||
						ch->move < ch->max_move )
					werewolf_regen(ch);
				if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana ||
						ch->move < ch->max_move )
					werewolf_regen(ch);
				if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana ||
						ch->move < ch->max_move )
					werewolf_regen(ch);

				if (ch->loc_hp[6] > 0)
				{
					int sn = skill_lookup( "clot" );
					(*skill_table[sn].spell_fun) (sn,ch->level,ch,ch);
				}
				else
				{
					if ((ch->loc_hp[0] + ch->loc_hp[1] + ch->loc_hp[2] +
								ch->loc_hp[3] + ch->loc_hp[4] + ch->loc_hp[5]) != 0)
						reg_mend(ch);
				}
			}
			else if ((IS_CLASS(ch, CLASS_DEMON) || IS_SET(ch->special, SPC_CHAMPION)) && IS_HERO(ch)
					&& ch->in_room != NULL && ch->in_room->vnum == 30000)
			{
				if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
						ch->move < ch->max_move )
					werewolf_regen(ch);
				if (ch->hit > 0)
				{
					if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
							ch->move < ch->max_move )
						werewolf_regen(ch);
					if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
							ch->move < ch->max_move )
						werewolf_regen(ch);
					if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
							ch->move < ch->max_move )
						werewolf_regen(ch);
					if ( ch->hit < ch->max_hit || ch->mana < ch->max_mana || 
							ch->move < ch->max_move )
						werewolf_regen(ch);
				}
				if (ch->loc_hp[6] > 0)
				{
					int sn = skill_lookup( "clot" );
					(*skill_table[sn].spell_fun) (sn,ch->level,ch,ch);
				}
				else
				{
					if ((ch->loc_hp[0] + ch->loc_hp[1] + ch->loc_hp[2] +
								ch->loc_hp[3] + ch->loc_hp[4] + ch->loc_hp[5]) != 0)
						reg_mend(ch);
				}
			}
			continue;
		}

		if ( IS_AFFECTED(ch, AFF_CHARM) ) continue;
		/* Examine call for special procedure */
		if ( ch->spec_fun != 0 )
		{
			if ( (*ch->spec_fun) ( ch ) )
				continue;
			if (ch == NULL) continue;
		}

		/*dead Time keeper, for zombies and other timed creatures */
		if (IS_NPC(ch) && IS_SET(ch->act,ACT_DEAD))
		{
			if (ch->dead_time <= 0 )
			{
				act("$n crumbles in to dust.",ch,NULL,NULL,TO_ROOM);
				extract_char(ch,TRUE);
				continue;
			}
			else
			{
				ch->dead_time -= 1;
			}
		}

		/* That's all for sleeping / busy monster */
		if ( ch->position != POS_STANDING )
			continue;

		/* Scavenge */
		if ( IS_SET(ch->act, ACT_SCAVENGER)
				&&   ch->in_room->contents != NULL
				&&   number_bits( 2 ) == 0 )
		{
			OBJ_DATA *obj;
			OBJ_DATA *obj_best;
			int max;

			max         = 1;
			obj_best    = 0;
			for ( obj = ch->in_room->contents; obj != NULL; obj = obj->next_content )
			{
				if ( CAN_WEAR(obj, ITEM_TAKE) && obj->cost > max )
				{
					obj_best    = obj;
					max         = obj->cost;
				}
			}

			if ( obj_best )
			{
				obj_from_room( obj_best );
				obj_to_char( obj_best, ch );
				act( "$n picks $p up.", ch, obj_best, NULL, TO_ROOM );
				act( "You pick $p up.", ch, obj_best, NULL, TO_CHAR );
			}
		}

		/* Wander */
		if ( !IS_SET(ch->act, ACT_SENTINEL)
				&& ( door = number_bits( 5 ) ) <= 5
				&& ( pexit = ch->in_room->exit[door] ) != NULL
				&&   pexit->to_room != NULL
				&&   !IS_SET(pexit->exit_info, EX_CLOSED)
				&&   !IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB)
				&& ( ch->hunting == NULL || ch->hunting->len < 2 )
				&&   (pexit->to_room->area == ch->in_room->area ))
		{
			move_char( ch, door );
		}

		if (IS_NPC(ch) )
		{
			if ( ch->fighting == NULL )
			{
				if (ch->stance[0] > 0 )
				{
					act("$n relaxes from $s fighting stance.",ch,NULL,NULL,TO_ROOM);
					ch->stance[0] = STANCE_NONE;
				}
			}
		}

		if (IS_NPC(ch))
		{
			mem_fade(ch);

			if ( ch->fighting == NULL
					&& IS_AWAKE(ch)
					&& ch->mob_hunting != NULL )
			{
				hunt_victim(ch);
				continue;
			}
		}


		/* Flee */
		if ( ch->hit < ch->max_hit / 2
				&& ( door = number_bits( 3 ) ) <= 5
				&& ( pexit = ch->in_room->exit[door] ) != NULL
				&&   pexit->to_room != NULL
				&&   !IS_AFFECTED(ch, AFF_WEBBED)
				&&   ch->level < 900
				&&   !IS_SET(pexit->exit_info, EX_CLOSED)
				&&   !IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB) )
		{
			CHAR_DATA *rch;
			bool found;

			found = FALSE;
			for ( rch  = pexit->to_room->people;
					rch != NULL;
					rch  = rch->next_in_room )
			{
				if ( !IS_NPC(rch) )
				{
					found = TRUE;
					break;
				}
			}
			if ( !found )
				move_char( ch, door );
		}

	}


	mudsetting->last_proc_logged = 91;
	return;
}



/*
 * Update the weather.
 */
/*
void weather_update( void )
{
	char buf[MAX_STRING_LENGTH];
	DESCRIPTOR_DATA *d;
	CHAR_DATA *ch;
	int playwave = 666;
	int diff;
	bool char_up;
	
	buf[0] = '\0';
	
	switch ( ++time_info.hour )
	{
		case  5:
			weather_info.sunlight = SUN_LIGHT;
			strcat( buf, "{wThe day has begun.{x\n\r" );
			break;
			
		case  6:
			weather_info.sunlight = SUN_RISE;
			strcat( buf, "{wThe sun rises in the east.{x\n\r" );
			playwave = 13;
			break;
			
		case 19:
			weather_info.sunlight = SUN_SET;
			strcat( buf, "{wThe sun slowly disappears in the west.{x\n\r" );
			break;
			
		case 20:
			weather_info.sunlight = SUN_DARK;
			strcat( buf, "{wThe night has begun.{x\n\r" );
			playwave = 12;
			break;
			
		case 24:
			time_info.hour = 0;
			time_info.day++;
			for ( d = descriptor_list; d != NULL; d = d->next )
			{
				char_up = FALSE;
				if ( d->connected == CON_PLAYING
					&&   (ch = d->character) != NULL
					&&  !IS_NPC(ch))
				{
					playwave_toch(ch,0);
					send_to_char( "{wYou hear a clock in the distance strike midnight.{x\n\r",ch);
				}
			}
			break;
	}
	if ( playwave != 666)
	{
		for ( d = descriptor_list; d != NULL; d = d->next )
		{
			char_up = FALSE;
			if ( d->connected == CON_PLAYING
				&&   (ch = d->character) != NULL
				&&  !IS_NPC(ch))
			{
				playwave_toch(ch,playwave);
			}
		}
	}
	
	if ( time_info.day   >= 35 )
	{
		time_info.day = 0;
		time_info.month++;
	}
	
	if ( time_info.month >= 17 )
	{
		time_info.month = 0;
		time_info.year++;
	}
	
	if ( time_info.month >= 9 && time_info.month <= 16 )
		diff = weather_info.mmhg >  985 ? -2 : 2;
	else
		diff = weather_info.mmhg > 1015 ? -2 : 2;
	
	weather_info.change   += diff * dice(1, 4) + dice(2, 6) - dice(2, 6);
	weather_info.change    = UMAX(weather_info.change, -12);
	weather_info.change    = UMIN(weather_info.change,  12);
	
	weather_info.mmhg += weather_info.change;
	weather_info.mmhg  = UMAX(weather_info.mmhg,  960);
	weather_info.mmhg  = UMIN(weather_info.mmhg, 1040);
	
	switch ( weather_info.sky )
	{
		default: 
			bug( "Weather_update: bad sky %d.", weather_info.sky );
			weather_info.sky = SKY_CLOUDLESS;
			break;
			
		case SKY_CLOUDLESS:
			if ( weather_info.mmhg <  990
				|| ( weather_info.mmhg < 1010 && number_bits( 2 ) == 0 ) )
			{
				strcat( buf, "The sky is getting cloudy.\n\r" );
				weather_info.sky = SKY_CLOUDY;
			}
			break;
			
		case SKY_CLOUDY:
			if ( weather_info.mmhg <  970
				|| ( weather_info.mmhg <  990 && number_bits( 2 ) == 0 ) )
			{
				strcat( buf, "It starts to rain.\n\r" );
				weather_info.sky = SKY_RAINING;
			}
			
			if ( weather_info.mmhg > 1030 && number_bits( 2 ) == 0 )
			{
				strcat( buf, "The clouds disappear.\n\r" );
				weather_info.sky = SKY_CLOUDLESS;
			}
			break;
			
		case SKY_RAINING:
			if ( weather_info.mmhg <  970 && number_bits( 2 ) == 0 )
			{
				strcat( buf, "Lightning flashes in the sky.\n\r" );
				weather_info.sky = SKY_LIGHTNING;
			}
			
			if ( weather_info.mmhg > 1030
				|| ( weather_info.mmhg > 1010 && number_bits( 2 ) == 0 ) )
			{
				strcat( buf, "The rain stopped.\n\r" );
				weather_info.sky = SKY_CLOUDY;
			}
			break;
			
		case SKY_LIGHTNING:
			if ( weather_info.mmhg > 1010
				|| ( weather_info.mmhg >  990 && number_bits( 2 ) == 0 ) )
			{
				strcat( buf, "The lightning has stopped.\n\r" );
				weather_info.sky = SKY_RAINING;
				break;
			}
			break;
	}
	
	if ( buf[0] != '\0' )
	{
		for ( d = descriptor_list; d != NULL; d = d->next )
		{
			if ( d->connected == CON_PLAYING
				&&   IS_OUTSIDE(d->character)
				&&   IS_AWAKE(d->character) )
			{
				if ( weather_info.sky == SKY_RAINING )
					playwave_toch(d->character,4);
				send_to_char( buf, d->character );
			}
		}
	}
	
	return;
}
*/


void paradox_hit (CHAR_DATA *ch)
{
	ROOM_INDEX_DATA *location;
	char buf[MSL];

	if ( ( location = get_room_index( ROOM_VNUM_TEMPLE ) ) == NULL )
	{
		send_to_char( "You are completely lost.\n\r", ch );
		return;
	}
	
	if ( ch->in_room == location )
		return;
	

	ch->hit = 0;
	ch->move = 0;
	ch->mana = 0;
	update_pos(ch);
	act( "$n fades out of existance.", ch, NULL, NULL, TO_ROOM );
	char_from_room( ch );
	char_to_room( ch, location );
	act( "$n fades into existance.", ch, NULL, NULL, TO_ROOM );
	do_look( ch, "auto" );
	sprintf(buf,"Mages do exist! %s has gotten nailed by paradox!",ch->name->str);
	do_info(ch,buf);
	return;
}

/*
 * use this to run though the pet routine on update.
 */
void add_neg_behavior( CHAR_DATA *ch )
{
    int randB = 0,randD;
    
    randD = dice(1,64);
    
    switch (randD)
    {
        case 1:
            if (!IS_SET(ch->pet_stats[PET_BEHAVIOR], BEHAVIOR_ANNOYING))
                SET_BIT(ch->pet_stats[PET_BEHAVIOR], BEHAVIOR_ANNOYING);
            break;
        
        case 2:
            if (!IS_SET(ch->pet_stats[PET_BEHAVIOR], BEHAVIOR_RANDOM_SPELL))
                SET_BIT(ch->pet_stats[PET_BEHAVIOR], BEHAVIOR_RANDOM_SPELL);
            break;

        default:
            randB = 0;
            break;
    }

    return;
}

void pet_update( CHAR_DATA *ch )
{
    // Make sure the people we don't wanna update don't make it here.

    if (!IS_NPC(ch) || (IS_NPC(ch) && !IS_PET(ch))) 
        return;
    
    //Knock thier Hunger and Thirst down.
    ch->pet_stats[PET_HUNGER]--;
    ch->pet_stats[PET_THIRST]--;

    //check if theres any other pets in the room.
    check_pet_reaction(ch);

    if (ch->pet_stats[PET_HUNGER] < 5)
        ch->pet_stats[PET_AFFECTION] -= 2;
    else if (ch->pet_stats[PET_HUNGER] < 10)
        do_say(ch,"Umm please give me some food?");
    else if (ch->pet_stats[PET_HUNGER] < 20)
        do_say(ch,"Hey YOU!.. I NEED FOOD!");
    else if (ch->pet_stats[PET_HUNGER] < 30)
        do_say(ch,"I'm getting hungry here people!");
    
    if (ch->pet_stats[PET_THIRST] < 5)
        ch->pet_stats[PET_AFFECTION] -= 2;
    else if (ch->pet_stats[PET_THIRST] < 10)
        do_say(ch,"Umm please give me something to drink?");
    else if (ch->pet_stats[PET_THIRST] < 20)
        do_say(ch,"Hey YOU!.. I NEED SOMETHING TO DRINK!");
    else if (ch->pet_stats[PET_THIRST] < 30)
        do_say(ch,"I'm getting thirst here people!");
    
    if (ch->pet_stats[PET_AFFECTION] < 10)
    {
        ch->pet_stats[PET_PERM_AFF] --;    
        ch->pet_stats[PET_AFFECTION] = 50;
    }
    
    if (ch->pet_stats[PET_AFFECTION] >= 100)
    {
        ch->pet_stats[PET_PERM_AFF] --;    
        ch->pet_stats[PET_AFFECTION] = 50;
    }

    if (ch->pet_stats[PET_PERM_AFF] < 10)
        add_neg_behavior(ch);
    
    /*
     * Start Parseing though the Behavior Bits that
     * Are affected at update.
     */

    if (IS_SET(ch->pet_stats[PET_BEHAVIOR], BEHAVIOR_ANNOYING))
    {
        switch (dice(1,34))
        {
            case 1: 
                do_say(ch,"Did you know I'm related to puff?");
                break;
            case 2:
                do_say(ch,"Hey, what are we doing today?");
                break;
            case 3:
                do_say(ch,"Your mama was a hampster and your father smelled of elderberry!");
                break;
            case 4:
                do_say(ch,"Psst, Spiral's Kewler then you!");
                break;
        }
    }

    return;

}

/*
 * Update all chars, including mobs.
 * This function is performance sensitive.
 */
void char_update( void )
{   
	CHAR_DATA *ch;
	CHAR_DATA *ch_next;
	CHAR_DATA *ch_save;
	CHAR_DATA *ch_quit;
	bool is_obj;
	bool drop_out = FALSE;
	time_t save_time;
	OBJ_DATA *obj;
	int max = 100;
	int min = 50;
	int haunt_count;
	char buf[MAX_STRING_LENGTH];
	int ch_age;  /* hours calculation */
	

	save_time	= current_time;
	ch_save	= NULL;
	ch_quit	= NULL;
    
    logchan("Tick!",NULL,NULL,WIZ_TICKS,0,LEVEL_IMMORTAL);

	for ( ch = char_list; ch != NULL; ch = ch_next )
	{
		AFFECT_DATA *paf;
		AFFECT_DATA *paf_next;
		SPHERE_DATA *sp_paf;
		SPHERE_DATA *sp_paf_next;

		ch_next = ch->next;

		mudsetting->last_proc_logged = 3088;

		if (IS_NPC(ch) && IS_PET(ch))
			pet_update(ch);

		if ( ch->pk_timer > 0 )
			ch->pk_timer--;

		if ( !IS_NPC(ch) && ch->pcdata->obeah > 0 )
			ch->pcdata->obeah--;

		if (!IS_NPC(ch) && ch->pcdata->obeah == 0 && ch->plane == PLANE_PUNISHMENT)
		{
			ch->plane = PLANE_NORMAL;
			send_to_char("Your punishment time is OVER.\n\r",ch);
			shift_obj_plane(ch);
		}

		if ( ch->attack_timer > 0 )
			ch->attack_timer--;

		/*
		   if (ch->pk_timer == 0)
		   {
		   if (ch->last_attacked != NULL)
		   ch->last_attacked = NULL;
		   }
		   */

		if ( ch->attack_timer == 0 )
		{
			REMOVE_BIT(ch->act,PLR_ATTACK);
			ch->pk_sect = 0;
		}

		if ( ch->delay_timer > 0 )
			ch->delay_timer--;

		if ( ch->silent_time > 0 )
			ch->silent_time--;

		if (!IS_NPC(ch) && (IS_HEAD(ch,LOST_HEAD) || IS_EXTRA(ch,EXTRA_OSWITCH)))
			is_obj = TRUE;
		else if (!IS_NPC(ch) && ch->pcdata->obj_vnum != 0)
		{
			is_obj = TRUE;SET_BIT(ch->extra, EXTRA_OSWITCH);
		}
		else
			is_obj = FALSE;
		/*
		 * Find dude with oldest save time.
		 */
		if ( !IS_NPC(ch)
				&& ( ch->desc == NULL || ch->desc->connected == CON_PLAYING )
				&&   ch->level >= 2
				&&   ch->save_time < save_time )
		{
			ch_save	= ch;
			save_time	= ch->save_time;
		}
		if ( ch->position > POS_STUNNED && !is_obj)
		{
			if ( ch->hit  < ch->max_hit )
				ch->hit  += hit_gain(ch);

			if ( ch->mana < ch->max_mana )
				ch->mana += mana_gain(ch);

			if ( ch->move < ch->max_move )
				ch->move += move_gain(ch);
		}
		if ( IS_CLASS(ch,CLASS_MAGE) && IS_SET(ch->act,ACT_TAPPING))
		{
			if (ch->in_room->vnum != ROOM_VNUM_CAERN)
				REMOVE_BIT(ch->act,ACT_TAPPING);
		}
		if ( ch->position == POS_STUNNED && !is_obj)
		{
			ch->hit = ch->hit + number_range(2,4);
			update_pos( ch );
		}

		if (is_obj)
		{
			if ( ++ch->timer >= 12 )
			{
				if ( ch->was_in_room == NULL && ch->in_room != NULL )
				{
					if ( ( obj = ch->pcdata->chobj ) != NULL )
					{
						ch->pcdata->obj_vnum = 0;
						obj->chobj = NULL;
						ch->pcdata->chobj = NULL;
						REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
						REMOVE_BIT(ch->extra, EXTRA_OSWITCH);
						ch->morph = g_string_assign(ch->morph,"");
						act("$p transforms into $n.",ch,obj,NULL,TO_ROOM);
						act("Your reform your human body.",ch,obj,NULL,TO_CHAR);
						extract_obj(obj);
					}

					ch->was_in_room = ch->in_room;
					if ( ch->fighting != NULL )
						stop_fighting( ch, TRUE );
					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 > 30 ) ch_quit = ch;
		}

		if (!IS_NPC(ch) && !is_obj && ch->pcdata->stage[0] > 0 )
			ch->pcdata->stage[0]--;	



		if ( !IS_NPC(ch) && ch->level < LEVEL_IMMORTAL && !is_obj)
		{
			OBJ_DATA *obj;
			int blood;

			if ( ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) != NULL
						&&   obj->item_type == ITEM_LIGHT
						&&   obj->value[2] > 0 )
					|| ( ( obj = get_eq_char( ch, WEAR_HOLD ) ) != NULL
						&&   obj->item_type == ITEM_LIGHT
						&&   obj->value[2] > 0 ) )
			{
				if ( --obj->value[2] == 0 && ch->in_room != NULL )
				{
					--ch->in_room->light;
					act( "$p goes out.", ch, obj, NULL, TO_ROOM );
					act( "$p goes out.", ch, obj, NULL, TO_CHAR );
					extract_obj( obj );
				}
			}

			if ( ++ch->timer >= 12 )
			{
				if ( ch->was_in_room == NULL && ch->in_room != NULL )
				{
					ch->was_in_room = ch->in_room;
					if ( ch->fighting != NULL )
						stop_fighting( ch, TRUE );
					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 > 30 ) 
				ch_quit = ch;




			gain_condition( ch, COND_DRUNK,  -1 );

			if (!IS_CLASS(ch, CLASS_VAMPIRE))
			{
				gain_condition( ch, COND_FULL, -1 );
				gain_condition( ch, COND_THIRST, -1 );
			}
			else
			{
				blood = -1;
				if (ch->beast > 0)
				{
					blood -= (count_snoopers(ch->desc) * 10);
					if (IS_VAMPAFF(ch, VAM_CLAWS)) blood -= number_range(1,3);
					if (IS_VAMPAFF(ch, VAM_FANGS)) blood -= 1;
					if (IS_VAMPAFF(ch, VAM_NIGHTSIGHT)) blood -= 1;
					if (IS_SET(ch->sight, SIGHT_SPIRIT)) blood -=1;
					if (IS_SET(ch->act, PLR_HOLYLIGHT)) blood -= number_range(1,5);
					if (IS_VAMPAFF(ch, VAM_DISGUISED)) blood -= number_range(5,10);
					if (IS_VAMPAFF(ch, VAM_CHANGED)) blood -= number_range(5,10);
					if (IS_VAMPAFF(ch, IMM_SHIELDED)) blood -= number_range(1,3);
					if (IS_POLYAFF(ch, POLY_SERPENT)) blood -= number_range(1,3);
					if (IS_SET(ch->act, PLR_MARBLEFLESH)) blood -= 2;
					if (IS_SET(ch->added, ADDED_CLOAK)) blood -= number_range(5,10);
					if (IS_SET(ch->act, PLR_WIZINVIS)) blood -= 5;
					if (IS_SET(ch->added, ADDED_NIGHTFALL)) blood -= 5;
					if (IS_SET(ch->added, ADDED_DISCERN)) blood -= 30;
					if (ch->beast == 100) blood *= 2;
				}
				if (!IS_IMMORTAL(ch))
					gain_condition( ch, COND_THIRST, blood );
			}
		}
		/*PLAYER ONLY AFFECTS!*/
		if (!IS_NPC(ch))
		{	
			if (IS_AFFECTED(ch, AFF_DISEASE))
			{
				ch->pcdata->condition[COND_THIRST] -= 10;
				send_to_char("Blood trickles out of your ears, nose and mouth.\n\r",ch);
			}
			if (IS_ADDED(ch, ADDED_FLAMES_PURE))
			{
				min += 10 - ch->pcdata->stats[UNI_GEN];
				max += 20 - (ch->pcdata->stats[UNI_GEN] * 2);
				ch->mana -= UMIN(ch->mana + number_range(min,max), ch->max_mana);
				update_pos(ch);
				send_to_char("Your body burns from the flames of purification.\n\r",ch);
				act("$n's body burns from the flames of purification.",ch,NULL,NULL,TO_ROOM);

			}

			/* Haunt Effects ! */
			if (IS_ADDED(ch, ADDED_HAUNT))
			{
				haunt_count = number_range(1,HAUNT_MAX);
				sprintf(buf,"%s",haunt_table[haunt_count].haunt);
				strcat(buf,"\n\r");
				send_to_char(buf, ch);
			}
			if (IS_CLASS(ch,CLASS_VAMPIRE) && IS_SET(ch->added,ADDED_DIABLERIE))
				ch->pcdata->diab[DIAB_TIME]--;

			if (IS_SET(ch->added,ADDED_DIABLERIE) && ch->pcdata->diab[DIAB_TIME] <= 0 )
			{
				REMOVE_BIT(ch->added,ADDED_DIABLERIE);
				send_to_char("The aura of Diablerie leaves your body.\n\r",ch);
			}
		}

		if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_MAGE))
		{
			ch_age = (get_age(ch) - 17) * 2;
			if (ch_age >= 1500) 
			{
				if (ch->paradox[0] >= 500)
				{
					send_to_char("Paradox STRIKES! You been using magic too quick!",ch);
					ch->paradox[0] = 0;
					paradox_hit(ch);
				}
			}
			else if (ch_age >=  800) 
			{
				if (ch->paradox[0] >= 400)
				{
					send_to_char("Paradox STRIKES! You been using magic too quick!",ch);
					ch->paradox[0] = 0;
					paradox_hit(ch);
				}
			}
			else if (ch_age >=  400) 
			{
				if (ch->paradox[0] >= 300)
				{
					send_to_char("Paradox STRIKES! You been using magic too quick!",ch);
					ch->paradox[0] = 0;
					paradox_hit(ch);
				}
			}
			else if (ch_age >=  200) 
			{
				if (ch->paradox[0] >= 200)
				{
					send_to_char("Paradox STRIKES! You been using magic too quick!",ch);
					ch->paradox[0] = 0;
					paradox_hit(ch);
				}
			}
			else                     
			{
				if (ch->paradox[0] >= 100)
				{
					send_to_char("Paradox STRIKES! You been using magic too quick!",ch);
					ch->paradox[0] = 0;
					paradox_hit(ch);
				}
			}
			if (ch->paradox[0] > 1)
			{
				if (IS_SET(ch->sphere_spaffect,AFSPHERE_SQUARE_CIRCLE) && ch->position == POS_MEDITATING )
					ch->paradox[0] -= 5;

				ch->paradox[0] -= 1;
			}
		}

		if (!IS_NPC(ch) && IS_CLASS(ch,CLASS_VAMPIRE) && ch->pcdata->condition[COND_THIRST] < 25) 
		{
			/* Auto Convert for low blood */

			if (ch->plane != PLANE_NORMAL && ch->plane != PLANE_PUNISHMENT)
			{
				send_to_char("You phase back to reality.\n\r",ch);

				ch->plane = 1;
				shift_obj_plane(ch);
				clear_stats(ch);
				ch->morph = g_string_assign(ch->morph,"");
			}


			if (IS_VAMPAFF(ch, VAM_CHANGED) && IS_SET(ch->pcdata->powers[WOLF_POLYAFF], POLY_ZULO))
			{
				REMOVE_BIT(ch->pcdata->powers[WOLF_POLYAFF], POLY_ZULO);
				ch->max_hit = ch->max_hit - 1000;
				ch->hit = ch->hit - 1000;
				ch->armor -= 500;
				ch->damroll -= 250;

				if (ch->hit < 1) ch->hit = 1;
				act( "Low blood causes you transform into human form.", ch, NULL, NULL, TO_CHAR );
				act( "$n transforms into human form.", ch, NULL, NULL, TO_ROOM );
				REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
				REMOVE_BIT(ch->pcdata->stats[UNI_AFF], VAM_CHANGED);
				clear_stats(ch);
				ch->morph = g_string_assign(ch->morph,"");
			}

			if (IS_AFFECTED(ch,AFF_POLYMORPH) && IS_SET(ch->extra, EXTRA_OSWITCH));
			{
				if ( ( obj = ch->pcdata->chobj ) != NULL )
				{
					ch->pcdata->obj_vnum = 0;
					obj->chobj = NULL;
					ch->pcdata->chobj = NULL;
					REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
					REMOVE_BIT(ch->extra, EXTRA_OSWITCH);
					ch->morph = g_string_assign(ch->morph,"");
					act("$p transforms into $n.",ch,obj,NULL,TO_ROOM);
					act("Due to lack of blood you reform in to your human body.",ch,obj,NULL,TO_CHAR);
					extract_obj(obj);
				}
			}
			if (IS_SET(ch->act, PLR_WIZINVIS));
			{
				REMOVE_BIT(ch->act,PLR_WIZINVIS);
				act("$n becomes visible.",ch,NULL,NULL,TO_ROOM);
				send_to_char("You become visible.\n\r",ch);
			}

		}

		for ( paf = ch->affected; paf != NULL; paf = paf_next )
		{
			paf_next	= paf->next;
			if ( paf->duration > 0 )
				paf->duration--;
			else if ( paf->duration < 0 )
				;
			else
			{
				if ( paf_next == NULL
						||   paf_next->type != paf->type
						||   paf_next->duration > 0 )
				{
					if ( paf->type > 0 && skill_table[paf->type].msg_off && !is_obj)
					{
						send_to_char( skill_table[paf->type].msg_off, ch );
						send_to_char( "\n\r", ch );
					}
				}

				affect_remove( ch, paf );
			}
		}

		for ( sp_paf = ch->sphere_affected; sp_paf != NULL; sp_paf = sp_paf_next )
		{
			sp_paf_next	= sp_paf->next;
			if ( sp_paf->duration > 0 )
				sp_paf->duration--;
			else if ( sp_paf->duration < 0 )
				;
			else
			{
				if ( sp_paf_next == NULL
						||   sp_paf_next->type != sp_paf->type
						||   sp_paf_next->duration > 0 )
				{
					send_to_char( mage_affect_table[sp_paf->spell_number].off_msg, ch );
					send_to_char( "\n\r", ch );
				}
				/* Check for Special Bits IE:Poly_MIST */
				if (!IS_NPC(ch))
				{
					if (IS_CLASS(ch,CLASS_MAGE) && IS_SET(ch->added,ADDED_POLY_MIST))
						do_unmist(ch,"unmist");	
				}
				sphere_remove( ch, sp_paf );
			}
		}
		/*
		 * Careful with the damages here,
		 *   MUST NOT refer to ch after damage taken,
		 *   as it may be lethal damage (on NPC).
		 */
		if ( ch->loc_hp[6] > 0 && !is_obj && ch->in_room != NULL )
		{
			int dam = 0;
			int minhit = 0;
			if (!IS_NPC(ch)) minhit = -11;
			if (IS_BLEEDING(ch,BLEEDING_HEAD) && (ch->hit-dam) > minhit )
			{
				act( "A spray of blood shoots from the stump of $n's neck.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "A spray of blood shoots from the stump of your neck.\n\r", ch );
				dam += number_range(20,50);
			}
			if (IS_BLEEDING(ch,BLEEDING_THROAT) && (ch->hit-dam) > minhit )
			{
				act( "Blood pours from the slash in $n's throat.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "Blood pours from the slash in your throat.\n\r", ch );
				dam += number_range(10,20);
			}
			if (IS_BLEEDING(ch,BLEEDING_ARM_L) && (ch->hit-dam) > minhit )
			{
				act( "A spray of blood shoots from the stump of $n's left arm.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "A spray of blood shoots from the stump of your left arm.\n\r", ch );
				dam += number_range(10,20);
			}
			else if (IS_BLEEDING(ch,BLEEDING_HAND_L) && (ch->hit-dam) > minhit )
			{
				act( "A spray of blood shoots from the stump of $n's left wrist.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "A spray of blood shoots from the stump of your left wrist.\n\r", ch );
				dam += number_range(5,10);
			}
			if (IS_BLEEDING(ch,BLEEDING_ARM_R) && (ch->hit-dam) > minhit )
			{
				act( "A spray of blood shoots from the stump of $n's right arm.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "A spray of blood shoots from the stump of your right arm.\n\r", ch );
				dam += number_range(10,20);
			}
			else if (IS_BLEEDING(ch,BLEEDING_HAND_R) && (ch->hit-dam) > minhit )
			{
				act( "A spray of blood shoots from the stump of $n's right wrist.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "A spray of blood shoots from the stump of your right wrist.\n\r", ch );
				dam += number_range(5,10);
			}
			if (IS_BLEEDING(ch,BLEEDING_LEG_L) && (ch->hit-dam) > minhit )
			{
				act( "A spray of blood shoots from the stump of $n's left leg.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "A spray of blood shoots from the stump of your left leg.\n\r", ch );
				dam += number_range(10,20);
			}
			else if (IS_BLEEDING(ch,BLEEDING_FOOT_L) && (ch->hit-dam) > minhit )
			{
				act( "A spray of blood shoots from the stump of $n's left ankle.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "A spray of blood shoots from the stump of your left ankle.\n\r", ch );
				dam += number_range(5,10);
			}
			if (IS_BLEEDING(ch,BLEEDING_LEG_R) && (ch->hit-dam) > minhit )
			{
				act( "A spray of blood shoots from the stump of $n's right leg.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "A spray of blood shoots from the stump of your right leg.\n\r", ch );
				dam += number_range(10,20);
			}
			else if (IS_BLEEDING(ch,BLEEDING_FOOT_R) && (ch->hit-dam) > minhit )
			{
				act( "A spray of blood shoots from the stump of $n's right ankle.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "A spray of blood shoots from the stump of your right ankle.\n\r", ch );
				dam += number_range(5,10);
			}
			if (IS_HERO(ch)) { ch->hit = ch->hit - dam;
				if (ch->hit < 1) ch->hit = 1; }
			else ch->hit = ch->hit - dam;
			update_pos(ch);
			ch->in_room->blood += dam;
			if (ch->in_room->blood > 1000) ch->in_room->blood = 1000;
			if (ch->hit <=-11 || (IS_NPC(ch) && ch->hit < 1))
			{
				do_killperson(ch,ch->name->str);
				drop_out = TRUE;
			}
		}
		if (is_affected(ch, gsn_plague) && ch != NULL)
		{
			AFFECT_DATA *af, plague;
			CHAR_DATA *vch;
			int dam;

			if (ch->in_room != NULL)
			{
				act("$n writhes in agony as plague sores erupt from $s skin.",
						ch,NULL,NULL,TO_ROOM);
				send_to_char("You writhe in agony from the plague.\n\r",ch);
				for ( af = ch->affected; af != NULL; af = af->next )
				{
					if (af->type == gsn_plague)
						break;
				}

				if (af == NULL)
				{
					REMOVE_BIT(ch->affected_by,AFF_PLAGUE);
				}

				plague.type         = gsn_plague;
				plague.duration     = number_range(1,20);
				plague.location     = APPLY_STR;
				plague.modifier     = -5;
				plague.bitvector    = AFF_PLAGUE;

				for ( vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room)
				{
					if (IS_SWWF(vch) && get_tribe(vch,TRIBE_FIANNA) >= 1)
					{
						send_to_char("They seem to be unaffected.\n\r",ch);
						continue;
					}
					if (IS_HERO(vch) && !saves_spell(2,vch) &&  !IS_IMMORTAL(vch)
							&&  !IS_AFFECTED(vch,AFF_PLAGUE) )
					{
						send_to_char("You feel hot and feverish.\n\r",vch);
						act("$n shivers and looks very ill.",vch,NULL,NULL,TO_ROOM);
						affect_to_char(vch,&plague);
					}
				}

				if (!IS_NPC(ch))
				{
					dam = UMIN(ch->level,af->duration/5+1);
					ch->mana -= dam;
					ch->move -= dam;
					damage( ch, ch, dam, gsn_plague);
				}
			}
		}

		mudsetting->last_proc_logged = 3087;

		if ( IS_AFFECTED(ch, AFF_FLAMING) && !is_obj && !drop_out && ch->in_room != NULL )
		{
			int dam;
			if (!IS_NPC(ch) && IS_HERO(ch))
			{ 
				if (!IS_IMMMERIT(ch, IMM_MERIT_HEAT)) 
				{
					act( "$n's flesh burns and crisps.", ch, NULL, NULL, TO_ROOM );
					send_to_char( "Your flesh burns and crisps.\n\r", ch );

					dam = number_range(10,20);
					if (!IS_NPC(ch) && IS_IMMFLAW(ch, IMM_FLAW_HEAT)) 
						dam += dam;

					if (!IS_NPC(ch) && IS_IMMMERIT(ch, IMM_MERIT_HEAT)) dam /= 2;
					if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE)) dam *= 10;
					ch->hit = ch->hit - dam;
					update_pos(ch);
					if (ch->hit <=-11)
					{
						do_killperson(ch,ch->name->str);
						drop_out = TRUE;
					}
				}
			}
		}

		if ( IS_CLASS(ch, CLASS_VAMPIRE) 
				&& (!IS_NPC(ch) && !IS_IMMUNE(ch,IMM_SUNLIGHT)) 
				&& ch->in_room != NULL 
				&& (!ch->in_room->sector_type == SECT_INSIDE) 
				&& (ch->plane == PLANE_NORMAL)
				&& !is_obj 
				&& !room_is_dark(ch->in_room) 
				&& (weather_info[ch->in_room->sector_type].sunlight != SUN_DARK)
				&& (!IS_ITEMAFF(ch, ITEMA_FORTITUDE)) 
				&& get_disc(ch,DISC_FORTITUDE) < 9 )
		{
			act( "$n's flesh smolders in the sunlight!", ch, NULL, NULL, TO_ROOM );
			send_to_char( "Your flesh smolders in the sunlight!\n\r", ch );

			ch->hit -= ( number_range(3800,4200) - 
					( get_disc(ch,DISC_FORTITUDE) * number_range(480,500) ) );
			update_pos(ch);
			if (ch->hit <=-11)
			{
				do_killperson(ch,ch->name->str);
				drop_out = TRUE;
			}
		}

		if ( IS_AFFECTED(ch, AFF_POISON) && !is_obj && !drop_out )
		{
			act( "$n shivers and suffers.", ch, NULL, NULL, TO_ROOM );
			send_to_char( "You shiver and suffer.\n\r", ch );
			damage( ch, ch, 2, gsn_poison );
		}

		if ( ch->position == POS_INCAP && !is_obj && !drop_out )
		{
			if (IS_HERO(ch))
				ch->hit = ch->hit + number_range(2,4);
			else
				ch->hit = ch->hit - number_range(1,2);
			update_pos( ch );
			if (ch->position > POS_INCAP)
			{
				act( "$n's wounds stop bleeding and seal up.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "Your wounds stop bleeding and seal up.\n\r", ch );
			}
			if (ch->position > POS_STUNNED)
			{
				act( "$n clambers back to $s feet.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "You clamber back to your feet.\n\r", ch );
			}
		}

		if ( ch->position == POS_MORTAL && !is_obj && !drop_out )
		{
			drop_out = FALSE;
			if (IS_HERO(ch))
				ch->hit = ch->hit + number_range(2,4);
			else
			{
				ch->hit = ch->hit - number_range(1,2);
				if (!IS_NPC(ch) && (ch->hit <=-11))
					do_killperson(ch,ch->name->str);
				drop_out = TRUE;
			}
			if (!drop_out)
			{
				update_pos( ch );
				if (ch->position == POS_INCAP)
				{
					act( "$n's wounds begin to close, and $s bones pop back into place.", ch, NULL, NULL, TO_ROOM );
					send_to_char( "Your wounds begin to close, and your bones pop back into place.\n\r", ch );
				}
			}
		}

		if ( ch->position == POS_DEAD && !is_obj && !drop_out )
		{
			update_pos(ch);
			if (!IS_NPC(ch))
				do_killperson(ch,ch->name->str);
		}

		mudsetting->last_proc_logged = 3086;

		drop_out = FALSE;
	}
	
    /*
     * Autosave and autoquit.
     * Check that these chars still exist.
     */
	if ( ch_save != NULL || ch_quit != NULL )
	{
		for ( ch = char_list; ch != NULL; ch = ch_next )
		{
			ch_next = ch->next;
			if ( ch == ch_save )
				save_char_obj( ch );
			if ( ch == ch_quit )
				do_quit( ch, "" );
		}
	}
	
	mudsetting->last_proc_logged = 86;
	
	return;
}

/*
 * Update all objs.
 * This function is performance sensitive.
 */
void obj_update( void )
{   
	AFFECT_DATA *paf;
	AFFECT_DATA *paf_next;
	OBJ_DATA *obj;
	GSList *tmp = object_list;

	while ( tmp != NULL )
	{
		CHAR_DATA *rch;
		char *message;

		obj = (OBJ_DATA *)tmp->data;
		if (obj == NULL){
			bug("Something went wrong again!",0);
			continue;
		}
		
		/* go through affects and decrement */
		for ( paf = obj->affected; paf != NULL; paf = paf_next )
		{
			paf_next    = paf->next;
			if ( paf->duration > 0 )
			{
				paf->duration--;
			}
			else if ( paf->duration < 0 )
				;
			else
			{
				affect_remove_obj( obj, paf );
			}
		}

		/* IF object still has a timer Continue(Go tot he next object 
		 *    other wise extract that object
		 */	
		if ( obj->timer <= 0 || --obj->timer > 0 ){
			tmp = g_slist_next(tmp);
			continue;
		}

		//check for PROG
		if ( HAS_PROG(obj->pIndexData, TRIG_RANDOM) )
			oprog_percent_trigger(obj, obj->in_room->people, NULL, NULL, TRIG_RANDOM);

		if ( HAS_PROG(obj->pIndexData, TRIG_DELAY) )
			oprog_percent_trigger(obj, obj->in_room->people, NULL, NULL, TRIG_DELAY);

		if (IS_OBJ_STAT(obj,ITEM_FROZEN)){
			REMOVE_BIT(obj->extra_flags,ITEM_FROZEN);
			tmp = g_slist_next(tmp);
			continue;
		}

		switch ( obj->item_type )
		{
			default:              message = "$p vanishes.";         	break;
			case ITEM_FOUNTAIN:   message = "$p dries up.";         	break;
			case ITEM_CORPSE_NPC:
				if (IS_SET(mudsetting->mud_setting,MS_LIVING_DEAD) && obj->in_room != NULL)
				{
					create_zombie(obj);
					tmp = g_slist_next(tmp);
					continue;
				} 
				message = "$p decays into dust."; 	
				break;
			case ITEM_CORPSE_PC:  
					      message = "$p decays into dust."; 	
					      break;
			case ITEM_FOOD:       message = "$p decomposes.";		break;
			case ITEM_TRASH:      message = "$p crumbles into dust.";	break;
			case ITEM_EGG:        message = "$p cracks open.";		break;
			case ITEM_TFILET:     message = "$p almost vanishes from the amount of maggots chewing on it.";		break;
			case ITEM_FIRE:     message = "$p flickers and dies out.";		break;
			case ITEM_WEAPON:     message = "The poison on $p melts through it.";		break;
		}

		if ( obj->carried_by != NULL )
		{
			act( message, obj->carried_by, obj, NULL, TO_CHAR );
		}
		else if ( obj->in_room != NULL
				&&      ( rch = obj->in_room->people ) != NULL )
		{
			playwave_toroom(rch,1);
			act( message, rch, obj, NULL, TO_ROOM );
			act( message, rch, obj, NULL, TO_CHAR );
		}


		/* If the item is an egg, we need to create a mob and shell!
		 * KaVir
		 */
		if ( obj->item_type == ITEM_EGG )
		{
			CHAR_DATA      *creature;
			OBJ_DATA       *egg;
			if ( get_mob_index( obj->value[0] ) != NULL )
			{
				if (obj->carried_by != NULL && obj->carried_by->in_room != NULL)
				{
					creature = create_mobile( get_mob_index( obj->value[0] ) );
					char_to_room(creature,obj->carried_by->in_room);
				}
				else if (obj->in_room != NULL)
				{
					creature = create_mobile( get_mob_index( obj->value[0] ) );
					char_to_room(creature,obj->in_room);
				}
				else
				{
					creature = create_mobile( get_mob_index( obj->value[0] ) );
					char_to_room(creature,get_room_index(ROOM_VNUM_HELL));
					/*
					   obj->timer = 1;
					   continue;
					 */
				}
				egg = create_object( get_obj_index( OBJ_VNUM_EMPTY_EGG ), 0 );
				egg->timer = 2;
				obj_to_room( egg, creature->in_room );
				act( "$n clambers out of $p.", creature, obj, NULL, TO_ROOM );
			}
			else if (obj->in_room != NULL)
			{
				egg = create_object( get_obj_index( OBJ_VNUM_EMPTY_EGG ), 0 );
				egg->timer = 2;
				obj_to_room( egg, obj->in_room );
			}
		
		}
		tmp = g_slist_next(tmp);
		
		//Timer ran out.. extract the object
		extract_obj( obj );
		
	}
	
	g_slist_free(tmp);
	
	return;
}


void process_update_dlist(DESCRIPTOR_DATA *d)
{

	CHAR_DATA *ch;
	OBJ_DATA *chobj = NULL;
	OBJ_DATA *obj = NULL;
	ROOM_INDEX_DATA *objroom = NULL;

	if ( d->connected == CON_PLAYING
			&& ( ch = d->character ) != NULL
			&&   !IS_NPC(ch)
			&&   ch->pcdata != NULL
			&& ( obj = ch->pcdata->chobj ) != NULL )
	{
		if (obj->in_room != NULL)
			objroom = obj->in_room;
		else if (obj->in_obj != NULL)
			objroom = get_room_index(ROOM_VNUM_IN_OBJECT);
		else if (obj->carried_by != NULL)
		{
			if (obj->carried_by != ch && obj->carried_by->in_room != NULL)
				objroom = obj->carried_by->in_room;
			else return;
		}
		else return;
		if (ch->in_room != objroom && objroom != NULL)
		{
			char_from_room(ch);
			char_to_room(ch,objroom);
			do_look(ch,"auto");
		}
	}
	else if ( d->connected == CON_PLAYING
			&& ( ch = d->character ) != NULL
			&&   !IS_NPC(ch)
			&&   ch->pcdata != NULL
			&&   (IS_HEAD(ch,LOST_HEAD) || IS_EXTRA(ch,EXTRA_OSWITCH) || ch->pcdata->obj_vnum != 0) )
	{
		if (ch->pcdata->obj_vnum != 0)
		{
			bind_char(ch);
			return;
		}
		if (IS_HEAD(ch,LOST_HEAD))
		{
			REMOVE_BIT(ch->loc_hp[0],LOST_HEAD);
			send_to_char("You are able to regain a body.\n\r",ch);
			ch->position = POS_RESTING;
			ch->hit = 1;
		} else {
			send_to_char("You return to your body.\n\r",ch);
			REMOVE_BIT(ch->extra,EXTRA_OSWITCH);}
			REMOVE_BIT(ch->affected_by,AFF_POLYMORPH);
			ch->morph = g_string_assign(ch->morph,"");
			char_from_room(ch);
			char_to_room(ch,get_room_index(ROOM_VNUM_ALTAR));
			if ( ( chobj = ch->pcdata->chobj ) != NULL )
				chobj->chobj = NULL;
			ch->pcdata->chobj = NULL;
			do_look(ch,"auto");
	}
	return;
}

/*
 * Aggress.
 *
 * for each mortal PC
 *     for each mob in room
 *         aggress on some random PC
 *
 * This function takes 25% to 35% of ALL Merc cpu time.
 * Unfortunately, checking on each PC move is too tricky,
 *   because we don't want the mob to just attack the first PC
 *   who leads the party into the room.
 *
 * -- Furey
 */
void aggr_update( void )
{
	CHAR_DATA *wch;
	CHAR_DATA *ch;
	CHAR_DATA *ch_next;
	CHAR_DATA *vch;
	CHAR_DATA *vch_next;
	CHAR_DATA *victim = NULL;
	OBJ_DATA *chobj = NULL;

	CHAR_DATA *wch_next;
	char buf[MAX_STRING_LENGTH];
	
	g_slist_foreach(descriptor_list,(GFunc)process_update_dlist,NULL);
	
	for ( wch = char_list; wch != NULL; wch = wch_next )
	{
		wch_next = wch->next;
		if ( IS_NPC(wch)
			|| ( wch->desc != NULL && wch->desc->connected != CON_PLAYING )
			||   wch->position <= POS_STUNNED
			||   wch->level >= LEVEL_IMMORTAL
			||   wch->pcdata == NULL
			||   wch->in_room == NULL
			|| ( ( chobj = wch->pcdata->chobj ) != NULL )
			||   wch->in_room == NULL )
			continue;

	   for ( ch = wch->in_room->people; ch != NULL; ch = ch_next )
		{
			int rnd_count;
			int count;
			
			ch_next	= ch->next_in_room;
			
			/* Trilby sez:  ACK! He found me! */
       		if ( IS_NPC(ch) && can_see(ch, wch) && is_same_plane(ch,wch))
           	{
          	    MEM_DATA *remember;
		    	if ( (remember = get_mem_data(ch, wch)) != NULL)
                {
                	if ( IS_SET(remember->reaction, MEM_AFRAID)
                   		&& IS_SET(ch->act, ACT_WIMPY)
                   		&& ch->wait < PULSE_VIOLENCE / 2
                   		&& ch->position == POS_STANDING
                   		&& number_bits(2) == 1)
						{
							str_cpy(buf,"Ack Run Away! Run Away!");
                 			do_say(ch,buf);
                       		do_flee(ch, "self");
							continue;
               	    	}
               	        if ( IS_SET(remember->reaction, MEM_HOSTILE)   
                     		&& ch->position == POS_STANDING
                     		&& ch->fighting == NULL )
                       	{
                       		rnd_count = number_range(0, MAX_REMEMBER);

                       		do_say(ch,remember_table[rnd_count].haunt);
                        	multi_hit(ch, wch, TYPE_UNDEFINED);
							continue;
                   		}
            	}
            }


			if ( wch->in_room == NULL || ch->in_room == NULL)
			{
				bug("Error in aggr_Update, null in->room BAH!",0);
				continue;
			}

			if (!hates_players(ch,wch))
				if ( !IS_NPC(ch)
					||   !IS_SET(ch->act, ACT_AGGRESSIVE)
					||   no_attack(ch, wch)
					||   ch->fighting != NULL
					||   IS_AFFECTED(ch, AFF_CHARM)
					||   !IS_AWAKE(ch)
					||   ( IS_SET(ch->act, ACT_WIMPY) && IS_AWAKE(wch) )
					||   !can_see( ch, wch ) )
					continue;
			
		/*
		 *   Check for them Leopald dudes... they hate people
         */
		
			if (hates_players(ch,wch) && is_same_plane(ch,wch))
			{
				if (IS_SET(ch->act,ACT_GUARD))
					do_say(ch,"MURDERER!");
				if (IS_SET(ch->act,ACT_ELITE))
					do_say(ch,"For the SOCIETY OF LEOPOLD! DIE INFIDEL!");
                
                multi_hit(ch, wch, TYPE_UNDEFINED);
				
				continue;
			}

	    /*
	     * Ok we have a 'wch' player character and a 'ch' npc aggressor.
	     * Now make the aggressor fight a RANDOM pc victim in the room,
	     *   giving each 'vch' an equal chance of selection.
	     */

			count	= 0;
			victim	= NULL;
			for ( vch = wch->in_room->people; vch != NULL; vch = vch_next )
			{
				vch_next = vch->next_in_room;
				
				if ( !IS_NPC(vch)
					&&   !no_attack(ch, vch)
					&&   vch->pcdata != NULL
					&& ( ( chobj = vch->pcdata->chobj ) == NULL )
					&&   vch->level < LEVEL_IMMORTAL
					&&   vch->position > POS_STUNNED
					&&   ( !IS_SET(ch->act, ACT_WIMPY) || !IS_AWAKE(vch) )
					&&   can_see( ch, vch ) )
				{
					if ( number_range( 0, count ) == 0 )
						victim = vch;
					count++;
				}
			}
			
     		if ( victim == NULL )
			{
				continue;
			}
			
			multi_hit( ch, victim, TYPE_UNDEFINED );
		}
	}
	//DEBUG
	check_both("ARRG_UPDATE");
	mudsetting->last_proc_logged = 89;
	return;
}


void caern_update( void )
{
	/* Check all the people in ROOM_VNUM_CAERN
	 * If wwf are there, including fenris then stop the regen
	 */
   ROOM_INDEX_DATA *location;
   CHAR_DATA *ch;
   CHAR_DATA *vch;
   bool wwf_found = FALSE;

   if ((location = get_room_index(ROOM_VNUM_CAERN)) == NULL)
   {
   		bug("Can't find caern!",0);
		return;
   }

   for (ch = location->people;ch != NULL;ch = ch->next_in_room)
   {
		if (IS_NPC(ch))
		{
			/*check for the fenris wolf */
			if (ch->pIndexData->vnum == MOB_VNUM_FENRIS)
				wwf_found = TRUE;
		}
		else
		{
			/*check for wolves*/
			if (IS_CLASS(ch,CLASS_WEREWOLF))
				wwf_found = TRUE;
		}
   }

   if (wwf_found)
   {
   	  for (vch = location->people;vch != NULL;vch = vch->next_in_room)
   	  {
		if (IS_SET(vch->act, ACT_TAPPING))
		{
   	  		REMOVE_BIT(vch->act, ACT_TAPPING);
   	  		send_to_char("Since there are garou's in the area you stop tapping the caern to deal with them.\n\r",vch);
		}
   	  }
   }
}
void process_caren_update(DESCRIPTOR_DATA *d,gpointer userdata)
{
	CHAR_DATA       *victim;
	float            dam = 0;

		if (!IS_PLAYING(d) || (victim = d->character) == NULL
			|| IS_NPC(victim) || IS_IMMORTAL(victim)
			|| victim->in_room == NULL || victim->pcdata->chobj != NULL
			|| IS_CLASS(victim,CLASS_WEREWOLF))
		{
			return;
		}
		if ( !IS_SET( d->character->in_room->room_flags, ROOM_BLADE_BARRIER ) )
			return;
		
		act( "The scattered blades on the ground fly up into the air ripping into you.", d->character, NULL, NULL, TO_CHAR );
		act( "The scattered blades on the ground fly up into the air ripping into $n.", d->character, NULL, NULL, TO_ROOM );
		
		act( "The blades drop to the ground inert.", d->character, NULL, NULL, TO_CHAR );
		act( "The blades drop to the ground inert.", d->character, NULL, NULL, TO_ROOM );
		
		dam = number_range( 7, 14 );
		dam = dam / 100;
		dam = d->character->hit * dam;
		if ( dam < 100 ) dam = 100;
		d->character->hit = d->character->hit - (int)dam;
		if ( d->character->hit < -10 ) d->character->hit = -10;
		update_pos( victim );
	return;
}

void ww_update( void )
{
	
	g_slist_foreach(descriptor_list,(GFunc)process_caren_update,NULL);
	return;
}
void room_update( void )
{   
	ROOM_INDEX_DATA *room;
	AFFECT_DATA *paf;
	AFFECT_DATA *paf_next;
	CHAR_DATA *rch;
	int iHash;
	for (iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
	{
		for ( room = room_index_hash[iHash]; room != NULL; room = room->next )
		{
		/* 
		 * First check all the affects per room and see if they are
		 * timed out yet.
		 */
			for ( paf = room->affected; paf != NULL; paf = paf_next )
			{
				paf_next	= paf->next;
				if ( paf->duration > 0 )
					paf->duration--;
				else if ( paf->duration <= 0 )
				{
					for ( rch  = room->people;
						rch != NULL;
						rch  = rch->next_in_room )
					{
						
						if ( IS_RAFFECTED(room, ROOM_AFF_SILENT ))
							act( "Complete and utter silence seems to fade.",rch,NULL,NULL,TO_CHAR);   
					}
					affect_remove_room( room, paf );
				}
			}
		    if ( HAS_PROG(room, TRIG_RANDOM) )
         	 rprog_percent_trigger(room, room->people, NULL, NULL, TRIG_RANDOM);
		   if ( HAS_PROG(room, TRIG_DELAY) )
         	 rprog_percent_trigger(room, room->people, NULL, NULL, TRIG_DELAY);
    	
    	
		}
	}
	return;
}

/*
 * 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_area;
	static  int     pulse_mobile;
	static  int     pulse_violence;
	static  int     pulse_point;
	char buf[MAX_STRING_LENGTH];
	CHAR_DATA *ch = NULL;
/*
    static  int     pulse_ww;

    if ( --pulse_ww       <= 0 )
    {
        pulse_ww        = PULSE_WW;
        ww_update       ( );
    }
*/
	
	if ( --pulse_area     <= 0 )
	{
		pulse_area	= number_range( PULSE_AREA / 2, 3 * PULSE_AREA / 2 );
		
		if ( copyover_set == TRUE && copyover_time > 0 )
		{
			copyover_time--;
			sprintf(buf,"{RMinutes until scheduled copyover: %d, Please save.{x",copyover_time);
			do_echo(ch,buf);
		}
		
		if ( copyover_set == TRUE && copyover_time == 0 )
			do_copyover(ch,"aasdf");
		
		check_both("Before area update");
		area_update	( );
		check_both("after area update");
	}
	
	if ( --pulse_mobile   <= 0 )
	{
		pulse_mobile	= PULSE_MOBILE;
		check_both("MObileupdate");
		mobile_update	( );
	}
	
	if ( --pulse_violence <= 0 )
	{
		pulse_violence	= PULSE_VIOLENCE;
		violence_update	( );
	}
	
	if ( --pulse_point    <= 0 )
	{
		check_both("Update Start");
		pulse_point     = number_range( PULSE_TICK / 2, 3 * PULSE_TICK / 2 );
		weather_update( );
		check_both("Before PLayer Update");
		char_update( );
		check_both("After Player Update");
		room_update( );
		quest_update( );
		check_both("Before WWf update");
		update_wwf( );
		check_both("After wwf update");
		obj_update( );
		caern_update( );
		check_both("Update End");
	}
	aggr_update( );
	tail_chain( );
	return;
}