alRom/bin/
alRom/data/class/
alRom/data/command/
alRom/data/guild/
alRom/data/help/
alRom/data/lang/
alRom/data/race/
alRom/data/religion/
alRom/data/skill/
alRom/note/
/* Event code */

#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <stdarg.h>
#include "include.h"

char *build_cmdevent []=
{	 "stop",
	 "face", 
	 "look",
	  NULL
};

char *busy_cmdevent []=
{	 "stop",
	 "look",
	 "retract",
	  NULL
};

EVENT_DATA *event_list;
EVENT_DATA *event_last;


void event_to_char(CHAR_DATA *ch, char *string, void *arg, int value, int type, int delay )
{	EVENT_DATA *event;

	event = event_new();
	event->ch	= ch;
	event->event = type;
	event->delay = delay * PULSE_PER_SECOND;
	event->value = value;
	event->type = TYPE_CHAR;
	event->arg = arg;
	event->string = str_dup(string);
	
	if(event_last)
		event_last->next = event;
	event_last = event;
	if(!event_list)
		event_list = event;
	
	if(ch->event_last)
		ch->event_last->next_event = event;
	ch->event_last = event;
	if(!ch->event_list)
		ch->event_list = event;
	return;
}
void event_to_obj(OBJ_DATA *obj, CHAR_DATA *ch, char *string, void *arg, int value, int type, int delay )
{	EVENT_DATA *event;

	event = event_new();
	event->obj	= obj;
	event->ch	= ch;
	event->event = type;
	event->delay = delay * PULSE_PER_SECOND;
	event->prev = obj->event_last;
	event->value = value;
	event->type = TYPE_OBJ;
	event->arg = arg;
	event->string = str_dup(string);
	
	if(event_last)
		event_last->next = event;
	event_last = event;
	if(!event_list)
		event_list = event;
	
	if(obj->event_last)
		obj->event_last->next_event = event;
	obj->event_last = event;
	if(!obj->event_list)
		obj->event_list = event;
	return;
}
int calc_damage( CHAR_DATA *ch, OBJ_DATA *crystal, int power );
int spell_lookup( const char *name );

void event_spelldam( CHAR_DATA *ch, CHAR_DATA *victim, int dt, const char *name )
{	OBJ_DATA *crystal;
	int dam;
	
	crystal = get_eq_char(ch, WEAR_WIELD )->embedded;
	dam = calc_damage(ch, crystal, 9);
	if(!str_cmp(name, "soul steal") )
		ch->hit += dam;
	if(!str_cmp(name, "heal") )
	{	victim->hit += dam;
		if(victim->hit > victim->max_hit)
			victim->hit = victim->max_hit;
	}
	else
	damage(ch, victim, dam, TYPE_SPELL+spell_lookup(name), dt, TRUE );
	return;
}

void event_mine_entrance(CHAR_DATA *ch, int door, SHAFT_DATA *pShaft )
{	MINE_DATA *pMine;
	
	if( ch->complete < 33 )
	{	send_to_char("You pull out your lumber, and tools, and begin work on the entrance.\n\r",ch);
		new_entrance(ch->in_room,  door, (*(ch->in_room->exit))[door],pMine, &pShaft );
		event_to_char(ch, END_CHAR, (void *) pShaft, door, BUILD_ENTRANCE, 5 );
		ch->complete = 34;
		pShaft->complete = 34;
		return;
	}

	if( ch->complete < 66 )
	{	send_to_char("You get a few feet into the rock, placing lumber around to form the frame as you go.\n\r",ch);
		event_to_char(ch, END_CHAR,  (void *) pShaft, door, BUILD_ENTRANCE, 5 );
		ch->complete = 70;
		pShaft->complete = 70;
		return;
	}

	if(ch->complete < 80 )
	{	send_to_char("Getting deeper, the frame begins to take form as an entrance to a new mine.\n\r",ch);
		event_to_char(ch, END_CHAR, (void *) pShaft,  door, BUILD_ENTRANCE, 5 );
		ch->complete = 98;
		pShaft->complete = 98;
		return;
	}
	if( ch->complete < 99 )
	{	send_to_char("As you kick away afew out of place pebbles, the entrance looks complete. You begin on the details.\n\r",ch);
		event_to_char(ch, END_CHAR, (void *) pShaft,  door, BUILD_ENTRANCE, 2 );
		ch->complete = 99;
		pShaft->complete = 99;
		return;
	}

	send_to_char("The entrance creeks for a moment, as you shift the last slab of lumber into place. Standing back, you feel a sense of accomplishment.\n\r",ch);
	ch->complete = 100;
	pShaft->complete = 100;
	return;
}
extern int move_dir[6][3];

