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