Example #1
0
/*
================
idEvent::CancelEvents
================
*/
void idEvent::CancelEvents( const idClass *obj, const idEventDef *evdef ) {
	idEvent *event;
	idEvent *next;

	if ( !initialized ) {
		return;
	}

	for( event = EventQueue.Next(); event != NULL; event = next ) {
		next = event->eventNode.Next();
		if ( event->object == obj ) {
			if ( !evdef || ( evdef == event->eventdef ) ) {
				event->Free();
			}
		}
	}

#ifdef _D3XP
	for( event = FastEventQueue.Next(); event != NULL; event = next ) {
		next = event->eventNode.Next();
		if ( event->object == obj ) {
			if ( !evdef || ( evdef == event->eventdef ) ) {
				event->Free();
			}
		}
	}
#endif
}
Example #2
0
/*
================
idEvent::Schedule
================
*/
void idEvent::Schedule( idClass* obj, const idTypeInfo* type, int time )
{
	idEvent* event;
	
	assert( initialized );
	if( !initialized )
	{
		return;
	}
	
	object = obj;
	typeinfo = type;
	
	// wraps after 24 days...like I care. ;)
	this->time = gameLocal.time + time;
	
	eventNode.Remove();
	
	if( obj->IsType( idEntity::Type ) && ( ( ( idEntity* )( obj ) )->timeGroup == TIME_GROUP2 ) )
	{
		event = FastEventQueue.Next();
		while( ( event != NULL ) && ( this->time >= event->time ) )
		{
			event = event->eventNode.Next();
		}
		
		if( event )
		{
			eventNode.InsertBefore( event->eventNode );
		}
		else
		{
			eventNode.AddToEnd( FastEventQueue );
		}
		
		return;
	}
	else
	{
		this->time = gameLocal.slow.time + time;
	}
	
	event = EventQueue.Next();
	while( ( event != NULL ) && ( this->time >= event->time ) )
	{
		event = event->eventNode.Next();
	}
	
	if( event )
	{
		eventNode.InsertBefore( event->eventNode );
	}
	else
	{
		eventNode.AddToEnd( EventQueue );
	}
}
Example #3
0
/*
================
idEvent::Schedule
================
*/
void idEvent::Schedule( idClass *obj, const idTypeInfo *type, int time ) {
	idEvent *event;

	assert( initialized );
	if ( !initialized ) {
		return;
	}

	object = obj;
	typeinfo = type;

	// wraps after 24 days...like I care. ;)
	this->time = gameLocal.time + time;

	eventNode.Remove();

	event = EventQueue.Next();
	while( ( event != NULL ) && ( this->time >= event->time ) ) {
		event = event->eventNode.Next();
	}

	if ( event ) {
		eventNode.InsertBefore( event->eventNode );
	} else {
		eventNode.AddToEnd( EventQueue );
	}
}
Example #4
0
/*
================
idEvent::Save
================
*/
void idEvent::Save( idSaveGame *savefile ) {
	char *str;
	int i, size;
	idEvent	*event;
	byte *dataPtr;
	bool validTrace;
	const char	*format;

	savefile->WriteInt( EventQueue.Num() );

	event = EventQueue.Next();
	while( event != NULL ) {
		savefile->WriteInt( event->time );
		savefile->WriteString( event->eventdef->GetName() );
		savefile->WriteString( event->typeinfo->classname );
		savefile->WriteObject( event->object );
		savefile->WriteInt( event->eventdef->GetArgSize() );
		format = event->eventdef->GetArgFormat();
		for ( i = 0, size = 0; i < event->eventdef->GetNumArgs(); ++i) {
			dataPtr = &event->data[ event->eventdef->GetArgOffset( i ) ];
			switch( format[ i ] ) {
				case D_EVENT_FLOAT :
					savefile->WriteFloat( *reinterpret_cast<float *>( dataPtr ) );
					size += sizeof( float );
					break;
				case D_EVENT_INTEGER :
				case D_EVENT_ENTITY :
				case D_EVENT_ENTITY_NULL :
					savefile->WriteInt( *reinterpret_cast<int *>( dataPtr ) );
					size += sizeof( int );
					break;
				case D_EVENT_VECTOR :
					savefile->WriteVec3( *reinterpret_cast<idVec3 *>( dataPtr ) );
					size += sizeof( idVec3 );
					break;
				case D_EVENT_TRACE :
					validTrace = *reinterpret_cast<bool *>( dataPtr );
					savefile->WriteBool( validTrace );
					size += sizeof( bool );
					if ( validTrace ) {
						size += sizeof( trace_t );
						const trace_t &t = *reinterpret_cast<trace_t *>( dataPtr + sizeof( bool ) );
						SaveTrace( savefile, t );
						if ( t.c.material ) {
							size += MAX_STRING_LEN;
							str = reinterpret_cast<char *>( dataPtr + sizeof( bool ) + sizeof( trace_t ) );
							savefile->Write( str, MAX_STRING_LEN );
						}
					}
					break;
				default:
					break;
			}
		}
		assert( size == event->eventdef->GetArgSize() );
		event = event->eventNode.Next();
	}
}
Example #5
0
/*
================
idEvent::Restore
================
*/
void idEvent::Restore( idRestoreGame *savefile ) {
	int		i;
	int		num;
	int		argsize;
	idStr	name;
	idEvent	*event;

	savefile->ReadInt( num );

	for ( i = 0; i < num; i++ ) {
		if ( FreeEvents.IsListEmpty() ) {
			gameLocal.Error( "idEvent::Restore : No more free events" );
		}

		event = FreeEvents.Next();
		event->eventNode.Remove();
		event->eventNode.AddToEnd( EventQueue );

		savefile->ReadInt( event->time );

		// read the event name
		savefile->ReadString( name );
		event->eventdef = idEventDef::FindEvent( name );
		if ( !event->eventdef ) {
			savefile->Error( "idEvent::Restore: unknown event '%s'", name.c_str() );
		}

		// read the classtype
		savefile->ReadString( name );
		event->typeinfo = idClass::GetClass( name );
		if ( !event->typeinfo ) {
			savefile->Error( "idEvent::Restore: unknown class '%s' on event '%s'", name.c_str(), event->eventdef->GetName() );
		}

		savefile->ReadObject( event->object );
		assert( event->object );

		// read the args
		savefile->ReadInt( argsize );
		if ( argsize != event->eventdef->GetArgSize() ) {
			savefile->Error( "idEvent::Restore: arg size (%d) doesn't match saved arg size(%d) on event '%s'", event->eventdef->GetArgSize(), argsize, event->eventdef->GetName() );
		}
		if ( argsize ) {
			event->data = eventDataAllocator.Alloc( argsize );
			savefile->Read( event->data, argsize );
		} else {
			event->data = NULL;
		}
	}
}
Example #6
0
/*
================
idEvent::Save
================
*/
void idEvent::Save( idSaveGame *savefile ) {
	idEvent	*event;

	savefile->WriteInt( EventQueue.Num() );

	event = EventQueue.Next();
	while( event != NULL ) {
		savefile->WriteInt( event->time );
		savefile->WriteString( event->eventdef->GetName() );
		savefile->WriteString( event->typeinfo->classname );
		savefile->WriteObject( event->object );
		savefile->WriteInt( event->eventdef->GetArgSize() );
		savefile->Write( event->data, event->eventdef->GetArgSize() );

		event = event->eventNode.Next();
	}
}
Example #7
0
/*
================
idEvent::EventIsPosted
================
*/
bool idEvent::EventIsPosted( const idClass *obj, const idEventDef *evdef ) {
	idEvent *event;
	idEvent *next;

	if ( !initialized ) {
		return false;
	}

	for( event = EventQueue.Next(); event != NULL; event = next ) {
		next = event->eventNode.Next();
		if( event->object == obj && evdef == event->eventdef ) {
			return true;
		}
	}

	return false;
}
Example #8
0
void idEvent::WriteDebugInfo( void ) {
	idEvent	*event;
	int		count = 0;

	idFile *FH = fileSystem->OpenFileAppend( "idEvents.txt" );

	FH->Printf( "Num Events = %d\n", EventQueue.Num() );

	event = EventQueue.Next();
	while( event != NULL ) {
		count++;

		FH->Printf( "%d. %d - %s - %s - %s\n", count, event->time, event->eventdef->GetName(), event->typeinfo->classname, event->object->GetClassname() );

		event = event->eventNode.Next();
	}

	FH->Printf( "\n\n" );
	fileSystem->CloseFile( FH );
}
Example #9
0
/*
================
idEvent::Restore
================
*/
void idEvent::Restore( idRestoreGame *savefile ) {
	char    *str;
	int		num, argsize, i, j, size;
	idStr	name;
	byte *dataPtr;
	idEvent	*event;
	const char	*format;

	savefile->ReadInt( num );

	for ( i = 0; i < num; i++ ) {
		if ( FreeEvents.IsListEmpty() ) {
			gameLocal.Error( "idEvent::Restore : No more free events" );
		}

		event = FreeEvents.Next();
		event->eventNode.Remove();
		event->eventNode.AddToEnd( EventQueue );

		savefile->ReadInt( event->time );

		// read the event name
		savefile->ReadString( name );
		event->eventdef = idEventDef::FindEvent( name );
		if ( !event->eventdef ) {
			savefile->Error( "idEvent::Restore: unknown event '%s'", name.c_str() );
		}

		// read the classtype
		savefile->ReadString( name );
		event->typeinfo = idClass::GetClass( name );
		if ( !event->typeinfo ) {
			savefile->Error( "idEvent::Restore: unknown class '%s' on event '%s'", name.c_str(), event->eventdef->GetName() );
		}

		savefile->ReadObject( event->object );

		// read the args
		savefile->ReadInt( argsize );
		if ( ((size_t)argsize) != event->eventdef->GetArgSize() ) {
			savefile->Error( "idEvent::Restore: arg size (%d) doesn't match saved arg size(%d) on event '%s'", event->eventdef->GetArgSize(), argsize, event->eventdef->GetName() );
		}
		if ( argsize ) {
			event->data = eventDataAllocator.Alloc( argsize );
			format = event->eventdef->GetArgFormat();
			assert( format );
			for ( j = 0, size = 0; j < event->eventdef->GetNumArgs(); ++j) {
				dataPtr = &event->data[ event->eventdef->GetArgOffset( j ) ];
				switch( format[ j ] ) {
					case D_EVENT_FLOAT :
						savefile->ReadFloat( *reinterpret_cast<float *>( dataPtr ) );
						size += sizeof( float );
						break;
					case D_EVENT_INTEGER :
					case D_EVENT_ENTITY :
					case D_EVENT_ENTITY_NULL :
						savefile->ReadInt( *reinterpret_cast<int *>( dataPtr ) );
						size += sizeof( int );
						break;
					case D_EVENT_VECTOR :
						savefile->ReadVec3( *reinterpret_cast<idVec3 *>( dataPtr ) );
						size += sizeof( idVec3 );
						break;
					case D_EVENT_TRACE :
						savefile->ReadBool( *reinterpret_cast<bool *>( dataPtr ) );
						size += sizeof( bool );
						if ( *reinterpret_cast<bool *>( dataPtr ) ) {
							size += sizeof( trace_t );
							trace_t &t = *reinterpret_cast<trace_t *>( dataPtr + sizeof( bool ) );
							RestoreTrace( savefile,  t) ;
							if ( t.c.material ) {
								size += MAX_STRING_LEN;
								str = reinterpret_cast<char *>( dataPtr + sizeof( bool ) + sizeof( trace_t ) );
								savefile->Read( str, MAX_STRING_LEN );
							}
						}
						break;
					default:
						break;
				}
			}
			assert( size == event->eventdef->GetArgSize() );
		} else {
			event->data = NULL;
		}
	}
}
Example #10
0
/*
================
idEvent::ServiceEvents
================
*/
void idEvent::ServiceEvents( void ) {
	idEvent		*event;
	int			num;
	int			args[ D_EVENT_MAXARGS ];
	int			offset;
	int			i;
	int			numargs;
	const char	*formatspec;
	trace_t		**tracePtr;
	const idEventDef *ev;
	byte		*data;
	const char  *materialName;

	num = 0;
	while( !EventQueue.IsListEmpty() ) {
		event = EventQueue.Next();
		assert( event );

		if ( event->time > gameLocal.time ) {
			break;
		}

		// copy the data into the local args array and set up pointers
		ev = event->eventdef;
		formatspec = ev->GetArgFormat();
		numargs = ev->GetNumArgs();
		for( i = 0; i < numargs; i++ ) {
			offset = ev->GetArgOffset( i );
			data = event->data;
			switch( formatspec[ i ] ) {
			case D_EVENT_FLOAT :
			case D_EVENT_INTEGER :
				args[ i ] = *reinterpret_cast<int *>( &data[ offset ] );
				break;

			case D_EVENT_VECTOR :
				*reinterpret_cast<idVec3 **>( &args[ i ] ) = reinterpret_cast<idVec3 *>( &data[ offset ] );
				break;

			case D_EVENT_STRING :
				*reinterpret_cast<const char **>( &args[ i ] ) = reinterpret_cast<const char *>( &data[ offset ] );
				break;

			case D_EVENT_ENTITY :
			case D_EVENT_ENTITY_NULL :
				*reinterpret_cast<idEntity **>( &args[ i ] ) = reinterpret_cast< idEntityPtr<idEntity> * >( &data[ offset ] )->GetEntity();
				break;

			case D_EVENT_TRACE :
				tracePtr = reinterpret_cast<trace_t **>( &args[ i ] );
				if ( *reinterpret_cast<bool *>( &data[ offset ] ) ) {
					*tracePtr = reinterpret_cast<trace_t *>( &data[ offset + sizeof( bool ) ] );

					if ( ( *tracePtr )->c.material != NULL ) {
						// look up the material name to get the material pointer
						materialName = reinterpret_cast<const char *>( &data[ offset + sizeof( bool ) + sizeof( trace_t ) ] );
						( *tracePtr )->c.material = declManager->FindMaterial( materialName, true );
					}
				} else {
					*tracePtr = NULL;
				}
				break;

			default:
				gameLocal.Error( "idEvent::ServiceEvents : Invalid arg format '%s' string for '%s' event.", formatspec, ev->GetName() );
			}
		}

		// the event is removed from its list so that if then object
		// is deleted, the event won't be freed twice
		event->eventNode.Remove();
		assert( event->object );
		event->object->ProcessEventArgPtr( ev, args );

#if 0
		// event functions may never leave return values on the FPU stack
		// enable this code to check if any event call left values on the FPU stack
		if ( !sys->FPU_StackIsEmpty() ) {
			gameLocal.Error( "idEvent::ServiceEvents %d: %s left a value on the FPU stack\n", num, ev->GetName() );
		}
#endif

		// return the event to the free list
		event->Free();

		// Don't allow ourselves to stay in here too long.  An abnormally high number
		// of events being processed is evidence of an infinite loop of events.
		num++;
		if ( num > MAX_EVENTSPERFRAME ) {
			gameLocal.Error( "Event overflow.  Possible infinite loop in script." );
		}
	}
}
Example #11
0
/*
================
idEvent::Alloc
================
*/
idEvent *idEvent::Alloc( const idEventDef *evdef, int numargs, va_list args ) {
	idEvent		*ev;
	size_t		size;
	const char	*format;
	idEventArg	*arg;
	byte		*dataPtr;
	int			i;
	const char	*materialName;

	if ( FreeEvents.IsListEmpty() ) {
		gameLocal.Error( "idEvent::Alloc : No more free events" );
	}

	ev = FreeEvents.Next();
	ev->eventNode.Remove();

	ev->eventdef = evdef;

	if ( numargs != evdef->GetNumArgs() ) {
		gameLocal.Error( "idEvent::Alloc : Wrong number of args for '%s' event.", evdef->GetName() );
	}

	size = evdef->GetArgSize();
	if ( size ) {
		ev->data = eventDataAllocator.Alloc( size );
		memset( ev->data, 0, size );
	} else {
		ev->data = NULL;
	}

	format = evdef->GetArgFormat();
	for( i = 0; i < numargs; i++ ) {
		arg = va_arg( args, idEventArg * );
		if ( format[ i ] != arg->type ) {
			// when NULL is passed in for an entity, it gets cast as an integer 0, so don't give an error when it happens
			if ( !( ( ( format[ i ] == D_EVENT_TRACE ) || ( format[ i ] == D_EVENT_ENTITY ) ) && ( arg->type == 'd' ) && ( arg->value == 0 ) ) ) {
				gameLocal.Error( "idEvent::Alloc : Wrong type passed in for arg # %d on '%s' event.", i, evdef->GetName() );
			}
		}

		dataPtr = &ev->data[ evdef->GetArgOffset( i ) ];

		switch( format[ i ] ) {
		case D_EVENT_FLOAT :
		case D_EVENT_INTEGER :
			*reinterpret_cast<int *>( dataPtr ) = arg->value;
			break;

		case D_EVENT_VECTOR :
			if ( arg->value ) {
				*reinterpret_cast<idVec3 *>( dataPtr ) = *reinterpret_cast<const idVec3 *>( arg->value );
			}
			break;

		case D_EVENT_STRING :
			if ( arg->value ) {
				idStr::Copynz( reinterpret_cast<char *>( dataPtr ), reinterpret_cast<const char *>( arg->value ), MAX_STRING_LEN );
			}
			break;

		case D_EVENT_ENTITY :
		case D_EVENT_ENTITY_NULL :
			*reinterpret_cast< idEntityPtr<idEntity> * >( dataPtr ) = reinterpret_cast<idEntity *>( arg->value );
			break;

		case D_EVENT_TRACE :
			if ( arg->value ) {
				*reinterpret_cast<bool *>( dataPtr ) = true;
				*reinterpret_cast<trace_t *>( dataPtr + sizeof( bool ) ) = *reinterpret_cast<const trace_t *>( arg->value );

				// save off the material as a string since the pointer won't be valid in save games.
				// since we save off the entire trace_t structure, if the material is NULL here,
				// it will be NULL when we process it, so we don't need to save off anything in that case.
				if ( reinterpret_cast<const trace_t *>( arg->value )->c.material ) {
					materialName = reinterpret_cast<const trace_t *>( arg->value )->c.material->GetName();
					idStr::Copynz( reinterpret_cast<char *>( dataPtr + sizeof( bool ) + sizeof( trace_t ) ), materialName, MAX_STRING_LEN );
				}
			} else {
				*reinterpret_cast<bool *>( dataPtr ) = false;
			}
			break;

		default :
			gameLocal.Error( "idEvent::Alloc : Invalid arg format '%s' string for '%s' event.", format, evdef->GetName() );
			break;
		}
	}

	return ev;
}
Example #12
0
/*
================
idEvent::Restore
================
*/
void idEvent::Restore( idRestoreGame* savefile )
{
	char*    str;
	int		num, argsize, i, j, size;
	idStr	name;
	byte* dataPtr;
	idEvent*	event;
	const char*	format;
	// RB: for missing D_EVENT_STRING
	idStr s;
	// RB end
	
	savefile->ReadInt( num );
	
	for( i = 0; i < num; i++ )
	{
		if( FreeEvents.IsListEmpty() )
		{
			gameLocal.Error( "idEvent::Restore : No more free events" );
		}
		
		event = FreeEvents.Next();
		event->eventNode.Remove();
		event->eventNode.AddToEnd( EventQueue );
		
		savefile->ReadInt( event->time );
		
		// read the event name
		savefile->ReadString( name );
		event->eventdef = idEventDef::FindEvent( name );
		if( event->eventdef == NULL )
		{
			savefile->Error( "idEvent::Restore: unknown event '%s'", name.c_str() );
			return;
		}
		
		// read the classtype
		savefile->ReadString( name );
		event->typeinfo = idClass::GetClass( name );
		if( event->typeinfo == NULL )
		{
			savefile->Error( "idEvent::Restore: unknown class '%s' on event '%s'", name.c_str(), event->eventdef->GetName() );
			return;
		}
		
		savefile->ReadObject( event->object );
		
		// read the args
		savefile->ReadInt( argsize );
		if( argsize != ( int )event->eventdef->GetArgSize() )
		{
			// RB: fixed wrong formatting
			savefile->Error( "idEvent::Restore: arg size (%zd) doesn't match saved arg size(%zd) on event '%s'", event->eventdef->GetArgSize(), argsize, event->eventdef->GetName() );
			// RB end
		}
		if( argsize )
		{
			event->data = eventDataAllocator.Alloc( argsize );
			format = event->eventdef->GetArgFormat();
			assert( format );
			for( j = 0, size = 0; j < event->eventdef->GetNumArgs(); ++j )
			{
				dataPtr = &event->data[ event->eventdef->GetArgOffset( j ) ];
				switch( format[ j ] )
				{
					case D_EVENT_FLOAT :
						savefile->ReadFloat( *reinterpret_cast<float*>( dataPtr ) );
						// RB: 64 bit fix, changed sizeof( float ) to sizeof( intptr_t )
						size += sizeof( intptr_t );
						// RB end
						break;
					case D_EVENT_INTEGER :
						// RB: 64 bit fix
						savefile->ReadInt( *reinterpret_cast<int*>( dataPtr ) );
						size += sizeof( intptr_t );
						break;
						// RB end
					case D_EVENT_ENTITY :
					case D_EVENT_ENTITY_NULL :
						// RB: 64 bit fix, changed alignment to sizeof( intptr_t )
						reinterpret_cast<idEntityPtr<idEntity> *>( dataPtr )->Restore( savefile );
						size += sizeof( intptr_t );
						// RB end
						break;
					case D_EVENT_VECTOR :
						savefile->ReadVec3( *reinterpret_cast<idVec3*>( dataPtr ) );
						// RB: 64 bit fix, changed sizeof( int ) to E_EVENT_SIZEOF_VEC
						size += E_EVENT_SIZEOF_VEC;
						// RB end
						break;
#if 1
						// RB: added missing D_EVENT_STRING case
					case D_EVENT_STRING :
						savefile->ReadString( s );
						//idStr::Copynz(reinterpret_cast<char *>( dataPtr ), s, s.Length() );
						//size += s.Length();
						idStr::Copynz( reinterpret_cast<char*>( dataPtr ), s, MAX_STRING_LEN );
						size += MAX_STRING_LEN;
						break;
						// RB end
#endif
					case D_EVENT_TRACE :
						savefile->ReadBool( *reinterpret_cast<bool*>( dataPtr ) );
						size += sizeof( bool );
						if( *reinterpret_cast<bool*>( dataPtr ) )
						{
							size += sizeof( trace_t );
							trace_t& t = *reinterpret_cast<trace_t*>( dataPtr + sizeof( bool ) );
							RestoreTrace( savefile,  t ) ;
							if( t.c.material )
							{
								size += MAX_STRING_LEN;
								str = reinterpret_cast<char*>( dataPtr + sizeof( bool ) + sizeof( trace_t ) );
								savefile->Read( str, MAX_STRING_LEN );
							}
						}
						break;
					default:
						break;
				}
			}
			assert( size == ( int )event->eventdef->GetArgSize() );
		}
		else
		{
			event->data = NULL;
		}
	}
	
	// Restore the Fast EventQueue
	savefile->ReadInt( num );
	
	for( i = 0; i < num; i++ )
	{
		if( FreeEvents.IsListEmpty() )
		{
			gameLocal.Error( "idEvent::Restore : No more free events" );
		}
		
		event = FreeEvents.Next();
		event->eventNode.Remove();
		event->eventNode.AddToEnd( FastEventQueue );
		
		savefile->ReadInt( event->time );
		
		// read the event name
		savefile->ReadString( name );
		event->eventdef = idEventDef::FindEvent( name );
		if( event->eventdef == NULL )
		{
			savefile->Error( "idEvent::Restore: unknown event '%s'", name.c_str() );
			return;
		}
		
		// read the classtype
		savefile->ReadString( name );
		event->typeinfo = idClass::GetClass( name );
		if( event->typeinfo == NULL )
		{
			savefile->Error( "idEvent::Restore: unknown class '%s' on event '%s'", name.c_str(), event->eventdef->GetName() );
			return;
		}
		
		savefile->ReadObject( event->object );
		
		// read the args
		savefile->ReadInt( argsize );
		if( argsize != ( int )event->eventdef->GetArgSize() )
		{
			savefile->Error( "idEvent::Restore: arg size (%d) doesn't match saved arg size(%d) on event '%s'", event->eventdef->GetArgSize(), argsize, event->eventdef->GetName() );
		}
		if( argsize )
		{
			event->data = eventDataAllocator.Alloc( argsize );
			savefile->Read( event->data, argsize );
		}
		else
		{
			event->data = NULL;
		}
	}
}
Example #13
0
/*
================
idEvent::Save
================
*/
void idEvent::Save( idSaveGame* savefile )
{
	char* str;
	int i, size;
	idEvent*	event;
	byte* dataPtr;
	bool validTrace;
	const char*	format;
	// RB: for missing D_EVENT_STRING
	idStr s;
	// RB end
	
	savefile->WriteInt( EventQueue.Num() );
	
	event = EventQueue.Next();
	while( event != NULL )
	{
		savefile->WriteInt( event->time );
		savefile->WriteString( event->eventdef->GetName() );
		savefile->WriteString( event->typeinfo->classname );
		savefile->WriteObject( event->object );
		savefile->WriteInt( event->eventdef->GetArgSize() );
		format = event->eventdef->GetArgFormat();
		for( i = 0, size = 0; i < event->eventdef->GetNumArgs(); ++i )
		{
			dataPtr = &event->data[ event->eventdef->GetArgOffset( i ) ];
			switch( format[ i ] )
			{
				case D_EVENT_FLOAT :
					savefile->WriteFloat( *reinterpret_cast<float*>( dataPtr ) );
					// RB: 64 bit fix, changed sizeof( float ) to sizeof( intptr_t )
					size += sizeof( intptr_t );
					// RB end
					break;
				case D_EVENT_INTEGER :
					// RB: 64 bit fix, changed sizeof( int ) to sizeof( intptr_t )
					savefile->WriteInt( *reinterpret_cast<int*>( dataPtr ) );
					size += sizeof( intptr_t );
					break;
					// RB end
				case D_EVENT_ENTITY :
				case D_EVENT_ENTITY_NULL :
					// RB: 64 bit fix, changed alignment to sizeof( intptr_t )
					reinterpret_cast< idEntityPtr<idEntity> * >( dataPtr )->Save( savefile );
					size += sizeof( intptr_t );
					// RB end
					break;
				case D_EVENT_VECTOR :
					savefile->WriteVec3( *reinterpret_cast<idVec3*>( dataPtr ) );
					// RB: 64 bit fix, changed sizeof( int ) to E_EVENT_SIZEOF_VEC
					size += E_EVENT_SIZEOF_VEC;
					// RB end
					break;
#if 1
					// RB: added missing D_EVENT_STRING case
				case D_EVENT_STRING :
					s.Clear();
					s.Append( reinterpret_cast<char*>( dataPtr ) );
					savefile->WriteString( s );
					//size += s.Length();
					size += MAX_STRING_LEN;
					break;
					// RB end
#endif
				case D_EVENT_TRACE :
					validTrace = *reinterpret_cast<bool*>( dataPtr );
					savefile->WriteBool( validTrace );
					size += sizeof( bool );
					if( validTrace )
					{
						size += sizeof( trace_t );
						const trace_t& t = *reinterpret_cast<trace_t*>( dataPtr + sizeof( bool ) );
						SaveTrace( savefile, t );
						if( t.c.material )
						{
							size += MAX_STRING_LEN;
							str = reinterpret_cast<char*>( dataPtr + sizeof( bool ) + sizeof( trace_t ) );
							savefile->Write( str, MAX_STRING_LEN );
						}
					}
					break;
				default:
					break;
			}
		}
		assert( size == ( int )event->eventdef->GetArgSize() );
		event = event->eventNode.Next();
	}
	
	// Save the Fast EventQueue
	savefile->WriteInt( FastEventQueue.Num() );
	
	event = FastEventQueue.Next();
	while( event != NULL )
	{
		savefile->WriteInt( event->time );
		savefile->WriteString( event->eventdef->GetName() );
		savefile->WriteString( event->typeinfo->classname );
		savefile->WriteObject( event->object );
		savefile->WriteInt( event->eventdef->GetArgSize() );
		savefile->Write( event->data, event->eventdef->GetArgSize() );
		
		event = event->eventNode.Next();
	}
}
Example #14
0
/*
================
idEvent::Alloc
================
*/
idEvent *idEvent::Alloc( const idEventDef *evdef, int numargs, va_list args ) {
	idEvent		*ev;
	size_t		size;
	const char	*format;
	idEventArg	*arg;
	byte		*dataPtr;
	int			i;
	const char	*materialName;

	if ( FreeEvents.IsListEmpty() ) {
		WriteDebugInfo( );
		gameLocal.Error( "idEvent::Alloc : No more free events for '%s' event.", evdef->GetName() );
	}

	ev = FreeEvents.Next();
	ev->eventNode.Remove();

	ev->eventdef = evdef;

	if ( numargs != evdef->GetNumArgs() ) {
		gameLocal.Error( "idEvent::Alloc : Wrong number of args for '%s' event.", evdef->GetName() );
	}

	size = evdef->GetArgSize();
	if ( size ) {
		ev->data = eventDataAllocator.Alloc( size );
		memset( ev->data, 0, size );
	} else {
		ev->data = NULL;
	}

	format = evdef->GetArgFormat();
	for( i = 0; i < numargs; i++ ) {
		arg = va_arg( args, idEventArg * );
		if ( format[ i ] != arg->type ) {
// RAVEN BEGIN
// abahr: type checking change as per Jim D.
			if ( ( format[ i ] == D_EVENT_ENTITY_NULL ) && ( arg->type == D_EVENT_ENTITY ) ) {
			// these types are identical, so allow them
			} else if ( ( arg->type == D_EVENT_INTEGER ) && ( arg->value == 0 ) ) {
				if ( ( format[ i ] == D_EVENT_ENTITY ) || ( format[ i ] == D_EVENT_ENTITY_NULL ) || ( format[ i ] == D_EVENT_TRACE ) ) {
				 // when NULL is passed in for an entity or trace, it gets cast as an integer 0, so don't give an error when it happens
				} else {
					 gameLocal.Error( "idEvent::Alloc : Wrong type passed in for arg # %d on '%s' event.", i, evdef->GetName() );
				}
			} else {
				gameLocal.Error( "idEvent::Alloc : Wrong type passed in for arg # %d on '%s' event.", i, evdef->GetName() );
			}
// RAVEN END
		}

		dataPtr = &ev->data[ evdef->GetArgOffset( i ) ];

		switch( format[ i ] ) {
		case D_EVENT_FLOAT :
		case D_EVENT_INTEGER :
			*reinterpret_cast<int *>( dataPtr ) = arg->value;
			break;

		case D_EVENT_VECTOR :
			if ( arg->value ) {
				*reinterpret_cast<idVec3 *>( dataPtr ) = *reinterpret_cast<const idVec3 *>( arg->value );
			}
			break;

		case D_EVENT_STRING :
			if ( arg->value ) {
				idStr::Copynz( reinterpret_cast<char *>( dataPtr ), reinterpret_cast<const char *>( arg->value ), MAX_STRING_LEN );
			}
			break;

// RAVEN BEGIN
// abahr: type checking change as per Jim D.
// jshepard: TODO FIXME HACK this never ever produces desired, positive results. Events should be built to prepare for null entities, especially when dealing with 
//							 script events. This will throw a warning, and events should be prepared to deal with null entities. 
		case D_EVENT_ENTITY :
			if ( reinterpret_cast<idEntity *>( arg->value ) == NULL ) {
				gameLocal.Warning( "idEvent::Alloc : NULL entity passed in to event function that expects a non-NULL pointer on arg # %d on '%s' event.", i, evdef->GetName() );
			}
			*reinterpret_cast< idEntityPtr<idEntity> * >( dataPtr ) = reinterpret_cast<idEntity *>( arg->value );
			break;
 
		case D_EVENT_ENTITY_NULL :
			*reinterpret_cast< idEntityPtr<idEntity> * >( dataPtr ) = reinterpret_cast<idEntity *>( arg->value );
			break;
//RAVEN END

		case D_EVENT_TRACE :
			if ( arg->value ) {
				*reinterpret_cast<bool *>( dataPtr ) = true;
				*reinterpret_cast<trace_t *>( dataPtr + sizeof( bool ) ) = *reinterpret_cast<const trace_t *>( arg->value );

				// save off the material as a string since the pointer won't be valid in save games.
				// since we save off the entire trace_t structure, if the material is NULL here,
				// it will be NULL when we process it, so we don't need to save off anything in that case.
				if ( reinterpret_cast<const trace_t *>( arg->value )->c.material ) {
					materialName = reinterpret_cast<const trace_t *>( arg->value )->c.material->GetName();
					idStr::Copynz( reinterpret_cast<char *>( dataPtr + sizeof( bool ) + sizeof( trace_t ) ), materialName, MAX_STRING_LEN );
				}
			} else {
				*reinterpret_cast<bool *>( dataPtr ) = false;
			}
			break;

		default :
			gameLocal.Error( "idEvent::Alloc : Invalid arg format '%s' string for '%s' event.", format, evdef->GetName() );
			break;
		}
	}

	return ev;
}