void event_mine_shaft(CHAR_DATA *ch, int door, SHAFT_DATA *pShaft )
{	int new_x, new_y, new_z;

	if( ch->complete < 33 )
	{	send_to_char("You gather your remaining lumber, and begin work on the new mine shaft.\n\r",ch);
		new_x = ch->pcdata->cordinate[CORD_X] + move_dir[door][CORD_X];
		new_y = ch->pcdata->cordinate[CORD_Y] + move_dir[door][CORD_Y];
		new_z = ch->pcdata->cordinate[CORD_Z] + move_dir[door][CORD_Z];
		create_shaft(ch->pcdata->in_mine, ch->pcdata->in_shaft, &pShaft,door, new_x, new_y, new_z );
		event_to_char(ch, END_CHAR, (void *) pShaft, door, BUILD_SHAFT, 10 );
		ch->complete = 34;
		pShaft->complete = 34;
		return;
	}

	if( ch->complete < 66 )
	{	send_to_char("You clear the excess rubble away, and continue with your work.\n\r",ch);
		event_to_char(ch, END_CHAR, (void *) pShaft, door, BUILD_SHAFT, 10 );
		ch->complete = 67;
		pShaft->complete = 67;
		return;
	}

	if( ch->complete < 98 )
	{	send_to_char("You wipe sweat from your brow, as you bang a few more logs into place.\n\r",ch);
		event_to_char(ch, END_CHAR, (void *) pShaft, door, BUILD_SHAFT, 8 );
		ch->complete = 99;
		pShaft->complete = 99;
		return;
	}

	send_to_char("As you slam the last logs into place, as loud cracking sounds echos the mine.\n\r",ch);
	pShaft->complete = 100;
	ch->complete = 100;
	return;
}

void event_mine_link(CHAR_DATA *ch, int door, SHAFT_DATA *pShaft )
{	int new_x, new_y, new_z;

	if(ch->complete < 33 )
	{	event_to_char(ch, END_CHAR, (void *) pShaft, door, BUILD_LINK, 8 );
		send_to_char("You tap lightly on the rock face, finding the correct place to link the two shafts.\n\r",ch);
		ch->complete = 34;
		return;
	}

	if( ch->complete < 66 )
	{	send_to_char("Having found the correct spot, you land your pick axe into the rock, chipping, and hacking away.\n\r",ch);
		event_to_char(ch, END_CHAR, (void *) pShaft, door, BUILD_LINK, 6 );
		ch->complete = 67;
		return;
	}

	if( ch->complete < 98 )
	{	send_to_char("With a shattering swing of the pick axe, light peaks through a small crack in the wall. The shaft has been reached.\n\r",ch);
		event_to_char(ch, END_CHAR, (void *) pShaft, door, BUILD_LINK, 4 );
		ch->complete = 98;
		return;
	}
	new_x = ch->pcdata->cordinate[CORD_X] + move_dir[door][CORD_X];
	new_y = ch->pcdata->cordinate[CORD_Y] + move_dir[door][CORD_Y];
	new_z = ch->pcdata->cordinate[CORD_Z] + move_dir[door][CORD_Z];
	create_link(&pShaft, door, ch->pcdata->in_shaft);
	send_to_char("You bang the frame into the final position between the two shafts.\n\r",ch);
	ch->complete = 100;
	return;
}

