Events/
/* Event code by Davion of MudBytes.net */

#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 "merc.h"

EVENT_DATA *event_list;
EVENT_DATA *event_last;

void eprintf_to_char( CHAR_DATA *ch, int delay, char *fmt, ... )
{	char buf [MSL];
	va_list args;
	va_start (args, fmt);
	vsnprintf(buf, MSL, fmt, args);
	va_end (args);
	event_to_char(ch, buf, NULL, 0, EVENT_PRINT, delay);
	return;
}

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;
	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;
	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;
}

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;
		default:
			log_string("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)
	{	default:
			log_string("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 )
		{	log_string("Check_eventcmd: Bad Event!\n");
			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[] =
{	{ 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;
}