Probably there are plenty released in the past, but here a tiny one from me:

http://www.youtube.com/watch?v=xE9sZULURKo





Link to model and code:
http://joozey.nl/3dgs/contribs/Electricity.zip

Have fun!



Code:
//defines

//handy
#define new(x) malloc(sizeof(x))
#define remove(x) free(x)



//length of the model (you need to adapt this if you got your own model)
#define ELECTRIC_LENGTH 50

//model name
#define ELECTRICITY_MODEL "electricity.mdl"



//structure
typedef struct
{
	VECTOR start;
	VECTOR end;
	var seconds;
	ENTITY *electricity_entity;
	var deviation;
	
} ELECTRICITY;



//prototypes
void ELECTRICITY_Shoot( ELECTRICITY *e );
void ELECTRICITY_Run( ELECTRICITY *e );
ELECTRICITY *ELECTRICITY_Create( VECTOR *start, VECTOR *end, var seconds, var deviation );
void ELECTRICITY_Remove( ELECTRICITY *e );



//runs as many time as has been assigned on seconds (not really seconds by the way)
void ELECTRICITY_Run( ELECTRICITY *e )
{
	//shoot a new electric (will recursively loop in here again)
	ELECTRICITY_Shoot( e );
	
	//factor for decaying alpha with seconds
	var factor = 100/e->seconds;
	set( e->electricity_entity, TRANSLUCENT );
	
	//loop while we still got seconds
	while( e->seconds > 0 )
	{
		e->seconds -= 1 * time_step;
		e->electricity_entity.alpha -= factor * time_step; //decay alpha
		wait(1);
	}
	
	//remove the entity
	ent_remove( e->electricity_entity );
	remove( e );
}


//create a new electricity (you call this to create a new thunder, also used for recursive loop internally)
ELECTRICITY *ELECTRICITY_Create( VECTOR *start, VECTOR *end, var seconds, var deviation )
{
	ELECTRICITY *e = new(ELECTRICITY);
	
	vec_set( e->start, start );
	vec_set( e->end, end );
	e->seconds = seconds;
	e->deviation = deviation;
	e->electricity_entity = ent_create(ELECTRICITY_MODEL, e->start, NULL);
	
	//start running
	ELECTRICITY_Run( e );	
	
	return e;
}


//remove electricity
//since the run function still uses the electricity when it is removed here, errors may pop up
//so we make sure the run ends, and let the run function take care of removing
//we end the run by putting seconds on 0
void ELECTRICITY_Remove( ELECTRICITY *e )
{
	e->seconds = 0;
}


//shoot a new segment of electricity
void ELECTRICITY_Shoot( ELECTRICITY *e )
{
	VECTOR newStart;
	VECTOR newEnd;
	
	//get direction from current position to global end
	vec_set( newEnd, e->end );
	vec_sub( newEnd, e->start );
	
	//rotate a bit by given deviation
	vec_rotate( newEnd, vector( random(e->deviation*2)-e->deviation, random(e->deviation*2)-e->deviation, random(e->deviation*2)-e->deviation ) );
	
	//scale it to the model's length
	vec_normalize( newEnd, ELECTRIC_LENGTH );
	
	//place it at the previous electric segment
	vec_set( newStart, e->start );
	vec_add( newStart, newEnd );
	
	
	//place the real model
	vec_set( e->electricity_entity.x, e->start );
	
	//rotate the real model
	VECTOR *vAngle = vector( 0, 0, 0 );
	vec_set( vAngle, e->start );
	vec_sub( vAngle, newStart );
	vec_to_angle( e->electricity_entity.pan, vAngle );
	
	
	//since this function is recursive, we need to limit it before it goes endless looping
	//we look if the electric segment approaches the global end, if so, we dont make a new segment anymore
	//
	//TODO: make the last segment end exactly on the designated end position
	//currently it is not exactly on the spot but stops right before or after it
	if( vec_dist( e->start, e->end ) > ELECTRIC_LENGTH + 10 )
	{
		ELECTRICITY *e = ELECTRICITY_Create( newStart, e->end, e->seconds, e->deviation );
	}
	
	//this is the very last segment,we treat it a bit different
	if( vec_dist( e->start, e->end ) <= ELECTRIC_LENGTH + 10 &&
	 	 vec_dist( e->start, e->end ) >= ELECTRIC_LENGTH - 10 )
	{
		//at least give the last segment a deviation of 0 so it will point directly towards global end
		ELECTRICITY *e = ELECTRICITY_Create( newStart, e->end, e->seconds, e->deviation );
	}
}




Click and join the 3dgs irc community!
Room: #3dgs