void event_mine_mineral( CHAR_DATA *ch, int mineral )
{	ROOM_INDEX_DATA *pRoom;
	OBJ_DATA *ore;
	char buf[MSL];
	pRoom = ch->in_room;

	if( ch->complete < 33 )
	{	send_to_char( "You bang your tools vigorously against the ground, trying to find some minerals.\n\r", ch );
		event_to_char(ch, END_CHAR, NULL, mineral, EVENT_MINE, 5 );
		ch->complete = 34;
		return;
	}
	if(ch->complete < 98 )
	{	send_to_char( "You wipe the sweat from your brow, as the work becomes strenuous.\n\r",ch);
		event_to_char(ch, END_CHAR, NULL, mineral, EVENT_MINE, 5 );
		ch->complete = 99;
		return;
	}
	if( mineral != MIN_ALL )
	{	if(pRoom->mineral[mineral] <= 0 )
		{	send_to_char( "You didn't find a hint of the mineral\n\r", ch);
			ch->wait = 0;
			return;
		}
		if(number_range(0, 100 ) < pRoom->mineral[mineral] )
		{	sprintf(buf, "You found some %s.\n\r", mineral_table[mineral].name );
			act( buf, ch, NULL, NULL, TO_CHAR );
			ore = create_ore(pRoom, mineral );
			obj_to_char(ore, ch);
			return;
		}
		act( "Your search for minerals has turned up fruitless.\n\r", ch, NULL, NULL, TO_CHAR );
		return;
	}

	if(number_range(0, 100 ) < pRoom->mineral[mineral] )
	{	sprintf(buf, "You found some %s\n\r", mineral_table[mineral].name );
		send_to_char( buf, ch );
		return;
	}
	send_to_char( "Your search for minerals has turned up fruitless.\n\r", ch);
	return;
}
void event_charge( CHAR_DATA *ch, OBJ_DATA *crystal )
{	USE *use;
	int percent;
	static int last_percent;
	if( !( use = get_obj_use( crystal, UTYPE_CRYSTAL ) ) )
	{	send_to_char("This isn't a crystal.\n\r",ch);
		return;
	}

	if(use->value[2] >= use->value[1] )
	{	send_to_char("The crystal is fully charged.\n\r",ch);
		use->value[2] = use->value[1];
		return;
	}
	if( ch->mana == 0 )
	{	send_to_char ("Your out of mana!\n\r",ch);
		return;
	}
	ch->mana--;
	use->value[2]++;
	percent = (int)( ( (float)use->value[2] / (float)use->value[1] ) *100 );
	if(percent == 10 && last_percent != 10)
	{	send_to_char("The crystal begins to glow with a low glimmer.\n\r",ch);
		last_percent = 10;
	}
	else if (percent == 20 && last_percent != 20)
	{	send_to_char("The low glimmer of the crystal grows.\n\r",ch);
		last_percent = 20;
	}
	else if (percent == 40 && last_percent != 40)
	{	send_to_char("The crystal begins to glow softly.\n\r",ch);
		last_percent = 40;
	}
	else if (percent == 70 && last_percent != 70)
	{	send_to_char("The crystal glows brightly.\n\r",ch);
		last_percent = 70;
	}
	else if (percent == 90 && last_percent != 90)
	{	send_to_char("The crystal glows strongly, and hums.\n\r",ch);
		last_percent = 90;
	}
	event_to_char(ch, END_CHAR, (void *) crystal, 0, EVENT_CHARGE, 1 );
	return;
}
bool is_vowel( const char letter )
{	char vowels[5] = { 'a', 'e', 'i', 'o', 'u' };
	int i;
	for( i = 0; i < 5 ; i++ )
		if(vowels[i] == letter )
			return TRUE;
	return FALSE;
}

void event_style( OBJ_DATA *obj, CHAR_DATA *ch, int style, int shape )
{	char buf[MSL];
	int length;
	
	sprintf(buf, "%d", shape);
	if( obj->temp < material_table[obj->material].redTmp )
	{	send_to_char("Hammering an object that isn't atleast red hot will just break it.\n\r",ch);
		return;
	}
	if( obj->complete != 0 )
		ch->complete = obj->complete;
	if(ch->complete == 0)
	{	printf_to_char(ch, "You begin hammering out the soon to be %s blade.\n\r", bstyle_table[style].name);
		ch->complete = 33;
		obj->complete = 33;
		event_to_char(ch, buf, (void *) obj, style, EVENT_STYLE, 4 );
		return;
	}

	if( ch->complete < 33 )
	{	if( style == 0 )
			send_to_char("You pull and straighten out the ore, to fit the style of the blade.\n\r",ch);
		else
			send_to_char("You bend and contort the ore to your will, to fit your curved styled blade.\n\r",ch);
		ch->complete = 34;
		obj->complete = 34;
		event_to_char(ch, buf, (void *) obj, style, EVENT_STYLE, 4 );
		return;
	}

	if( ch->complete < 66 )
	{	if(style == 0 )
			send_to_char("The now straight blade begins to slowly take form as you hammer away at it.\n\r",ch);
		else
			send_to_char("The now curved blade begins to slowly take form as you hammer away at it.\n\r",ch);
		ch->complete = 67;
		obj->complete = 67;
		event_to_char(ch, buf, (void *) obj, style, EVENT_STYLE, 4 );
		return;
	}
	ch->complete = 0;
	if(shape < BTYPE_MAX)
		length = 0;
	else if(shape < BTYPE_MAX*2)
		length = 1;
	else
		length = 2;
	ch->complete = 0;
	obj->complete = 0;
	send_to_char("After the many folds and beatings of this ore, it finally takes shape into a dull blade.\n\r",ch);
	send_to_char("You begin hammering out the desired edge.\n\r",ch);
	sprintf(buf, "A%s %s, %s, %s", 
				 is_vowel(material_table[obj->material].name[0]) ? "n\0" : "",
				 material_table[obj->material].name,
				 bstyle_table[style].name,			 
				 forge_table[shape].name);
	event_to_char(ch, buf, (void *)obj, shape, BUILD_BLADE, 4 );
				 
	return;
}

void event_blade(CHAR_DATA *ch, OBJ_DATA *ore, char *description, int shape)
{	OBJ_DATA *blade;
	USE *use;
	int style;
	int length;
	int origshape = shape;
	if( ore->temp < material_table[ore->material].redTmp )
	{	send_to_char("Hammering an object that isn't atleast red hot will just break it.\n\r",ch);
		return;
	}
	if(shape >= BTYPE_MAX)
		shape -= BTYPE_MAX;
	if(shape >= BTYPE_MAX)
		shape -= BTYPE_MAX;
	if(ore->complete == 80 )
		ch->complete = 34;
	if(ore->complete == 90 )
		ch->complete = 78;
	if(shape == 0 )
	{	if(ch->complete < 33 )
		{	send_to_char("You begin hammering down both sides of the blade. Collapsing the folds in on themselves.\n\r",ch);
			ch->complete = 34;
			ore->complete = 80;
			event_to_char(ch, description, (void *)ore, origshape, BUILD_BLADE, 4 );
			return;
		}

		if( ch->complete < 77 )
		{	send_to_char("Visible edges begin to become apparent on both sides of the blade as the hammering continues.\n\r",ch);
			ch->complete = 78;
			ore->complete = 90;
			event_to_char(ch, description, (void *) ore, origshape, BUILD_BLADE, 4 );
			return;
		}
		blade = create_object(get_obj_index(OBJ_VNUM_BLADE ), ch->level );
		use = get_obj_use(blade, UTYPE_BLADE);
		if(strstr(description, "straight" ) )
			style = 0;
		else
			style = 1;
		if(origshape < BTYPE_MAX)
			length = 0;
		else if(origshape < BTYPE_MAX*2)
			length = 1;
		else
			length = 2;
		use->value[0] = origshape;
		use->value[1] = style;
		use->value[2] = length;
		send_to_char("You file down the edges on either side, sharpening them to a fine edge.\n\r",ch);
		free_string(blade->short_descr);
		blade->short_descr = str_dup(description);
		ch->complete = 100;
		ore->complete = 100;
		extract_obj(ore);
		obj_to_char(blade, ch);

		return;
	}
	if(shape == 1 )
	{	if(ch->complete < 33 )
		{	send_to_char("You begin hammering down the inside edge of the blade. Collapsing the folds in on themselves.\n\r",ch);
			ch->complete = 34;
			ore->complete = 80;
			event_to_char(ch, description, (void *)ore, origshape, BUILD_BLADE, 4 );
			return;
		}

		if( ch->complete < 77 )
		{	send_to_char("a visible edge become apparent on the inside of the blade as the hammering continues.\n\r",ch);
			ch->complete = 78;
			ore->complete = 90;
			event_to_char(ch, description, (void *) ore, origshape, BUILD_BLADE, 4 );
			return;
		}
		blade = create_object(get_obj_index(OBJ_VNUM_BLADE ), ch->level );
		use = get_obj_use(blade, UTYPE_BLADE);
		if(strstr(description, "straight" ) )
			style = 0;
		else
			style = 1;
		if(origshape < BTYPE_MAX)
			length = 0;
		else if(origshape < BTYPE_MAX*2)
			length = 1;
		else
			length = 2;
		use->value[0] = origshape;
		use->value[1] = style;
		use->value[2] = length;
		send_to_char("You file down the edge on the inside, sharpening it to a fine edge.\n\r",ch);
		free_string(blade->short_descr);
		blade->short_descr = str_dup(description);
		ch->complete = 100;
		ore->complete = 100;
		extract_obj(ore);
		obj_to_char(blade, ch);
		return;
	}
	if(shape == 2 )
	{	if(ch->complete < 33 )
		{	send_to_char("You begin hammering down the outside edge of the blade. Collapsing the folds in on themselves.\n\r",ch);
			ch->complete = 34;
			ore->complete = 80;
			event_to_char(ch, description, (void *)ore, origshape, BUILD_BLADE, 4 );
			return;
		}

		if( ch->complete < 77 )
		{	send_to_char("A visible edge begin to become apparent on the outside of the blade as the hammering continues.\n\r",ch);
			ch->complete = 78;
			ore->complete = 90;
			event_to_char(ch, description, (void *) ore, origshape, BUILD_BLADE, 4 );
			return;
		}
		blade = create_object(get_obj_index(OBJ_VNUM_BLADE ), ch->level );
		use = get_obj_use(blade, UTYPE_BLADE);
		if(strstr(description, "straight" ) )
			style = 0;
		else
			style = 1;
		if(origshape < BTYPE_MAX)
			length = 0;
		else if(origshape < BTYPE_MAX*2)
			length = 1;
		else
			length = 2;
		use->value[0] = origshape;
		use->value[1] = style;
		use->value[2] = length;
		send_to_char("You file down the edge on the outside, sharpening it to a fine edge.\n\r",ch);
		free_string(blade->short_descr);
		blade->short_descr = str_dup(description);
		ch->complete = 100;
		ore->complete = 100;
		extract_obj(ore);
		obj_to_char(blade, ch);
		return;
	}
	if(shape == 3 )
	{	if(ch->complete < 33 )
		{	send_to_char("You begin hammering down one side of the straight blade. Collapsing the folds in on themselves.\n\r",ch);
			ch->complete = 34;
			ore->complete = 80;
			event_to_char(ch, description, (void *)ore, origshape, BUILD_BLADE, 4 );
			return;
		}

		if( ch->complete < 77 )
		{	send_to_char("A visible edge becomes apparent on the blades as the hammering continues.\n\r",ch);
			ch->complete = 78;
			ore->complete = 90;
			event_to_char(ch, description, (void *) ore, origshape, BUILD_BLADE, 4 );
			return;
		}
		blade = create_object(get_obj_index(OBJ_VNUM_BLADE ), ch->level );
		use = get_obj_use(blade, UTYPE_BLADE);
		if(strstr(description, "straight" ) )
			style = 0;
		else
			style = 1;
		if(origshape < BTYPE_MAX)
			length = 0;
		else if(origshape < BTYPE_MAX*2)
			length = 1;
		else
			length = 2;
		use->value[0] = origshape;
		use->value[1] = style;
		use->value[2] = length;
		send_to_char("You file down the edge, sharpening it to a fine edge.\n\r",ch);
		free_string(blade->short_descr);
		blade->short_descr = str_dup(description);
		ch->complete = 100;
		ore->complete = 100;
		extract_obj(ore);
		obj_to_char(blade, ch);
		return;
	}
	return;
}

void event_int_hilt( OBJ_DATA *blade, CHAR_DATA *ch)
{	OBJ_DATA *sword;
	char buf[MSL];
	USE *use;

	if( ch->complete < 33 )
	{	printf_to_char(ch, "You hammer away at %s turning it ever so slightly as you make your way around the blade.\n\r", blade->short_descr );
		ch->complete = 34;
		event_to_char(ch, END_CHAR, (void *) blade, 0, EVENT_INT_HILT, 4 );
		return;
	}

	if( ch->complete < 66 )
	{	send_to_char("You hammer away at it more, as the hilt slowly begins to take form.\n\r",ch);
		ch->complete = 67;
		event_to_char(ch, END_CHAR, (void *) blade, 0, EVENT_INT_HILT, 4 );
		return;
	}

	if( ch->complete < 90 )
	{	send_to_char("You hit it for the last time, and give it a quick rub down, and gaze at the glory of your newly formed sword.\n\r",ch);
		sword = create_object( get_obj_index(OBJ_VNUM_SCHOOL_SWORD), ch->level);
		use = get_obj_use(blade, UTYPE_BLADE);
		sprintf(buf, "A%s %s %s, with a %s %s",
						 is_vowel(material_table[blade->material].name[0]) ? "n\0" : "",
						 material_table[blade->material].name,
						 blength_table[use->value[2]].desc,
						 bstyle_table[use->value[1]].name,
						 forge_table[use->value[0]].desc);
		free_string(sword->short_descr);
		sword->short_descr = str_dup(buf);
		free_string(sword->description );
		sword->description = str_dup(buf);
		free_string(sword->name);
		sword->name = str_dup(buf);
		extract_obj(blade);
		obj_to_char(sword,ch);
		ch->complete = 100;
		return;
	}
	return;
}



void update_obj_state( OBJ_DATA *, int, int, bool, bool );
void event_heat_obj(OBJ_DATA *obj, CHAR_DATA *holder, OBJ_DATA *furnace )
{	int origTmp = obj->temp;
	int ave;

	if(furnace->temp > obj->temp)
		obj->temp += 10;
	else
		obj->temp--;

	update_obj_state(obj, origTmp, obj->temp, TRUE, TRUE );
	ave = material_table[obj->material].smeltTmp - material_table[obj->material].meltTmp;
	ave /= 2;

	if(obj->temp >= material_table[obj->material].meltTmp + ave)
	{	printf_to_char(holder, "%s melts in %s and is lost!", obj->short_descr, furnace->short_descr );
		extract_obj(obj);
		purge_all_events(holder);
		return;
	}
	event_to_obj(obj, holder, END_CHAR, furnace,0, EVENT_HEAT_OBJ, 3);
	
	return;
}

void event_genbeast( CHAR_DATA *to, CHAR_DATA *beast )
{	char_to_room(beast, to->in_room);
	beast->master = to;
	return;
}

void purge_all_events(CHAR_DATA *ch)
{	EVENT_DATA *event, *event_next;
	
	for( event = ch->event_list; event ; event = event_next )
	{	event_next = event->next_event;
		free_event(ch,NULL, event);
	}
	return;
}

void purge_obj_events(OBJ_DATA *pObj)
{	EVENT_DATA *event, *event_next;
	
	for( event = pObj->event_list; event ; event = event_next )
	{	event_next = event->next_event;
		free_event(NULL,pObj, event);
	}
	return;
}
void event_update()
{	EVENT_DATA *event, *event_next;

	for( event = event_list; event ; event = event_next )
	{	event->delay--;
		event_next = event->next; // We'll have this, cause after an event is executed, its freed
		if(event->delay <= 0 )
		{	if(event->type == TYPE_CHAR )
				execute_char_event(event->ch, event);
			else
				execute_obj_event(event->obj, event);
		}
	}
	return;
}

void execute_char_event(CHAR_DATA * ch, EVENT_DATA * event)
{	switch(event->event )
	{	case EVENT_PRINT:
			send_to_char(event->string,ch);
			break;
		case BUILD_ENTRANCE:
			event_mine_entrance(ch, event->value, (SHAFT_DATA *)event->arg );
			break;
		case BUILD_SHAFT:
			event_mine_shaft(ch, event->value, (SHAFT_DATA *) event->arg );
			break;
		case BUILD_LINK:
			event_mine_link(ch, event->value, (SHAFT_DATA *) event->arg);
			break;
		case EVENT_MINE:
			event_mine_mineral(ch, event->value );
			break;
		case EVENT_BUSY:
			event_to_char(ch,END_CHAR, NULL, 0, EVENT_BUSY, 100 );
			break;
		case EVENT_CHARGE:
			event_charge(ch, (OBJ_DATA *) event->arg );
			break;
		case EVENT_SPELLDAM:
			event_spelldam(ch, (CHAR_DATA *)event->arg, event->value, event->string);
			break;
		case EVENT_GENBEAST:
			event_genbeast(ch, (CHAR_DATA *)event->arg);
			break;
		case EVENT_STYLE:
			event_style((OBJ_DATA *)event->arg, ch, event->value, atoi(event->string) );
			break;
		case BUILD_BLADE:
			event_blade( ch,(OBJ_DATA *)event->arg, event->string, event->value);
			break;
		case EVENT_INT_HILT:
			event_int_hilt( (OBJ_DATA *)event->arg, ch );
			break;
		default:
			logf2("Execute_event: Bad event type" );
			break;
	}
	free_event(ch, NULL, event);
	return;
}

void execute_obj_event( OBJ_DATA *pObj, EVENT_DATA *event )
{	switch(event->event)
	{	case EVENT_HEAT_OBJ:
			event_heat_obj(pObj, event->ch, (OBJ_DATA *)event->arg);
		default:
			logf2("Execute_obj_event: bad event type");
			break;
	}
	free_event(NULL, pObj, event);
	return;
}

EVENT_DATA *get_specific_event( CHAR_DATA *ch, int type )
{	EVENT_DATA *event;
	if(!HAS_EVENT(ch) )
		return NULL;

	for(event = ch->event_list; event ; event = event->next )
	{	if(event->event == type )
			return event;
	}
	return NULL;
}

EVENT_DATA *get_obj_event( OBJ_DATA *pObj, int type )
{	EVENT_DATA *event;
	if(!HAS_EVENT(pObj) )
		return NULL;

	for(event = pObj->event_list; pObj ; pObj = pObj->next )
	{	if(event->event == type )
			return event;
	}
	return NULL;
}

int event_lookup(EVENT_DATA *event )
{	int i;
	for( i = 0; event_table[i].name != NULL ; i++ )
	{	if(event_table[i].event == event->event )
			return i;
	}
	return -1;
}

bool check_eventcmd(CHAR_DATA *ch, char *cmd )
{	EVENT_DATA *event;
	int iEvent, iCmd;

	for( event = ch->event_list ; event ; event = event->next )
	{	if( (iEvent = event_lookup(event) ) == -1 )
		{	logf2("Check_eventcmd: Bad Event! %d\n", event->event );
			return FALSE;
		}
		for(iCmd = 0; event_table[iEvent].cmdlist[iCmd] != NULL; iCmd++ )
		{	if(!str_cmp(event_table[iEvent].cmdlist[iCmd], cmd ) )
				return TRUE;
		}
	}
	return FALSE;
}


const struct event_type event_table[] =
{	{ "entrance",	BUILD_ENTRANCE, build_cmdevent	},
	{ "shaft",		BUILD_SHAFT,	build_cmdevent	},
	{ "link",		BUILD_LINK,		build_cmdevent	},
	{ "mine",		EVENT_MINE,		build_cmdevent	},
	{ "busy",		EVENT_BUSY,		busy_cmdevent	},
	{ NULL,			0,				NULL			}
};

EVENT_DATA		*		event_free;
EVENT_DATA *event_new()
{	EVENT_DATA *event;
	if(!event_free)
		event = (EVENT_DATA *) alloc_perm(sizeof(*event) );
	else
	{	event = event_free;
		event_free = event_free->next;
	}

	free_string(event->string );
	event->delay = -1;
	event->event = 0;
	event->next = NULL;
	return event;
}

void free_event(CHAR_DATA *ch, OBJ_DATA *pObj, EVENT_DATA *event )
{	EVENT_DATA *tmp;
	bool found = FALSE;
	event->delay = -1;
	free_string(event->string);
	
	if(ch)
	{	if(event == ch->event_list)
		{	ch->event_list = event->next_event;
			found = TRUE;
		}
		if(ch->event_last == event)
		{	if(!ch->event_list)
				ch->event_last = NULL;
			else
				for(tmp = ch->event_list ; tmp ; tmp = tmp->next_event )
					if(tmp->next_event == event )
						ch->event_last = tmp;
			found = TRUE;
		}
		if(!found)
			for( tmp = ch->event_list ; tmp ; tmp = tmp->next_event )
			{	if(tmp->next_event == event)
				tmp->next_event = event->next_event;
			}
	}
	found = FALSE;
	if(pObj)
	{	if(event == pObj->event_list)
		{	pObj->event_list = event->next_event;
			found = TRUE;
		}
		if(pObj->event_last == event)
		{	if(!pObj->event_list)
				pObj->event_last = NULL;
			else
				for(tmp = pObj->event_list ; tmp ; tmp = tmp->next_event )
					if(tmp->next_event == event )
						pObj->event_last = tmp;
			found = TRUE;
		}
		if(!found)
		for( tmp = pObj->event_list ; tmp ; tmp = tmp->next_event )
		{	if(tmp->next_event == event)
				tmp->next_event = event->next_event;
		}
	}
	found = FALSE;
	if( event == event_list )
	{	event_list = event->next;
		found = TRUE;
	}
	if( event == event_last )
	{	if(!event_list)
			event_last = NULL;
		else 
			for( tmp = event_list ; tmp ; tmp = tmp->next )
				if(tmp->next == event)
					tmp->next = event->next;
		return;
	}
	if(!found)
		for(tmp = event_list ; tmp ; tmp = tmp->next )
			if(tmp->next == event )
				tmp->next = event->next;
	event->next = event_free;
	event_free = event;
	event->next_event = NULL;
	return;
}