2012-01-08 11:39:03 -06:00
# include <cstdlib>
# include <math.h>
# include "Config.h"
# include "Simulation.h"
# include "Elements.h"
# include "ElementFunctions.h"
# include "Air.h"
# include "Gravity.h"
void Simulation : : clear_area ( int area_x , int area_y , int area_w , int area_h )
{
int cx = 0 ;
int cy = 0 ;
for ( cy = 0 ; cy < area_h ; cy + + )
{
for ( cx = 0 ; cx < area_w ; cx + + )
{
bmap [ ( cy + area_y ) / CELL ] [ ( cx + area_x ) / CELL ] = 0 ;
delete_part ( cx + area_x , cy + area_y , 0 ) ;
}
}
}
void Simulation : : create_box ( int x1 , int y1 , int x2 , int y2 , int c , int flags )
{
int i , j ;
if ( c = = SPC_PROP )
return ;
if ( x1 > x2 )
{
i = x2 ;
x2 = x1 ;
x1 = i ;
}
if ( y1 > y2 )
{
j = y2 ;
y2 = y1 ;
y1 = j ;
}
for ( j = y1 ; j < = y2 ; j + + )
for ( i = x1 ; i < = x2 ; i + + )
create_parts ( i , j , 0 , 0 , c , flags ) ;
}
int Simulation : : flood_prop_2 ( int x , int y , size_t propoffset , void * propvalue , int proptype , int parttype , char * bitmap )
{
int x1 , x2 , i , dy = 1 ;
x1 = x2 = x ;
while ( x1 > = CELL )
{
if ( ( pmap [ y ] [ x1 - 1 ] & 0xFF ) ! = parttype | | bitmap [ ( y * XRES ) + x1 - 1 ] )
{
break ;
}
x1 - - ;
}
while ( x2 < XRES - CELL )
{
if ( ( pmap [ y ] [ x2 + 1 ] & 0xFF ) ! = parttype | | bitmap [ ( y * XRES ) + x2 + 1 ] )
{
break ;
}
x2 + + ;
}
for ( x = x1 ; x < = x2 ; x + + )
{
i = pmap [ y ] [ x ] > > 8 ;
if ( proptype = = 2 ) {
* ( ( float * ) ( ( ( char * ) & parts [ i ] ) + propoffset ) ) = * ( ( float * ) propvalue ) ;
} else if ( proptype = = 0 ) {
* ( ( int * ) ( ( ( char * ) & parts [ i ] ) + propoffset ) ) = * ( ( int * ) propvalue ) ;
} else if ( proptype = = 1 ) {
* ( ( char * ) ( ( ( char * ) & parts [ i ] ) + propoffset ) ) = * ( ( char * ) propvalue ) ;
}
bitmap [ ( y * XRES ) + x ] = 1 ;
}
if ( y > = CELL + dy )
for ( x = x1 ; x < = x2 ; x + + )
if ( ( pmap [ y - dy ] [ x ] & 0xFF ) = = parttype & & ! bitmap [ ( ( y - dy ) * XRES ) + x ] )
if ( ! flood_prop_2 ( x , y - dy , propoffset , propvalue , proptype , parttype , bitmap ) )
return 0 ;
if ( y < YRES - CELL - dy )
for ( x = x1 ; x < = x2 ; x + + )
if ( ( pmap [ y + dy ] [ x ] & 0xFF ) = = parttype & & ! bitmap [ ( ( y + dy ) * XRES ) + x ] )
if ( ! flood_prop_2 ( x , y + dy , propoffset , propvalue , proptype , parttype , bitmap ) )
return 0 ;
return 1 ;
}
int Simulation : : flood_prop ( int x , int y , size_t propoffset , void * propvalue , int proptype )
{
int r = 0 ;
char * bitmap = ( char * ) malloc ( XRES * YRES ) ; //Bitmap for checking
memset ( bitmap , 0 , XRES * YRES ) ;
r = pmap [ y ] [ x ] ;
flood_prop_2 ( x , y , propoffset , propvalue , proptype , r & 0xFF , bitmap ) ;
free ( bitmap ) ;
return 0 ;
}
int Simulation : : flood_parts ( int x , int y , int fullc , int cm , int bm , int flags )
{
int c = fullc & 0xFF ;
int x1 , x2 , dy = ( c < PT_NUM ) ? 1 : CELL ;
int co = c ;
if ( c = = SPC_PROP )
return 0 ;
if ( cm = = PT_INST & & co = = PT_SPRK )
if ( ( pmap [ y ] [ x ] & 0xFF ) = = PT_SPRK )
return 0 ;
if ( cm = = - 1 )
{
if ( c = = 0 )
{
cm = pmap [ y ] [ x ] & 0xFF ;
if ( ! cm )
return 0 ;
//if ((flags&BRUSH_REPLACEMODE) && cm!=SLALT)
// return 0;
}
else
cm = 0 ;
}
if ( bm = = - 1 )
{
if ( c - UI_WALLSTART + UI_ACTUALSTART = = WL_ERASE )
{
bm = bmap [ y / CELL ] [ x / CELL ] ;
if ( ! bm )
return 0 ;
if ( bm = = WL_WALL )
cm = 0xFF ;
}
else
bm = 0 ;
}
if ( ( ( pmap [ y ] [ x ] & 0xFF ) ! = cm | | bmap [ y / CELL ] [ x / CELL ] ! = bm ) /*||( (flags&BRUSH_SPECIFIC_DELETE) && cm!=SLALT)*/ )
return 1 ;
// go left as far as possible
x1 = x2 = x ;
while ( x1 > = CELL )
{
if ( ( pmap [ y ] [ x1 - 1 ] & 0xFF ) ! = cm | | bmap [ y / CELL ] [ ( x1 - 1 ) / CELL ] ! = bm )
{
break ;
}
x1 - - ;
}
while ( x2 < XRES - CELL )
{
if ( ( pmap [ y ] [ x2 + 1 ] & 0xFF ) ! = cm | | bmap [ y / CELL ] [ ( x2 + 1 ) / CELL ] ! = bm )
{
break ;
}
x2 + + ;
}
// fill span
for ( x = x1 ; x < = x2 ; x + + )
{
if ( cm = = PT_INST & & co = = PT_SPRK )
{
if ( create_part ( - 1 , x , y , fullc ) = = - 1 )
return 0 ;
}
else if ( ! create_parts ( x , y , 0 , 0 , fullc , flags ) )
return 0 ;
}
// fill children
if ( cm = = PT_INST & & co = = PT_SPRK ) //wire crossing for INST
{
if ( y > = CELL + dy & & x1 = = x2 & &
( ( pmap [ y - 1 ] [ x1 - 1 ] & 0xFF ) = = PT_INST | | ( pmap [ y - 1 ] [ x1 - 1 ] & 0xFF ) = = PT_SPRK ) & & ( ( pmap [ y - 1 ] [ x1 ] & 0xFF ) = = PT_INST | | ( pmap [ y - 1 ] [ x1 ] & 0xFF ) = = PT_SPRK ) & & ( ( pmap [ y - 1 ] [ x1 + 1 ] & 0xFF ) = = PT_INST | | ( pmap [ y - 1 ] [ x1 + 1 ] & 0xFF ) = = PT_SPRK ) & &
( pmap [ y - 2 ] [ x1 - 1 ] & 0xFF ) ! = PT_INST & & ( ( pmap [ y - 2 ] [ x1 ] & 0xFF ) = = PT_INST | | ( pmap [ y - 2 ] [ x1 ] & 0xFF ) = = PT_SPRK ) & & ( pmap [ y - 2 ] [ x1 + 1 ] & 0xFF ) ! = PT_INST )
flood_parts ( x1 , y - 2 , fullc , cm , bm , flags ) ;
else if ( y > = CELL + dy )
for ( x = x1 ; x < = x2 ; x + + )
if ( ( pmap [ y - 1 ] [ x ] & 0xFF ) ! = PT_SPRK )
{
if ( x = = x1 | | x = = x2 | | y > = YRES - CELL - 1 | |
( pmap [ y - 1 ] [ x - 1 ] & 0xFF ) = = PT_INST | | ( pmap [ y - 1 ] [ x + 1 ] & 0xFF ) = = PT_INST | |
( pmap [ y + 1 ] [ x - 1 ] & 0xFF ) = = PT_INST | | ( ( pmap [ y + 1 ] [ x ] & 0xFF ) ! = PT_INST & & ( pmap [ y + 1 ] [ x ] & 0xFF ) ! = PT_SPRK ) | | ( pmap [ y + 1 ] [ x + 1 ] & 0xFF ) = = PT_INST )
flood_parts ( x , y - dy , fullc , cm , bm , flags ) ;
}
if ( y < YRES - CELL - dy & & x1 = = x2 & &
( ( pmap [ y + 1 ] [ x1 - 1 ] & 0xFF ) = = PT_INST | | ( pmap [ y + 1 ] [ x1 - 1 ] & 0xFF ) = = PT_SPRK ) & & ( ( pmap [ y + 1 ] [ x1 ] & 0xFF ) = = PT_INST | | ( pmap [ y + 1 ] [ x1 ] & 0xFF ) = = PT_SPRK ) & & ( ( pmap [ y + 1 ] [ x1 + 1 ] & 0xFF ) = = PT_INST | | ( pmap [ y + 1 ] [ x1 + 1 ] & 0xFF ) = = PT_SPRK ) & &
( pmap [ y + 2 ] [ x1 - 1 ] & 0xFF ) ! = PT_INST & & ( ( pmap [ y + 2 ] [ x1 ] & 0xFF ) = = PT_INST | | ( pmap [ y + 2 ] [ x1 ] & 0xFF ) = = PT_SPRK ) & & ( pmap [ y + 2 ] [ x1 + 1 ] & 0xFF ) ! = PT_INST )
flood_parts ( x1 , y + 2 , fullc , cm , bm , flags ) ;
else if ( y < YRES - CELL - dy )
for ( x = x1 ; x < = x2 ; x + + )
if ( ( pmap [ y + 1 ] [ x ] & 0xFF ) ! = PT_SPRK )
{
if ( x = = x1 | | x = = x2 | | y < 0 | |
( pmap [ y + 1 ] [ x - 1 ] & 0xFF ) = = PT_INST | | ( pmap [ y + 1 ] [ x + 1 ] & 0xFF ) = = PT_INST | |
( pmap [ y - 1 ] [ x - 1 ] & 0xFF ) = = PT_INST | | ( ( pmap [ y - 1 ] [ x ] & 0xFF ) ! = PT_INST & & ( pmap [ y - 1 ] [ x ] & 0xFF ) ! = PT_SPRK ) | | ( pmap [ y - 1 ] [ x + 1 ] & 0xFF ) = = PT_INST )
flood_parts ( x , y + dy , fullc , cm , bm , flags ) ;
}
}
else
{
if ( y > = CELL + dy )
for ( x = x1 ; x < = x2 ; x + + )
if ( ( pmap [ y - dy ] [ x ] & 0xFF ) = = cm & & bmap [ ( y - dy ) / CELL ] [ x / CELL ] = = bm )
if ( ! flood_parts ( x , y - dy , fullc , cm , bm , flags ) )
return 0 ;
if ( y < YRES - CELL - dy )
for ( x = x1 ; x < = x2 ; x + + )
if ( ( pmap [ y + dy ] [ x ] & 0xFF ) = = cm & & bmap [ ( y + dy ) / CELL ] [ x / CELL ] = = bm )
if ( ! flood_parts ( x , y + dy , fullc , cm , bm , flags ) )
return 0 ;
}
if ( ! ( cm = = PT_INST & & co = = PT_SPRK ) )
return 1 ;
return 0 ;
}
int Simulation : : flood_water ( int x , int y , int i , int originaly , int check )
{
int x1 = 0 , x2 = 0 ;
// go left as far as possible
x1 = x2 = x ;
if ( ! pmap [ y ] [ x ] )
return 1 ;
while ( x1 > = CELL )
{
if ( ( ptypes [ ( pmap [ y ] [ x1 - 1 ] & 0xFF ) ] . falldown ) ! = 2 )
{
break ;
}
x1 - - ;
}
while ( x2 < XRES - CELL )
{
if ( ( ptypes [ ( pmap [ y ] [ x2 + 1 ] & 0xFF ) ] . falldown ) ! = 2 )
{
break ;
}
x2 + + ;
}
// fill span
for ( x = x1 ; x < = x2 ; x + + )
{
parts [ pmap [ y ] [ x ] > > 8 ] . tmp2 = ! check ; //flag it as checked, maybe shouldn't use .tmp2
//check above, maybe around other sides too?
if ( ( ( y - 1 ) > originaly ) & & ! pmap [ y - 1 ] [ x ] & & eval_move ( parts [ i ] . type , x , y - 1 , NULL ) )
{
int oldx = ( int ) ( parts [ i ] . x + 0.5f ) ;
int oldy = ( int ) ( parts [ i ] . y + 0.5f ) ;
pmap [ y - 1 ] [ x ] = pmap [ oldy ] [ oldx ] ;
pmap [ oldy ] [ oldx ] = 0 ;
parts [ i ] . x = x ;
parts [ i ] . y = y - 1 ;
return 0 ;
}
}
// fill children
if ( y > = CELL + 1 )
for ( x = x1 ; x < = x2 ; x + + )
if ( ( ptypes [ ( pmap [ y - 1 ] [ x ] & 0xFF ) ] . falldown ) = = 2 & & parts [ pmap [ y - 1 ] [ x ] > > 8 ] . tmp2 = = check )
if ( ! flood_water ( x , y - 1 , i , originaly , check ) )
return 0 ;
if ( y < YRES - CELL - 1 )
for ( x = x1 ; x < = x2 ; x + + )
if ( ( ptypes [ ( pmap [ y + 1 ] [ x ] & 0xFF ) ] . falldown ) = = 2 & & parts [ pmap [ y + 1 ] [ x ] > > 8 ] . tmp2 = = check )
if ( ! flood_water ( x , y + 1 , i , originaly , check ) )
return 0 ;
return 1 ;
}
//wrapper around create_part to create TESC with correct tmp value
int Simulation : : create_part_add_props ( int p , int x , int y , int tv , int rx , int ry )
{
p = create_part ( p , x , y , tv ) ;
if ( tv = = PT_TESC )
{
parts [ p ] . tmp = rx * 4 + ry * 4 + 7 ;
if ( parts [ p ] . tmp > 300 )
parts [ p ] . tmp = 300 ;
}
return p ;
}
//this creates particles from a brush, don't use if you want to create one particle
int Simulation : : create_parts ( int x , int y , int rx , int ry , int c , int flags )
{
int i , j , r , f = 0 , u , v , oy , ox , b = 0 , dw = 0 , stemp = 0 , p ; //n;
int wall = c - 100 ;
if ( c = = SPC_WIND | | c = = PT_FIGH )
return 0 ;
//if(c==SPC_PROP){
// prop_edit_ui(vid_buf, x, y);
// return 0;
//}
for ( r = UI_ACTUALSTART ; r < = UI_ACTUALSTART + UI_WALLCOUNT ; r + + )
{
if ( wall = = r )
{
if ( c = = SPC_AIR | | c = = SPC_HEAT | | c = = SPC_COOL | | c = = SPC_VACUUM | | c = = SPC_PGRV | | c = = SPC_NGRV | | wall = = WL_SIGN )
break ;
if ( wall = = WL_ERASE )
b = 0 ;
else
b = wall ;
dw = 1 ;
}
}
if ( c = = WL_FANHELPER )
{
b = WL_FANHELPER ;
dw = 1 ;
}
if ( wall = = WL_GRAV )
{
gravwl_timeout = 60 ;
}
if ( c = = PT_LIGH )
{
if ( lighting_recreate > 0 & & rx + ry > 0 )
return 0 ;
p = create_part ( - 2 , x , y , c ) ;
if ( p ! = - 1 )
{
parts [ p ] . life = rx + ry ;
if ( parts [ p ] . life > 55 )
parts [ p ] . life = 55 ;
parts [ p ] . temp = parts [ p ] . life * 150 ; // temperature of the lighting shows the power of the lighting
lighting_recreate + = parts [ p ] . life / 2 + 1 ;
return 1 ;
}
else return 0 ;
}
if ( dw = = 1 )
{
ry = ry / CELL ;
rx = rx / CELL ;
x = x / CELL ;
y = y / CELL ;
x - = rx / 2 ;
y - = ry / 2 ;
for ( ox = x ; ox < = x + rx ; ox + + )
{
for ( oy = y ; oy < = y + rx ; oy + + )
{
if ( ox > = 0 & & ox < XRES / CELL & & oy > = 0 & & oy < YRES / CELL )
{
i = ox ;
j = oy ;
/*if ((flags&BRUSH_SPECIFIC_DELETE) && b!=WL_FANHELPER)
{
if ( bmap [ j ] [ i ] = = SLALT - 100 )
{
b = 0 ;
if ( SLALT = = WL_GRAV ) gravwl_timeout = 60 ;
}
else
continue ;
} */
if ( b = = WL_FAN )
{
fvx [ j ] [ i ] = 0.0f ;
fvy [ j ] [ i ] = 0.0f ;
}
if ( b = = WL_STREAM )
{
i = x + rx / 2 ;
j = y + ry / 2 ;
for ( v = - 1 ; v < 2 ; v + + )
for ( u = - 1 ; u < 2 ; u + + )
if ( i + u > = 0 & & i + u < XRES / CELL & &
j + v > = 0 & & j + v < YRES / CELL & &
bmap [ j + v ] [ i + u ] = = WL_STREAM )
return 1 ;
bmap [ j ] [ i ] = WL_STREAM ;
continue ;
}
if ( b = = 0 & & bmap [ j ] [ i ] = = WL_GRAV ) gravwl_timeout = 60 ;
bmap [ j ] [ i ] = b ;
}
}
}
return 1 ;
}
//eraser
if ( c = = 0 /* && !(flags&BRUSH_REPLACEMODE)*/ )
{
if ( rx = = 0 & & ry = = 0 )
{
delete_part ( x , y , 0 ) ;
}
else
for ( j = - ry ; j < = ry ; j + + )
for ( i = - rx ; i < = rx ; i + + )
//if (InCurrentBrush(i ,j ,rx ,ry))
delete_part ( x + i , y + j , 0 ) ;
return 1 ;
}
//specific deletion
/*if ((flags&BRUSH_SPECIFIC_DELETE)&& !(flags&BRUSH_REPLACEMODE))
{
if ( rx = = 0 & & ry = = 0 )
{
delete_part ( x , y , flags ) ;
}
else
for ( j = - ry ; j < = ry ; j + + )
for ( i = - rx ; i < = rx ; i + + )
if ( InCurrentBrush ( i , j , rx , ry ) )
delete_part ( x + i , y + j , flags ) ;
return 1 ;
} */
//why do these need a special if
if ( c = = SPC_AIR | | c = = SPC_HEAT | | c = = SPC_COOL | | c = = SPC_VACUUM | | c = = SPC_PGRV | | c = = SPC_NGRV )
{
if ( rx = = 0 & & ry = = 0 )
{
create_part ( - 2 , x , y , c ) ;
}
else
for ( j = - ry ; j < = ry ; j + + )
for ( i = - rx ; i < = rx ; i + + )
//if (InCurrentBrush(i ,j ,rx ,ry))
{
if ( x + i < 0 | | y + j < 0 | | x + i > = XRES | | y + j > = YRES )
continue ;
//if (!REPLACE_MODE)
create_part ( - 2 , x + i , y + j , c ) ;
/*else if ((pmap[y+j][x+i]&0xFF)==SLALT&&SLALT!=0)
create_part ( - 2 , x + i , y + j , c ) ; */
}
return 1 ;
}
/*if (flags&BRUSH_REPLACEMODE)
{
if ( rx = = 0 & & ry = = 0 )
{
if ( ( pmap [ y ] [ x ] & 0xFF ) = = SLALT | | SLALT = = 0 )
{
if ( ( pmap [ y ] [ x ] ) )
{
delete_part ( x , y , 0 ) ;
if ( c ! = 0 )
create_part_add_props ( - 2 , x , y , c , rx , ry ) ;
}
}
}
else
for ( j = - ry ; j < = ry ; j + + )
for ( i = - rx ; i < = rx ; i + + )
if ( InCurrentBrush ( i , j , rx , ry ) )
{
if ( x + i < 0 | | y + j < 0 | | x + i > = XRES | | y + j > = YRES )
continue ;
if ( ( pmap [ y + j ] [ x + i ] & 0xFF ) ! = SLALT & & SLALT ! = 0 )
continue ;
if ( ( pmap [ y + j ] [ x + i ] ) )
{
delete_part ( x + i , y + j , 0 ) ;
if ( c ! = 0 )
create_part_add_props ( - 2 , x + i , y + j , c , rx , ry ) ;
}
}
return 1 ;
} */
//else, no special modes, draw element like normal.
if ( rx = = 0 & & ry = = 0 ) //workaround for 1pixel brush/floodfill crashing. todo: find a better fix later.
{
if ( create_part_add_props ( - 2 , x , y , c , rx , ry ) = = - 1 )
f = 1 ;
}
else
for ( j = - ry ; j < = ry ; j + + )
for ( i = - rx ; i < = rx ; i + + )
//if (InCurrentBrush(i ,j ,rx ,ry))
if ( create_part_add_props ( - 2 , x + i , y + j , c , rx , ry ) = = - 1 )
f = 1 ;
return ! f ;
}
/*int Simulation::InCurrentBrush(int i, int j, int rx, int ry)
{
switch ( CURRENT_BRUSH )
{
case CIRCLE_BRUSH :
return ( pow ( i , 2 ) * pow ( ry , 2 ) + pow ( j , 2 ) * pow ( rx , 2 ) < = pow ( rx , 2 ) * pow ( ry , 2 ) ) ;
break ;
case SQUARE_BRUSH :
return ( i * j < = ry * rx ) ;
break ;
case TRI_BRUSH :
return ( j < = ry ) & & ( j > = ( ( ( - 2.0 * ry ) / rx ) * i ) - ry ) & & ( j > = ( ( ( - 2.0 * ry ) / ( - rx ) ) * i ) - ry ) ;
break ;
}
return 0 ;
}
int Simulation : : get_brush_flags ( )
{
int flags = 0 ;
if ( REPLACE_MODE )
flags | = BRUSH_REPLACEMODE ;
if ( sdl_mod & KMOD_CAPS )
flags | = BRUSH_SPECIFIC_DELETE ;
if ( ( sdl_mod & KMOD_LALT ) & & ( sdl_mod & ( KMOD_CTRL ) ) )
flags | = BRUSH_SPECIFIC_DELETE ;
return flags ;
} */
void Simulation : : create_line ( int x1 , int y1 , int x2 , int y2 , int rx , int ry , int c , int flags )
{
int cp = abs ( y2 - y1 ) > abs ( x2 - x1 ) , x , y , dx , dy , sy ;
float e , de ;
if ( c = = SPC_PROP )
return ;
if ( cp )
{
y = x1 ;
x1 = y1 ;
y1 = y ;
y = x2 ;
x2 = y2 ;
y2 = y ;
}
if ( x1 > x2 )
{
y = x1 ;
x1 = x2 ;
x2 = y ;
y = y1 ;
y1 = y2 ;
y2 = y ;
}
dx = x2 - x1 ;
dy = abs ( y2 - y1 ) ;
e = 0.0f ;
if ( dx )
de = dy / ( float ) dx ;
else
de = 0.0f ;
y = y1 ;
sy = ( y1 < y2 ) ? 1 : - 1 ;
for ( x = x1 ; x < = x2 ; x + + )
{
if ( cp )
create_parts ( y , x , rx , ry , c , flags ) ;
else
create_parts ( x , y , rx , ry , c , flags ) ;
e + = de ;
if ( e > = 0.5f )
{
y + = sy ;
if ( ( c = = WL_EHOLE + 100 | | c = = WL_ALLOWGAS + 100 | | c = = WL_ALLOWENERGY + 100 | | c = = WL_ALLOWALLELEC + 100 | | c = = WL_ALLOWSOLID + 100 | | c = = WL_ALLOWAIR + 100 | | c = = WL_WALL + 100 | | c = = WL_DESTROYALL + 100 | | c = = WL_ALLOWLIQUID + 100 | | c = = WL_FAN + 100 | | c = = WL_STREAM + 100 | | c = = WL_DETECT + 100 | | c = = WL_EWALL + 100 | | c = = WL_WALLELEC + 100 | | ! ( rx + ry ) )
& & ( ( y1 < y2 ) ? ( y < = y2 ) : ( y > = y2 ) ) )
{
if ( cp )
create_parts ( y , x , rx , ry , c , flags ) ;
else
create_parts ( x , y , rx , ry , c , flags ) ;
}
e - = 1.0f ;
}
}
}
void * Simulation : : transform_save ( void * odata , int * size , matrix2d transform , vector2d translate )
{
void * ndata ;
unsigned char ( * bmapo ) [ XRES / CELL ] = ( unsigned char ( * ) [ XRES / CELL ] ) calloc ( ( YRES / CELL ) * ( XRES / CELL ) , sizeof ( unsigned char ) ) ;
unsigned char ( * bmapn ) [ XRES / CELL ] = ( unsigned char ( * ) [ XRES / CELL ] ) calloc ( ( YRES / CELL ) * ( XRES / CELL ) , sizeof ( unsigned char ) ) ;
Particle * partst = ( Particle * ) calloc ( sizeof ( Particle ) , NPART ) ;
sign * signst = ( sign * ) calloc ( MAXSIGNS , sizeof ( sign ) ) ;
unsigned ( * pmapt ) [ XRES ] = ( unsigned ( * ) [ XRES ] ) calloc ( YRES * XRES , sizeof ( unsigned ) ) ;
float ( * fvxo ) [ XRES / CELL ] = ( float ( * ) [ XRES / CELL ] ) calloc ( ( YRES / CELL ) * ( XRES / CELL ) , sizeof ( float ) ) ;
float ( * fvyo ) [ XRES / CELL ] = ( float ( * ) [ XRES / CELL ] ) calloc ( ( YRES / CELL ) * ( XRES / CELL ) , sizeof ( float ) ) ;
float ( * fvxn ) [ XRES / CELL ] = ( float ( * ) [ XRES / CELL ] ) calloc ( ( YRES / CELL ) * ( XRES / CELL ) , sizeof ( float ) ) ;
float ( * fvyn ) [ XRES / CELL ] = ( float ( * ) [ XRES / CELL ] ) calloc ( ( YRES / CELL ) * ( XRES / CELL ) , sizeof ( float ) ) ;
int i , x , y , nx , ny , w , h , nw , nh ;
vector2d pos , tmp , ctl , cbr ;
vector2d cornerso [ 4 ] ;
unsigned char * odatac = ( unsigned char * ) odata ;
//*if (parse_save(odata, *size, 0, 0, 0, bmapo, fvxo, fvyo, signst, partst, pmapt)) TODO: IMPLEMENT
{
free ( bmapo ) ;
free ( bmapn ) ;
free ( partst ) ;
free ( signst ) ;
free ( pmapt ) ;
free ( fvxo ) ;
free ( fvyo ) ;
free ( fvxn ) ;
free ( fvyn ) ;
return odata ;
}
w = odatac [ 6 ] * CELL ;
h = odatac [ 7 ] * CELL ;
// undo any translation caused by rotation
cornerso [ 0 ] = v2d_new ( 0 , 0 ) ;
cornerso [ 1 ] = v2d_new ( w - 1 , 0 ) ;
cornerso [ 2 ] = v2d_new ( 0 , h - 1 ) ;
cornerso [ 3 ] = v2d_new ( w - 1 , h - 1 ) ;
for ( i = 0 ; i < 4 ; i + + )
{
tmp = m2d_multiply_v2d ( transform , cornerso [ i ] ) ;
if ( i = = 0 ) ctl = cbr = tmp ; // top left, bottom right corner
if ( tmp . x < ctl . x ) ctl . x = tmp . x ;
if ( tmp . y < ctl . y ) ctl . y = tmp . y ;
if ( tmp . x > cbr . x ) cbr . x = tmp . x ;
if ( tmp . y > cbr . y ) cbr . y = tmp . y ;
}
// casting as int doesn't quite do what we want with negative numbers, so use floor()
tmp = v2d_new ( floor ( ctl . x + 0.5f ) , floor ( ctl . y + 0.5f ) ) ;
translate = v2d_sub ( translate , tmp ) ;
nw = floor ( cbr . x + 0.5f ) - floor ( ctl . x + 0.5f ) + 1 ;
nh = floor ( cbr . y + 0.5f ) - floor ( ctl . y + 0.5f ) + 1 ;
if ( nw > XRES ) nw = XRES ;
if ( nh > YRES ) nh = YRES ;
// rotate and translate signs, parts, walls
for ( i = 0 ; i < MAXSIGNS ; i + + )
{
if ( ! signst [ i ] . text [ 0 ] ) continue ;
pos = v2d_new ( signst [ i ] . x , signst [ i ] . y ) ;
pos = v2d_add ( m2d_multiply_v2d ( transform , pos ) , translate ) ;
nx = floor ( pos . x + 0.5f ) ;
ny = floor ( pos . y + 0.5f ) ;
if ( nx < 0 | | nx > = nw | | ny < 0 | | ny > = nh )
{
signst [ i ] . text [ 0 ] = 0 ;
continue ;
}
signst [ i ] . x = nx ;
signst [ i ] . y = ny ;
}
for ( i = 0 ; i < NPART ; i + + )
{
if ( ! partst [ i ] . type ) continue ;
pos = v2d_new ( partst [ i ] . x , partst [ i ] . y ) ;
pos = v2d_add ( m2d_multiply_v2d ( transform , pos ) , translate ) ;
nx = floor ( pos . x + 0.5f ) ;
ny = floor ( pos . y + 0.5f ) ;
if ( nx < 0 | | nx > = nw | | ny < 0 | | ny > = nh )
{
partst [ i ] . type = PT_NONE ;
continue ;
}
partst [ i ] . x = nx ;
partst [ i ] . y = ny ;
}
for ( y = 0 ; y < YRES / CELL ; y + + )
for ( x = 0 ; x < XRES / CELL ; x + + )
{
pos = v2d_new ( x * CELL + CELL * 0.4f , y * CELL + CELL * 0.4f ) ;
pos = v2d_add ( m2d_multiply_v2d ( transform , pos ) , translate ) ;
nx = pos . x / CELL ;
ny = pos . y / CELL ;
if ( nx < 0 | | nx > = nw | | ny < 0 | | ny > = nh )
continue ;
if ( bmapo [ y ] [ x ] )
{
bmapn [ ny ] [ nx ] = bmapo [ y ] [ x ] ;
if ( bmapo [ y ] [ x ] = = WL_FAN )
{
fvxn [ ny ] [ nx ] = fvxo [ y ] [ x ] ;
fvyn [ ny ] [ nx ] = fvyo [ y ] [ x ] ;
}
}
}
//ndata = build_save(size,0,0,nw,nh,bmapn,fvxn,fvyn,signst,partst); TODO: IMPLEMENT
free ( bmapo ) ;
free ( bmapn ) ;
free ( partst ) ;
free ( signst ) ;
free ( pmapt ) ;
free ( fvxo ) ;
free ( fvyo ) ;
free ( fvxn ) ;
free ( fvyn ) ;
return ndata ;
}
void Simulation : : orbitalparts_get ( int block1 , int block2 , int resblock1 [ ] , int resblock2 [ ] )
{
resblock1 [ 0 ] = ( block1 & 0x000000FF ) ;
resblock1 [ 1 ] = ( block1 & 0x0000FF00 ) > > 8 ;
resblock1 [ 2 ] = ( block1 & 0x00FF0000 ) > > 16 ;
resblock1 [ 3 ] = ( block1 & 0xFF000000 ) > > 24 ;
resblock2 [ 0 ] = ( block2 & 0x000000FF ) ;
resblock2 [ 1 ] = ( block2 & 0x0000FF00 ) > > 8 ;
resblock2 [ 2 ] = ( block2 & 0x00FF0000 ) > > 16 ;
resblock2 [ 3 ] = ( block2 & 0xFF000000 ) > > 24 ;
}
void Simulation : : orbitalparts_set ( int * block1 , int * block2 , int resblock1 [ ] , int resblock2 [ ] )
{
int block1tmp = 0 ;
int block2tmp = 0 ;
block1tmp = ( resblock1 [ 0 ] & 0xFF ) ;
block1tmp | = ( resblock1 [ 1 ] & 0xFF ) < < 8 ;
block1tmp | = ( resblock1 [ 2 ] & 0xFF ) < < 16 ;
block1tmp | = ( resblock1 [ 3 ] & 0xFF ) < < 24 ;
block2tmp = ( resblock2 [ 0 ] & 0xFF ) ;
block2tmp | = ( resblock2 [ 1 ] & 0xFF ) < < 8 ;
block2tmp | = ( resblock2 [ 2 ] & 0xFF ) < < 16 ;
block2tmp | = ( resblock2 [ 3 ] & 0xFF ) < < 24 ;
* block1 = block1tmp ;
* block2 = block2tmp ;
}
inline int Simulation : : is_wire ( int x , int y )
{
return bmap [ y ] [ x ] = = WL_DETECT | | bmap [ y ] [ x ] = = WL_EWALL | | bmap [ y ] [ x ] = = WL_ALLOWLIQUID | | bmap [ y ] [ x ] = = WL_WALLELEC | | bmap [ y ] [ x ] = = WL_ALLOWALLELEC | | bmap [ y ] [ x ] = = WL_EHOLE ;
}
inline int Simulation : : is_wire_off ( int x , int y )
{
return ( bmap [ y ] [ x ] = = WL_DETECT | | bmap [ y ] [ x ] = = WL_EWALL | | bmap [ y ] [ x ] = = WL_ALLOWLIQUID | | bmap [ y ] [ x ] = = WL_WALLELEC | | bmap [ y ] [ x ] = = WL_ALLOWALLELEC | | bmap [ y ] [ x ] = = WL_EHOLE ) & & emap [ y ] [ x ] < 8 ;
}
int Simulation : : get_wavelength_bin ( int * wm )
{
int i , w0 = 30 , wM = 0 ;
if ( ! * wm )
return - 1 ;
for ( i = 0 ; i < 30 ; i + + )
if ( * wm & ( 1 < < i ) ) {
if ( i < w0 )
w0 = i ;
if ( i > wM )
wM = i ;
}
if ( wM - w0 < 5 )
return ( wM + w0 ) / 2 ;
i = rand ( ) % ( wM - w0 - 3 ) ;
i + = w0 ;
* wm & = 0x1F < < i ;
return i + 2 ;
}
void Simulation : : set_emap ( int x , int y )
{
int x1 , x2 ;
if ( ! is_wire_off ( x , y ) )
return ;
// go left as far as possible
x1 = x2 = x ;
while ( x1 > 0 )
{
if ( ! is_wire_off ( x1 - 1 , y ) )
break ;
x1 - - ;
}
while ( x2 < XRES / CELL - 1 )
{
if ( ! is_wire_off ( x2 + 1 , y ) )
break ;
x2 + + ;
}
// fill span
for ( x = x1 ; x < = x2 ; x + + )
emap [ y ] [ x ] = 16 ;
// fill children
if ( y > 1 & & x1 = = x2 & &
is_wire ( x1 - 1 , y - 1 ) & & is_wire ( x1 , y - 1 ) & & is_wire ( x1 + 1 , y - 1 ) & &
! is_wire ( x1 - 1 , y - 2 ) & & is_wire ( x1 , y - 2 ) & & ! is_wire ( x1 + 1 , y - 2 ) )
set_emap ( x1 , y - 2 ) ;
else if ( y > 0 )
for ( x = x1 ; x < = x2 ; x + + )
if ( is_wire_off ( x , y - 1 ) )
{
if ( x = = x1 | | x = = x2 | | y > = YRES / CELL - 1 | |
is_wire ( x - 1 , y - 1 ) | | is_wire ( x + 1 , y - 1 ) | |
is_wire ( x - 1 , y + 1 ) | | ! is_wire ( x , y + 1 ) | | is_wire ( x + 1 , y + 1 ) )
set_emap ( x , y - 1 ) ;
}
if ( y < YRES / CELL - 2 & & x1 = = x2 & &
is_wire ( x1 - 1 , y + 1 ) & & is_wire ( x1 , y + 1 ) & & is_wire ( x1 + 1 , y + 1 ) & &
! is_wire ( x1 - 1 , y + 2 ) & & is_wire ( x1 , y + 2 ) & & ! is_wire ( x1 + 1 , y + 2 ) )
set_emap ( x1 , y + 2 ) ;
else if ( y < YRES / CELL - 1 )
for ( x = x1 ; x < = x2 ; x + + )
if ( is_wire_off ( x , y + 1 ) )
{
if ( x = = x1 | | x = = x2 | | y < 0 | |
is_wire ( x - 1 , y + 1 ) | | is_wire ( x + 1 , y + 1 ) | |
is_wire ( x - 1 , y - 1 ) | | ! is_wire ( x , y - 1 ) | | is_wire ( x + 1 , y - 1 ) )
set_emap ( x , y + 1 ) ;
}
}
int Simulation : : parts_avg ( int ci , int ni , int t )
{
if ( t = = PT_INSL ) //to keep electronics working
{
int pmr = pmap [ ( ( int ) ( parts [ ci ] . y + 0.5f ) + ( int ) ( parts [ ni ] . y + 0.5f ) ) / 2 ] [ ( ( int ) ( parts [ ci ] . x + 0.5f ) + ( int ) ( parts [ ni ] . x + 0.5f ) ) / 2 ] ;
if ( pmr )
return parts [ pmr > > 8 ] . type ;
else
return PT_NONE ;
}
else
{
int pmr2 = pmap [ ( int ) ( ( parts [ ci ] . y + parts [ ni ] . y ) / 2 + 0.5f ) ] [ ( int ) ( ( parts [ ci ] . x + parts [ ni ] . x ) / 2 + 0.5f ) ] ; //seems to be more accurate.
if ( pmr2 )
{
if ( parts [ pmr2 > > 8 ] . type = = t )
return t ;
}
else
return PT_NONE ;
}
return PT_NONE ;
}
int Simulation : : nearest_part ( int ci , int t , int max_d )
{
int distance = ( max_d ! = - 1 ) ? max_d : MAX_DISTANCE ;
int ndistance = 0 ;
int id = - 1 ;
int i = 0 ;
int cx = ( int ) parts [ ci ] . x ;
int cy = ( int ) parts [ ci ] . y ;
for ( i = 0 ; i < = parts_lastActiveIndex ; i + + )
{
if ( ( parts [ i ] . type = = t | | ( t = = - 1 & & parts [ i ] . type ) ) & & ! parts [ i ] . life & & i ! = ci )
{
ndistance = abs ( cx - parts [ i ] . x ) + abs ( cy - parts [ i ] . y ) ; // Faster but less accurate Older: sqrt(pow(cx-parts[i].x, 2)+pow(cy-parts[i].y, 2));
if ( ndistance < distance )
{
distance = ndistance ;
id = i ;
}
}
}
return id ;
}
void Simulation : : create_arc ( int sx , int sy , int dx , int dy , int midpoints , int variance , int type , int flags )
{
int i ;
float xint , yint ;
int * xmid , * ymid ;
int voffset = variance / 2 ;
xmid = ( int * ) calloc ( midpoints + 2 , sizeof ( int ) ) ;
ymid = ( int * ) calloc ( midpoints + 2 , sizeof ( int ) ) ;
xint = ( float ) ( dx - sx ) / ( float ) ( midpoints + 1.0f ) ;
yint = ( float ) ( dy - sy ) / ( float ) ( midpoints + 1.0f ) ;
xmid [ 0 ] = sx ;
xmid [ midpoints + 1 ] = dx ;
ymid [ 0 ] = sy ;
ymid [ midpoints + 1 ] = dy ;
for ( i = 1 ; i < = midpoints ; i + + )
{
ymid [ i ] = ymid [ i - 1 ] + yint ;
xmid [ i ] = xmid [ i - 1 ] + xint ;
}
for ( i = 0 ; i < = midpoints ; i + + )
{
if ( i ! = midpoints )
{
xmid [ i + 1 ] + = ( rand ( ) % variance ) - voffset ;
ymid [ i + 1 ] + = ( rand ( ) % variance ) - voffset ;
}
create_line ( xmid [ i ] , ymid [ i ] , xmid [ i + 1 ] , ymid [ i + 1 ] , 0 , 0 , type , flags ) ;
}
free ( xmid ) ;
free ( ymid ) ;
}
void Simulation : : clear_sim ( void )
{
int i , x , y ;
if ( signs )
memset ( signs , 0 , sizeof ( signs ) ) ;
memset ( bmap , 0 , sizeof ( bmap ) ) ;
memset ( emap , 0 , sizeof ( emap ) ) ;
memset ( parts , 0 , sizeof ( Particle ) * NPART ) ;
for ( i = 0 ; i < NPART - 1 ; i + + )
parts [ i ] . life = i + 1 ;
parts [ NPART - 1 ] . life = - 1 ;
pfree = 0 ;
parts_lastActiveIndex = 0 ;
memset ( pmap , 0 , sizeof ( pmap ) ) ;
if ( pv )
memset ( pv , 0 , sizeof ( pv ) ) ;
if ( vx )
memset ( vx , 0 , sizeof ( vx ) ) ;
if ( vy )
memset ( vy , 0 , sizeof ( vy ) ) ;
if ( fvx )
memset ( fvx , 0 , sizeof ( fvx ) ) ;
if ( fvy )
memset ( fvy , 0 , sizeof ( fvy ) ) ;
memset ( photons , 0 , sizeof ( photons ) ) ;
memset ( wireless , 0 , sizeof ( wireless ) ) ;
memset ( gol2 , 0 , sizeof ( gol2 ) ) ;
memset ( portalp , 0 , sizeof ( portalp ) ) ;
memset ( fighters , 0 , sizeof ( fighters ) ) ;
fighcount = 0 ;
player . spwn = 0 ;
player2 . spwn = 0 ;
//memset(pers_bg, 0, (XRES+BARSIZE)*YRES*PIXELSIZE);
//memset(fire_r, 0, sizeof(fire_r));
//memset(fire_g, 0, sizeof(fire_g));
//memset(fire_b, 0, sizeof(fire_b));
//if(gravmask)
//memset(gravmask, 0xFFFFFFFF, (XRES/CELL)*(YRES/CELL)*sizeof(unsigned));
if ( gravy )
memset ( gravy , 0 , ( XRES / CELL ) * ( YRES / CELL ) * sizeof ( float ) ) ;
if ( gravx )
memset ( gravx , 0 , ( XRES / CELL ) * ( YRES / CELL ) * sizeof ( float ) ) ;
if ( gravp )
memset ( gravp , 0 , ( XRES / CELL ) * ( YRES / CELL ) * sizeof ( float ) ) ;
if ( hv )
for ( x = 0 ; x < XRES / CELL ; x + + ) {
for ( y = 0 ; y < YRES / CELL ; y + + ) {
hv [ y ] [ x ] = 273.15f + 22.0f ; //Set to room temperature
}
}
}
void Simulation : : init_can_move ( )
{
// can_move[moving type][type at destination]
// 0 = No move/Bounce
// 1 = Swap
// 2 = Both particles occupy the same space.
// 3 = Varies, go run some extra checks
int t , rt ;
for ( rt = 0 ; rt < PT_NUM ; rt + + )
can_move [ 0 ] [ rt ] = 0 ; // particles that don't exist shouldn't move...
for ( t = 1 ; t < PT_NUM ; t + + )
for ( rt = 0 ; rt < PT_NUM ; rt + + )
can_move [ t ] [ rt ] = 1 ;
for ( rt = 1 ; rt < PT_NUM ; rt + + )
{
can_move [ PT_PHOT ] [ rt ] = 2 ;
}
for ( t = 1 ; t < PT_NUM ; t + + )
{
for ( rt = 1 ; rt < PT_NUM ; rt + + )
{
// weight check, also prevents particles of same type displacing each other
if ( ptypes [ t ] . weight < = ptypes [ rt ] . weight ) can_move [ t ] [ rt ] = 0 ;
if ( t = = PT_NEUT & & ( ptypes [ rt ] . properties & PROP_NEUTPASS ) )
can_move [ t ] [ rt ] = 2 ;
if ( t = = PT_NEUT & & ( ptypes [ rt ] . properties & PROP_NEUTPENETRATE ) )
can_move [ t ] [ rt ] = 1 ;
if ( ( ptypes [ t ] . properties & PROP_NEUTPENETRATE ) & & rt = = PT_NEUT )
can_move [ t ] [ rt ] = 0 ;
if ( ( ptypes [ t ] . properties & TYPE_ENERGY ) & & ( ptypes [ rt ] . properties & TYPE_ENERGY ) )
can_move [ t ] [ rt ] = 2 ;
}
}
can_move [ PT_DEST ] [ PT_DMND ] = 0 ;
can_move [ PT_BIZR ] [ PT_FILT ] = 2 ;
can_move [ PT_BIZRG ] [ PT_FILT ] = 2 ;
for ( t = 0 ; t < PT_NUM ; t + + )
{
//spark shouldn't move
can_move [ PT_SPRK ] [ t ] = 0 ;
//all stickman collisions are done in stickman update function
can_move [ PT_STKM ] [ t ] = 2 ;
can_move [ PT_STKM2 ] [ t ] = 2 ;
can_move [ PT_FIGH ] [ t ] = 2 ;
}
for ( t = 0 ; t < PT_NUM ; t + + )
{
// make them eat things
can_move [ t ] [ PT_VOID ] = 1 ;
can_move [ t ] [ PT_BHOL ] = 1 ;
can_move [ t ] [ PT_NBHL ] = 1 ;
//all stickman collisions are done in stickman update function
can_move [ t ] [ PT_STKM ] = 2 ;
can_move [ t ] [ PT_STKM2 ] = 2 ;
can_move [ PT_FIGH ] [ t ] = 2 ;
//INVIS behaviour varies with pressure
can_move [ t ] [ PT_INVIS ] = 3 ;
//stop CNCT being displaced by other particles
can_move [ t ] [ PT_CNCT ] = 0 ;
//Powered void behaviour varies on powered state
can_move [ t ] [ PT_PVOD ] = 3 ;
}
for ( t = 0 ; t < PT_NUM ; t + + )
{
if ( t = = PT_GLAS | | t = = PT_PHOT | | t = = PT_CLNE | | t = = PT_PCLN
| | t = = PT_GLOW | | t = = PT_WATR | | t = = PT_DSTW | | t = = PT_SLTW
| | t = = PT_ISOZ | | t = = PT_ISZS | | t = = PT_FILT | | t = = PT_INVIS
| | t = = PT_QRTZ | | t = = PT_PQRT )
can_move [ PT_PHOT ] [ t ] = 2 ;
}
can_move [ PT_ELEC ] [ PT_LCRY ] = 2 ;
can_move [ PT_PHOT ] [ PT_LCRY ] = 3 ; //varies according to LCRY life
can_move [ PT_PHOT ] [ PT_BIZR ] = 2 ;
can_move [ PT_ELEC ] [ PT_BIZR ] = 2 ;
can_move [ PT_PHOT ] [ PT_BIZRG ] = 2 ;
can_move [ PT_ELEC ] [ PT_BIZRG ] = 2 ;
can_move [ PT_PHOT ] [ PT_BIZRS ] = 2 ;
can_move [ PT_ELEC ] [ PT_BIZRS ] = 2 ;
can_move [ PT_NEUT ] [ PT_INVIS ] = 2 ;
//whol eats anar
can_move [ PT_ANAR ] [ PT_WHOL ] = 1 ;
can_move [ PT_ANAR ] [ PT_NWHL ] = 1 ;
}
/*
RETURN - value explenation
1 = Swap
0 = No move / Bounce
2 = Both particles occupy the same space .
*/
int Simulation : : eval_move ( int pt , int nx , int ny , unsigned * rr )
{
unsigned r ;
int result ;
if ( nx < 0 | | ny < 0 | | nx > = XRES | | ny > = YRES )
return 0 ;
r = pmap [ ny ] [ nx ] ;
if ( r )
r = ( r & ~ 0xFF ) | parts [ r > > 8 ] . type ;
if ( rr )
* rr = r ;
if ( pt > = PT_NUM | | ( r & 0xFF ) > = PT_NUM )
return 0 ;
result = can_move [ pt ] [ r & 0xFF ] ;
if ( result = = 3 )
{
if ( ( pt = = PT_PHOT | | pt = = PT_ELEC ) & & ( r & 0xFF ) = = PT_LCRY )
result = ( parts [ r > > 8 ] . life > 5 ) ? 2 : 0 ;
if ( ( r & 0xFF ) = = PT_INVIS )
{
if ( pv [ ny / CELL ] [ nx / CELL ] > 4.0f | | pv [ ny / CELL ] [ nx / CELL ] < - 4.0f ) result = 2 ;
else result = 0 ;
}
if ( ( r & 0xFF ) = = PT_PVOD )
{
if ( parts [ r > > 8 ] . life = = 10 ) result = 1 ;
else result = 0 ;
}
}
if ( bmap [ ny / CELL ] [ nx / CELL ] )
{
if ( bmap [ ny / CELL ] [ nx / CELL ] = = WL_ALLOWGAS & & ! ( ptypes [ pt ] . properties & TYPE_GAS ) ) // && ptypes[pt].falldown!=0 && pt!=PT_FIRE && pt!=PT_SMKE)
return 0 ;
if ( bmap [ ny / CELL ] [ nx / CELL ] = = WL_ALLOWENERGY & & ! ( ptypes [ pt ] . properties & TYPE_ENERGY ) ) // && ptypes[pt].falldown!=0 && pt!=PT_FIRE && pt!=PT_SMKE)
return 0 ;
if ( bmap [ ny / CELL ] [ nx / CELL ] = = WL_ALLOWLIQUID & & ptypes [ pt ] . falldown ! = 2 )
return 0 ;
if ( bmap [ ny / CELL ] [ nx / CELL ] = = WL_ALLOWSOLID & & ptypes [ pt ] . falldown ! = 1 )
return 0 ;
if ( bmap [ ny / CELL ] [ nx / CELL ] = = WL_ALLOWAIR | | bmap [ ny / CELL ] [ nx / CELL ] = = WL_WALL | | bmap [ ny / CELL ] [ nx / CELL ] = = WL_WALLELEC )
return 0 ;
if ( bmap [ ny / CELL ] [ nx / CELL ] = = WL_EWALL & & ! emap [ ny / CELL ] [ nx / CELL ] )
return 0 ;
if ( bmap [ ny / CELL ] [ nx / CELL ] = = WL_EHOLE & & ! emap [ ny / CELL ] [ nx / CELL ] )
return 2 ;
}
return result ;
}
int Simulation : : try_move ( int i , int x , int y , int nx , int ny )
{
unsigned r , e ;
if ( x = = nx & & y = = ny )
return 1 ;
if ( nx < 0 | | ny < 0 | | nx > = XRES | | ny > = YRES )
return 1 ;
e = eval_move ( parts [ i ] . type , nx , ny , & r ) ;
if ( ( r & 0xFF ) = = PT_BOMB & & parts [ i ] . type = = PT_BOMB & & parts [ i ] . tmp = = 1 )
e = 2 ;
/* half-silvered mirror */
if ( ! e & & parts [ i ] . type = = PT_PHOT & &
( ( ( r & 0xFF ) = = PT_BMTL & & rand ( ) < RAND_MAX / 2 ) | |
( pmap [ y ] [ x ] & 0xFF ) = = PT_BMTL ) )
e = 2 ;
if ( ! e ) //if no movement
{
if ( parts [ i ] . type ! = PT_NEUT & & parts [ i ] . type ! = PT_PHOT )
return 0 ;
if ( ! legacy_enable & & parts [ i ] . type = = PT_PHOT & & r ) //PHOT heat conduction
{
if ( ( r & 0xFF ) = = PT_COAL | | ( r & 0xFF ) = = PT_BCOL )
parts [ r > > 8 ] . temp = parts [ i ] . temp ;
if ( ( r & 0xFF ) < PT_NUM & & ptypes [ r & 0xFF ] . hconduct & & ( ( r & 0xFF ) ! = PT_HSWC | | parts [ r > > 8 ] . life = = 10 ) & & ( r & 0xFF ) ! = PT_FILT )
parts [ i ] . temp = parts [ r > > 8 ] . temp = restrict_flt ( ( parts [ r > > 8 ] . temp + parts [ i ] . temp ) / 2 , MIN_TEMP , MAX_TEMP ) ;
}
if ( ( parts [ i ] . type = = PT_NEUT | | parts [ i ] . type = = PT_ELEC ) & & ( ( r & 0xFF ) = = PT_CLNE | | ( r & 0xFF ) = = PT_PCLN | | ( r & 0xFF ) = = PT_BCLN | | ( r & 0xFF ) = = PT_PBCN ) ) {
if ( ! parts [ r > > 8 ] . ctype )
parts [ r > > 8 ] . ctype = parts [ i ] . type ;
}
if ( ( r & 0xFF ) = = PT_PRTI & & ( parts [ i ] . type = = PT_PHOT | | parts [ i ] . type = = PT_NEUT | | parts [ i ] . type = = PT_ELEC ) )
{
int nnx , count ;
for ( count = 0 ; count < 8 ; count + + )
{
if ( isign ( x - nx ) = = isign ( portal_rx [ count ] ) & & isign ( y - ny ) = = isign ( portal_ry [ count ] ) )
break ;
}
count = count % 8 ;
parts [ r > > 8 ] . tmp = ( int ) ( ( parts [ r > > 8 ] . temp - 73.15f ) / 100 + 1 ) ;
if ( parts [ r > > 8 ] . tmp > = CHANNELS ) parts [ r > > 8 ] . tmp = CHANNELS - 1 ;
else if ( parts [ r > > 8 ] . tmp < 0 ) parts [ r > > 8 ] . tmp = 0 ;
for ( nnx = 0 ; nnx < 80 ; nnx + + )
if ( ! portalp [ parts [ r > > 8 ] . tmp ] [ count ] [ nnx ] . type )
{
portalp [ parts [ r > > 8 ] . tmp ] [ count ] [ nnx ] = parts [ i ] ;
parts [ i ] . type = PT_NONE ;
break ;
}
}
return 0 ;
}
if ( e = = 2 ) //if occupy same space
{
if ( parts [ i ] . type = = PT_PHOT & & ( r & 0xFF ) = = PT_GLOW & & ! parts [ r > > 8 ] . life )
if ( rand ( ) < RAND_MAX / 30 )
{
parts [ r > > 8 ] . life = 120 ;
create_gain_photon ( i ) ;
}
if ( parts [ i ] . type = = PT_PHOT & & ( r & 0xFF ) = = PT_FILT )
{
int temp_bin = ( int ) ( ( parts [ r > > 8 ] . temp - 273.0f ) * 0.025f ) ;
if ( temp_bin < 0 ) temp_bin = 0 ;
if ( temp_bin > 25 ) temp_bin = 25 ;
if ( ! parts [ r > > 8 ] . tmp ) {
parts [ i ] . ctype = 0x1F < < temp_bin ; //Assign Colour
} else if ( parts [ r > > 8 ] . tmp = = 1 ) {
parts [ i ] . ctype & = 0x1F < < temp_bin ; //Filter Colour
} else if ( parts [ r > > 8 ] . tmp = = 2 ) {
parts [ i ] . ctype | = 0x1F < < temp_bin ; //Add Colour
} else if ( parts [ r > > 8 ] . tmp = = 3 ) {
parts [ i ] . ctype & = ~ ( 0x1F < < temp_bin ) ; //Subtract Colour
}
}
if ( parts [ i ] . type = = PT_NEUT & & ( r & 0xFF ) = = PT_GLAS ) {
if ( rand ( ) < RAND_MAX / 10 )
create_cherenkov_photon ( i ) ;
}
if ( parts [ i ] . type = = PT_PHOT & & ( r & 0xFF ) = = PT_INVIS & & pv [ ny / CELL ] [ nx / CELL ] < = 4.0f & & pv [ ny / CELL ] [ nx / CELL ] > = - 4.0f ) {
part_change_type ( i , x , y , PT_NEUT ) ;
parts [ i ] . ctype = 0 ;
}
if ( ( parts [ i ] . type = = PT_BIZR | | parts [ i ] . type = = PT_BIZRG ) & & ( r & 0xFF ) = = PT_FILT )
{
int temp_bin = ( int ) ( ( parts [ r > > 8 ] . temp - 273.0f ) * 0.025f ) ;
if ( temp_bin < 0 ) temp_bin = 0 ;
if ( temp_bin > 25 ) temp_bin = 25 ;
parts [ i ] . ctype = 0x1F < < temp_bin ;
}
return 1 ;
}
//else e=1 , we are trying to swap the particles, return 0 no swap/move, 1 is still overlap/move, because the swap takes place later
if ( ( r & 0xFF ) = = PT_VOID | | ( r & 0xFF ) = = PT_PVOD ) //this is where void eats particles
{
if ( parts [ i ] . type = = PT_STKM )
{
player . spwn = 0 ;
}
if ( parts [ i ] . type = = PT_STKM2 )
{
player2 . spwn = 0 ;
}
if ( parts [ i ] . type = = PT_FIGH )
{
fighters [ ( unsigned char ) parts [ i ] . tmp ] . spwn = 0 ;
fighcount - - ;
}
parts [ i ] . type = PT_NONE ;
return 0 ;
}
if ( ( r & 0xFF ) = = PT_BHOL | | ( r & 0xFF ) = = PT_NBHL ) //this is where blackhole eats particles
{
if ( parts [ i ] . type = = PT_STKM )
{
player . spwn = 0 ;
}
if ( parts [ i ] . type = = PT_STKM2 )
{
player2 . spwn = 0 ;
}
if ( parts [ i ] . type = = PT_FIGH )
{
fighters [ ( unsigned char ) parts [ i ] . tmp ] . spwn = 0 ;
fighcount - - ;
}
parts [ i ] . type = PT_NONE ;
if ( ! legacy_enable )
{
parts [ r > > 8 ] . temp = restrict_flt ( parts [ r > > 8 ] . temp + parts [ i ] . temp / 2 , MIN_TEMP , MAX_TEMP ) ; //3.0f;
}
return 0 ;
}
if ( ( ( r & 0xFF ) = = PT_WHOL | | ( r & 0xFF ) = = PT_NWHL ) & & parts [ i ] . type = = PT_ANAR ) //whitehole eats anar
{
parts [ i ] . type = PT_NONE ;
if ( ! legacy_enable )
{
parts [ r > > 8 ] . temp = restrict_flt ( parts [ r > > 8 ] . temp - ( MAX_TEMP - parts [ i ] . temp ) / 2 , MIN_TEMP , MAX_TEMP ) ;
}
return 0 ;
}
if ( parts [ i ] . type = = PT_CNCT & & y < ny & & ( pmap [ y + 1 ] [ x ] & 0xFF ) = = PT_CNCT ) //check below CNCT for another CNCT
return 0 ;
if ( ( bmap [ y / CELL ] [ x / CELL ] = = WL_EHOLE & & ! emap [ y / CELL ] [ x / CELL ] ) & & ! ( bmap [ ny / CELL ] [ nx / CELL ] = = WL_EHOLE & & ! emap [ ny / CELL ] [ nx / CELL ] ) )
return 0 ;
if ( parts [ i ] . type = = PT_GBMB & & parts [ i ] . life > 0 )
return 0 ;
e = r > > 8 ; //e is now the particle number at r (pmap[ny][nx])
if ( r ) //the swap part, if we make it this far, swap
{
if ( parts [ i ] . type = = PT_NEUT ) {
// target material is NEUTPENETRATE, meaning it gets moved around when neutron passes
unsigned s = pmap [ y ] [ x ] ;
if ( ! ( ptypes [ s & 0xFF ] . properties & PROP_NEUTPENETRATE ) )
return 1 ; // if the element currently underneath neutron isn't NEUTPENETRATE, don't move anything except the neutron
// if nothing is currently underneath neutron, only move target particle
if ( s )
{
pmap [ ny ] [ nx ] = ( s & ~ ( 0xFF ) ) | parts [ s > > 8 ] . type ;
parts [ s > > 8 ] . x = nx ;
parts [ s > > 8 ] . y = ny ;
}
else pmap [ ny ] [ nx ] = 0 ;
parts [ e ] . x = x ;
parts [ e ] . y = y ;
pmap [ y ] [ x ] = ( e < < 8 ) | parts [ e ] . type ;
return 1 ;
}
if ( ( pmap [ ny ] [ nx ] > > 8 ) = = e ) pmap [ ny ] [ nx ] = 0 ;
parts [ e ] . x + = x - nx ;
parts [ e ] . y + = y - ny ;
pmap [ ( int ) ( parts [ e ] . y + 0.5f ) ] [ ( int ) ( parts [ e ] . x + 0.5f ) ] = ( e < < 8 ) | parts [ e ] . type ;
}
return 1 ;
}
// try to move particle, and if successful update pmap and parts[i].x,y
int Simulation : : do_move ( int i , int x , int y , float nxf , float nyf )
{
int nx = ( int ) ( nxf + 0.5f ) , ny = ( int ) ( nyf + 0.5f ) ;
int result = try_move ( i , x , y , nx , ny ) ;
if ( result )
{
int t = parts [ i ] . type ;
parts [ i ] . x = nxf ;
parts [ i ] . y = nyf ;
if ( ny ! = y | | nx ! = x )
{
if ( ( pmap [ y ] [ x ] > > 8 ) = = i ) pmap [ y ] [ x ] = 0 ;
else if ( ( photons [ y ] [ x ] > > 8 ) = = i ) photons [ y ] [ x ] = 0 ;
if ( nx < CELL | | nx > = XRES - CELL | | ny < CELL | | ny > = YRES - CELL ) //kill_part if particle is out of bounds
{
kill_part ( i ) ;
return - 1 ;
}
if ( t = = PT_PHOT | | t = = PT_NEUT | | t = = PT_ELEC )
photons [ ny ] [ nx ] = t | ( i < < 8 ) ;
else if ( t )
pmap [ ny ] [ nx ] = t | ( i < < 8 ) ;
}
}
return result ;
}
int Simulation : : pn_junction_sprk ( int x , int y , int pt )
{
unsigned r = pmap [ y ] [ x ] ;
if ( ( r & 0xFF ) ! = pt )
return 0 ;
r > > = 8 ;
if ( parts [ r ] . type ! = pt )
return 0 ;
if ( parts [ r ] . life ! = 0 )
return 0 ;
parts [ r ] . ctype = pt ;
part_change_type ( r , x , y , PT_SPRK ) ;
parts [ r ] . life = 4 ;
return 1 ;
}
void Simulation : : photoelectric_effect ( int nx , int ny ) //create sparks from PHOT when hitting PSCN and NSCN
{
unsigned r = pmap [ ny ] [ nx ] ;
if ( ( r & 0xFF ) = = PT_PSCN ) {
if ( ( pmap [ ny ] [ nx - 1 ] & 0xFF ) = = PT_NSCN | |
( pmap [ ny ] [ nx + 1 ] & 0xFF ) = = PT_NSCN | |
( pmap [ ny - 1 ] [ nx ] & 0xFF ) = = PT_NSCN | |
( pmap [ ny + 1 ] [ nx ] & 0xFF ) = = PT_NSCN )
pn_junction_sprk ( nx , ny , PT_PSCN ) ;
}
}
unsigned Simulation : : direction_to_map ( float dx , float dy , int t )
{
// TODO:
// Adding extra directions causes some inaccuracies.
// Not adding them causes problems with some diagonal surfaces (photons absorbed instead of reflected).
// For now, don't add them.
// Solution may involve more intelligent setting of initial i0 value in find_next_boundary?
// or rewriting normal/boundary finding code
return ( dx > = 0 ) |
( ( ( dx + dy ) > = 0 ) < < 1 ) | /* 567 */
( ( dy > = 0 ) < < 2 ) | /* 4+0 */
( ( ( dy - dx ) > = 0 ) < < 3 ) | /* 321 */
( ( dx < = 0 ) < < 4 ) |
( ( ( dx + dy ) < = 0 ) < < 5 ) |
( ( dy < = 0 ) < < 6 ) |
( ( ( dy - dx ) < = 0 ) < < 7 ) ;
/*
return ( dx > = - 0.001 ) |
( ( ( dx + dy ) > = - 0.001 ) < < 1 ) | // 567
( ( dy > = - 0.001 ) < < 2 ) | // 4+0
( ( ( dy - dx ) > = - 0.001 ) < < 3 ) | // 321
( ( dx < = 0.001 ) < < 4 ) |
( ( ( dx + dy ) < = 0.001 ) < < 5 ) |
( ( dy < = 0.001 ) < < 6 ) |
( ( ( dy - dx ) < = 0.001 ) < < 7 ) ;
} */
}
int Simulation : : is_blocking ( int t , int x , int y )
{
if ( t & REFRACT ) {
if ( x < 0 | | y < 0 | | x > = XRES | | y > = YRES )
return 0 ;
if ( ( pmap [ y ] [ x ] & 0xFF ) = = PT_GLAS )
return 1 ;
return 0 ;
}
return ! eval_move ( t , x , y , NULL ) ;
}
int Simulation : : is_boundary ( int pt , int x , int y )
{
if ( ! is_blocking ( pt , x , y ) )
return 0 ;
if ( is_blocking ( pt , x , y - 1 ) & & is_blocking ( pt , x , y + 1 ) & & is_blocking ( pt , x - 1 , y ) & & is_blocking ( pt , x + 1 , y ) )
return 0 ;
return 1 ;
}
int Simulation : : find_next_boundary ( int pt , int * x , int * y , int dm , int * em )
{
static int dx [ 8 ] = { 1 , 1 , 0 , - 1 , - 1 , - 1 , 0 , 1 } ;
static int dy [ 8 ] = { 0 , 1 , 1 , 1 , 0 , - 1 , - 1 , - 1 } ;
static int de [ 8 ] = { 0x83 , 0x07 , 0x0E , 0x1C , 0x38 , 0x70 , 0xE0 , 0xC1 } ;
int i , ii , i0 ;
if ( * x < = 0 | | * x > = XRES - 1 | | * y < = 0 | | * y > = YRES - 1 )
return 0 ;
if ( * em ! = - 1 ) {
i0 = * em ;
dm & = de [ i0 ] ;
} else
i0 = 0 ;
for ( ii = 0 ; ii < 8 ; ii + + ) {
i = ( ii + i0 ) & 7 ;
if ( ( dm & ( 1 < < i ) ) & & is_boundary ( pt , * x + dx [ i ] , * y + dy [ i ] ) ) {
* x + = dx [ i ] ;
* y + = dy [ i ] ;
* em = i ;
return 1 ;
}
}
return 0 ;
}
int Simulation : : get_normal ( int pt , int x , int y , float dx , float dy , float * nx , float * ny )
{
int ldm , rdm , lm , rm ;
int lx , ly , lv , rx , ry , rv ;
int i , j ;
float r , ex , ey ;
if ( ! dx & & ! dy )
return 0 ;
if ( ! is_boundary ( pt , x , y ) )
return 0 ;
ldm = direction_to_map ( - dy , dx , pt ) ;
rdm = direction_to_map ( dy , - dx , pt ) ;
lx = rx = x ;
ly = ry = y ;
lv = rv = 1 ;
lm = rm = - 1 ;
j = 0 ;
for ( i = 0 ; i < SURF_RANGE ; i + + ) {
if ( lv )
lv = find_next_boundary ( pt , & lx , & ly , ldm , & lm ) ;
if ( rv )
rv = find_next_boundary ( pt , & rx , & ry , rdm , & rm ) ;
j + = lv + rv ;
if ( ! lv & & ! rv )
break ;
}
if ( j < NORMAL_MIN_EST )
return 0 ;
if ( ( lx = = rx ) & & ( ly = = ry ) )
return 0 ;
ex = rx - lx ;
ey = ry - ly ;
r = 1.0f / hypot ( ex , ey ) ;
* nx = ey * r ;
* ny = - ex * r ;
return 1 ;
}
int Simulation : : get_normal_interp ( int pt , float x0 , float y0 , float dx , float dy , float * nx , float * ny )
{
int x , y , i ;
dx / = NORMAL_FRAC ;
dy / = NORMAL_FRAC ;
for ( i = 0 ; i < NORMAL_INTERP ; i + + ) {
x = ( int ) ( x0 + 0.5f ) ;
y = ( int ) ( y0 + 0.5f ) ;
if ( is_boundary ( pt , x , y ) )
break ;
x0 + = dx ;
y0 + = dy ;
}
if ( i > = NORMAL_INTERP )
return 0 ;
if ( pt = = PT_PHOT )
photoelectric_effect ( x , y ) ;
return get_normal ( pt , x , y , dx , dy , nx , ny ) ;
}
//For soap only
void Simulation : : detach ( int i )
{
if ( ( parts [ i ] . ctype & 2 ) = = 2 )
{
if ( ( parts [ parts [ i ] . tmp ] . ctype & 4 ) = = 4 )
parts [ parts [ i ] . tmp ] . ctype ^ = 4 ;
}
if ( ( parts [ i ] . ctype & 4 ) = = 4 )
{
if ( ( parts [ parts [ i ] . tmp2 ] . ctype & 2 ) = = 2 )
parts [ parts [ i ] . tmp2 ] . ctype ^ = 2 ;
}
parts [ i ] . ctype = 0 ;
}
void Simulation : : kill_part ( int i ) //kills particle number i
{
int x , y ;
if ( elementCount [ parts [ i ] . type ] & & parts [ i ] . type )
elementCount [ parts [ i ] . type ] - - ;
x = ( int ) ( parts [ i ] . x + 0.5f ) ;
y = ( int ) ( parts [ i ] . y + 0.5f ) ;
if ( parts [ i ] . type = = PT_STKM )
{
player . spwn = 0 ;
}
if ( parts [ i ] . type = = PT_STKM2 )
{
player2 . spwn = 0 ;
}
if ( parts [ i ] . type = = PT_FIGH )
{
fighters [ ( unsigned char ) parts [ i ] . tmp ] . spwn = 0 ;
fighcount - - ;
}
if ( parts [ i ] . type = = PT_SOAP )
{
detach ( i ) ;
}
if ( x > = 0 & & y > = 0 & & x < XRES & & y < YRES ) {
if ( ( pmap [ y ] [ x ] > > 8 ) = = i )
pmap [ y ] [ x ] = 0 ;
else if ( ( photons [ y ] [ x ] > > 8 ) = = i )
photons [ y ] [ x ] = 0 ;
}
parts [ i ] . type = PT_NONE ;
parts [ i ] . life = pfree ;
pfree = i ;
}
void Simulation : : part_change_type ( int i , int x , int y , int t ) //changes the type of particle number i, to t. This also changes pmap at the same time.
{
if ( x < 0 | | y < 0 | | x > = XRES | | y > = YRES | | i > = NPART | | t < 0 | | t > = PT_NUM )
return ;
if ( ! ptypes [ t ] . enabled )
t = PT_NONE ;
if ( parts [ i ] . type = = PT_STKM )
player . spwn = 0 ;
if ( parts [ i ] . type = = PT_STKM2 )
player2 . spwn = 0 ;
if ( parts [ i ] . type = = PT_FIGH )
{
fighters [ ( unsigned char ) parts [ i ] . tmp ] . spwn = 0 ;
fighcount - - ;
}
parts [ i ] . type = t ;
if ( t = = PT_PHOT | | t = = PT_NEUT | | t = = PT_ELEC )
{
photons [ y ] [ x ] = t | ( i < < 8 ) ;
if ( ( pmap [ y ] [ x ] > > 8 ) = = i )
pmap [ y ] [ x ] = 0 ;
}
else
{
pmap [ y ] [ x ] = t | ( i < < 8 ) ;
if ( ( photons [ y ] [ x ] > > 8 ) = = i )
photons [ y ] [ x ] = 0 ;
}
}
int Simulation : : create_part ( int p , int x , int y , int tv ) //the function for creating a particle, use p=-1 for creating a new particle, -2 is from a brush, or a particle number to replace a particle.
{
int i ;
int t = tv & 0xFF ;
int v = ( tv > > 8 ) & 0xFF ;
if ( x < 0 | | y < 0 | | x > = XRES | | y > = YRES | | ( ( t < 0 | | t > = PT_NUM ) & & t ! = SPC_HEAT & & t ! = SPC_COOL & & t ! = SPC_AIR & & t ! = SPC_VACUUM & & t ! = SPC_PGRV & & t ! = SPC_NGRV ) )
return - 1 ;
if ( t > = 0 & & t < PT_NUM & & ! ptypes [ t ] . enabled )
return - 1 ;
if ( t = = SPC_PROP ) {
return - 1 ; //Prop tool works on a mouse click basic, make sure it doesn't do anything here
}
/*if (t==SPC_HEAT||t==SPC_COOL)
{
if ( ( pmap [ y ] [ x ] & 0xFF ) ! = PT_NONE & & ( pmap [ y ] [ x ] & 0xFF ) < PT_NUM )
{
if ( t = = SPC_HEAT & & parts [ pmap [ y ] [ x ] > > 8 ] . temp < MAX_TEMP )
{
if ( ( pmap [ y ] [ x ] & 0xFF ) = = PT_PUMP | | ( pmap [ y ] [ x ] & 0xFF ) = = PT_GPMP ) {
parts [ pmap [ y ] [ x ] > > 8 ] . temp = restrict_flt ( parts [ pmap [ y ] [ x ] > > 8 ] . temp + 0.1f , MIN_TEMP , MAX_TEMP ) ;
} else if ( ( sdl_mod & ( KMOD_SHIFT ) ) & & ( sdl_mod & ( KMOD_CTRL ) ) ) {
parts [ pmap [ y ] [ x ] > > 8 ] . temp = restrict_flt ( parts [ pmap [ y ] [ x ] > > 8 ] . temp + 50.0f , MIN_TEMP , MAX_TEMP ) ;
} else {
parts [ pmap [ y ] [ x ] > > 8 ] . temp = restrict_flt ( parts [ pmap [ y ] [ x ] > > 8 ] . temp + 4.0f , MIN_TEMP , MAX_TEMP ) ;
}
}
if ( t = = SPC_COOL & & parts [ pmap [ y ] [ x ] > > 8 ] . temp > MIN_TEMP )
{
if ( ( pmap [ y ] [ x ] & 0xFF ) = = PT_PUMP | | ( pmap [ y ] [ x ] & 0xFF ) = = PT_GPMP ) {
parts [ pmap [ y ] [ x ] > > 8 ] . temp = restrict_flt ( parts [ pmap [ y ] [ x ] > > 8 ] . temp - 0.1f , MIN_TEMP , MAX_TEMP ) ;
} else if ( ( sdl_mod & ( KMOD_SHIFT ) ) & & ( sdl_mod & ( KMOD_CTRL ) ) ) {
parts [ pmap [ y ] [ x ] > > 8 ] . temp = restrict_flt ( parts [ pmap [ y ] [ x ] > > 8 ] . temp - 50.0f , MIN_TEMP , MAX_TEMP ) ;
} else {
parts [ pmap [ y ] [ x ] > > 8 ] . temp = restrict_flt ( parts [ pmap [ y ] [ x ] > > 8 ] . temp - 4.0f , MIN_TEMP , MAX_TEMP ) ;
}
}
return pmap [ y ] [ x ] > > 8 ;
}
else
{
return - 1 ;
}
} */
if ( t = = SPC_AIR )
{
pv [ y / CELL ] [ x / CELL ] + = 0.03f ;
if ( y + CELL < YRES )
pv [ y / CELL + 1 ] [ x / CELL ] + = 0.03f ;
if ( x + CELL < XRES )
{
pv [ y / CELL ] [ x / CELL + 1 ] + = 0.03f ;
if ( y + CELL < YRES )
pv [ y / CELL + 1 ] [ x / CELL + 1 ] + = 0.03f ;
}
return - 1 ;
}
if ( t = = SPC_VACUUM )
{
pv [ y / CELL ] [ x / CELL ] - = 0.03f ;
if ( y + CELL < YRES )
pv [ y / CELL + 1 ] [ x / CELL ] - = 0.03f ;
if ( x + CELL < XRES )
{
pv [ y / CELL ] [ x / CELL + 1 ] - = 0.03f ;
if ( y + CELL < YRES )
pv [ y / CELL + 1 ] [ x / CELL + 1 ] - = 0.03f ;
}
return - 1 ;
}
if ( t = = SPC_PGRV )
{
gravmap [ ( y / CELL ) * ( XRES / CELL ) + ( x / CELL ) ] = 5 ;
return - 1 ;
}
if ( t = = SPC_NGRV )
{
gravmap [ ( y / CELL ) * ( XRES / CELL ) + ( x / CELL ) ] = - 5 ;
return - 1 ;
}
if ( t = = PT_SPRK )
{
if ( ( pmap [ y ] [ x ] & 0xFF ) = = PT_WIRE ) {
parts [ pmap [ y ] [ x ] > > 8 ] . ctype = PT_DUST ;
}
if ( ! ( ( pmap [ y ] [ x ] & 0xFF ) = = PT_INST | | ( ptypes [ pmap [ y ] [ x ] & 0xFF ] . properties & PROP_CONDUCTS ) ) )
return - 1 ;
if ( parts [ pmap [ y ] [ x ] > > 8 ] . life ! = 0 )
return - 1 ;
parts [ pmap [ y ] [ x ] > > 8 ] . type = PT_SPRK ;
parts [ pmap [ y ] [ x ] > > 8 ] . life = 4 ;
parts [ pmap [ y ] [ x ] > > 8 ] . ctype = pmap [ y ] [ x ] & 0xFF ;
pmap [ y ] [ x ] = ( pmap [ y ] [ x ] & ~ 0xFF ) | PT_SPRK ;
return pmap [ y ] [ x ] > > 8 ;
}
if ( t = = PT_SPAWN & & elementCount [ PT_SPAWN ] )
return - 1 ;
if ( t = = PT_SPAWN2 & & elementCount [ PT_SPAWN2 ] )
return - 1 ;
if ( p = = - 1 ) //creating from anything but brush
{
if ( pmap [ y ] [ x ] | | ( bmap [ y / CELL ] [ x / CELL ] & & ! eval_move ( t , x , y , NULL ) ) )
{
if ( ( pmap [ y ] [ x ] & 0xFF ) ! = PT_SPAWN & & ( pmap [ y ] [ x ] & 0xFF ) ! = PT_SPAWN2 )
{
if ( t ! = PT_STKM & & t ! = PT_STKM2 & & t ! = PT_FIGH )
{
return - 1 ;
}
}
}
if ( pfree = = - 1 )
return - 1 ;
i = pfree ;
pfree = parts [ i ] . life ;
}
else if ( p = = - 2 ) //creating from brush
{
if ( pmap [ y ] [ x ] )
{
if ( (
( ( pmap [ y ] [ x ] & 0xFF ) = = PT_STOR & & ! ( ptypes [ t ] . properties & TYPE_SOLID ) ) | |
( pmap [ y ] [ x ] & 0xFF ) = = PT_CLNE | |
( pmap [ y ] [ x ] & 0xFF ) = = PT_BCLN | |
( pmap [ y ] [ x ] & 0xFF ) = = PT_CONV | |
( ( pmap [ y ] [ x ] & 0xFF ) = = PT_PCLN & & t ! = PT_PSCN & & t ! = PT_NSCN ) | |
( ( pmap [ y ] [ x ] & 0xFF ) = = PT_PBCN & & t ! = PT_PSCN & & t ! = PT_NSCN )
) & & (
t ! = PT_CLNE & & t ! = PT_PCLN & &
t ! = PT_BCLN & & t ! = PT_STKM & &
t ! = PT_STKM2 & & t ! = PT_PBCN & &
t ! = PT_STOR & & t ! = PT_FIGH )
)
{
parts [ pmap [ y ] [ x ] > > 8 ] . ctype = t ;
if ( t = = PT_LIFE & & v < NGOLALT & & ( pmap [ y ] [ x ] & 0xFF ) ! = PT_STOR ) parts [ pmap [ y ] [ x ] > > 8 ] . tmp = v ;
}
return - 1 ;
}
if ( photons [ y ] [ x ] & & ( t = = PT_PHOT | | t = = PT_NEUT | | t = = PT_ELEC ) )
return - 1 ;
if ( pfree = = - 1 )
return - 1 ;
i = pfree ;
pfree = parts [ i ] . life ;
}
else if ( p = = - 3 ) //skip pmap checks, e.g. for sing explosion
{
if ( pfree = = - 1 )
return - 1 ;
i = pfree ;
pfree = parts [ i ] . life ;
}
else
{
int oldX = ( int ) ( parts [ p ] . x + 0.5f ) ;
int oldY = ( int ) ( parts [ p ] . y + 0.5f ) ;
if ( ( pmap [ oldY ] [ oldX ] > > 8 ) = = p )
pmap [ oldY ] [ oldX ] = 0 ;
if ( ( photons [ oldY ] [ oldX ] > > 8 ) = = p )
photons [ oldY ] [ oldX ] = 0 ;
i = p ;
}
if ( i > parts_lastActiveIndex ) parts_lastActiveIndex = i ;
parts [ i ] . dcolour = 0 ;
if ( t = = PT_GLAS )
{
parts [ i ] . pavg [ 1 ] = pv [ y / CELL ] [ x / CELL ] ;
}
else if ( t = = PT_QRTZ )
{
parts [ i ] . pavg [ 1 ] = pv [ y / CELL ] [ x / CELL ] ;
}
else
{
parts [ i ] . pavg [ 0 ] = 0.0f ;
parts [ i ] . pavg [ 1 ] = 0.0f ;
}
if ( t ! = PT_STKM & & t ! = PT_STKM2 & & t ! = PT_FIGH ) //set everything to default values first, except for stickman.
{
parts [ i ] . x = ( float ) x ;
parts [ i ] . y = ( float ) y ;
parts [ i ] . type = t ;
parts [ i ] . vx = 0 ;
parts [ i ] . vy = 0 ;
parts [ i ] . life = 0 ;
parts [ i ] . ctype = 0 ;
parts [ i ] . temp = ptypes [ t ] . heat ;
parts [ i ] . tmp = 0 ;
parts [ i ] . tmp2 = 0 ;
}
if ( t = = PT_LIGH & & p = = - 2 )
{
switch ( gravityMode )
{
default :
case 0 :
parts [ i ] . tmp = 270 + rand ( ) % 40 - 20 ;
break ;
case 1 :
parts [ i ] . tmp = rand ( ) % 360 ;
break ;
case 2 :
parts [ i ] . tmp = atan2 ( x - XCNTR , y - YCNTR ) * ( 180.0f / M_PI ) + 90 ;
break ;
}
parts [ i ] . tmp2 = 4 ;
}
if ( t = = PT_SOAP )
{
parts [ i ] . tmp = - 1 ;
parts [ i ] . tmp2 = - 1 ;
}
//now set various properties that we want at spawn.
if ( t = = PT_ACID | | t = = PT_CAUS )
{
parts [ i ] . life = 75 ;
}
/*Testing
if ( t = = PT_WOOD ) {
parts [ i ] . life = 150 ;
}
End Testing */
if ( t = = PT_WARP ) {
parts [ i ] . life = rand ( ) % 95 + 70 ;
}
if ( t = = PT_FUSE ) {
parts [ i ] . life = 50 ;
parts [ i ] . tmp = 50 ;
}
/*if (ptypes[t].properties&PROP_LIFE) {
int r ;
for ( r = 0 ; r < NGOL ; r + + )
if ( t = = goltype [ r ] )
parts [ i ] . tmp = grule [ r + 1 ] [ 9 ] - 1 ;
} */
if ( t = = PT_LIFE & & v < NGOLALT )
{
parts [ i ] . tmp = grule [ v + 1 ] [ 9 ] - 1 ;
parts [ i ] . ctype = v ;
}
if ( t = = PT_DEUT )
parts [ i ] . life = 10 ;
if ( t = = PT_MERC )
parts [ i ] . tmp = 10 ;
if ( t = = PT_BRAY )
parts [ i ] . life = 30 ;
if ( t = = PT_PUMP )
parts [ i ] . life = 10 ;
if ( t = = PT_SING )
parts [ i ] . life = rand ( ) % 50 + 60 ;
if ( t = = PT_QRTZ )
parts [ i ] . tmp = ( rand ( ) % 11 ) ;
if ( t = = PT_PQRT )
parts [ i ] . tmp = ( rand ( ) % 11 ) ;
if ( t = = PT_CLST )
parts [ i ] . tmp = ( rand ( ) % 7 ) ;
if ( t = = PT_FSEP )
parts [ i ] . life = 50 ;
if ( t = = PT_COAL ) {
parts [ i ] . life = 110 ;
parts [ i ] . tmp = 50 ;
}
if ( t = = PT_IGNT ) {
parts [ i ] . life = 3 ;
}
if ( t = = PT_FRZW )
parts [ i ] . life = 100 ;
if ( t = = PT_PIPE )
parts [ i ] . life = 60 ;
if ( t = = PT_BCOL )
parts [ i ] . life = 110 ;
if ( t = = PT_FIRE )
parts [ i ] . life = rand ( ) % 50 + 120 ;
if ( t = = PT_PLSM )
parts [ i ] . life = rand ( ) % 150 + 50 ;
if ( t = = PT_HFLM )
parts [ i ] . life = rand ( ) % 150 + 50 ;
if ( t = = PT_LAVA )
parts [ i ] . life = rand ( ) % 120 + 240 ;
if ( t = = PT_NBLE )
parts [ i ] . life = 0 ;
if ( t = = PT_ICEI )
parts [ i ] . ctype = PT_WATR ;
if ( t = = PT_NEUT )
{
float r = ( rand ( ) % 128 + 128 ) / 127.0f ;
float a = ( rand ( ) % 360 ) * 3.14159f / 180.0f ;
parts [ i ] . life = rand ( ) % 480 + 480 ;
parts [ i ] . vx = r * cosf ( a ) ;
parts [ i ] . vy = r * sinf ( a ) ;
}
if ( t = = PT_MORT )
{
parts [ i ] . vx = 2 ;
}
if ( t = = PT_PHOT )
{
float a = ( rand ( ) % 8 ) * 0.78540f ;
parts [ i ] . life = 680 ;
parts [ i ] . ctype = 0x3FFFFFFF ;
parts [ i ] . vx = 3.0f * cosf ( a ) ;
parts [ i ] . vy = 3.0f * sinf ( a ) ;
}
if ( t = = PT_ELEC )
{
float a = ( rand ( ) % 360 ) * 3.14159f / 180.0f ;
parts [ i ] . life = 680 ;
parts [ i ] . vx = 2.0f * cosf ( a ) ;
parts [ i ] . vy = 2.0f * sinf ( a ) ;
}
if ( t = = PT_STKM )
{
if ( player . spwn = = 0 )
{
parts [ i ] . x = ( float ) x ;
parts [ i ] . y = ( float ) y ;
parts [ i ] . type = PT_STKM ;
parts [ i ] . vx = 0 ;
parts [ i ] . vy = 0 ;
parts [ i ] . life = 100 ;
parts [ i ] . ctype = 0 ;
parts [ i ] . temp = ptypes [ t ] . heat ;
STKM_init_legs ( this , & player , i ) ;
player . spwn = 1 ;
}
else
{
return - 1 ;
}
create_part ( - 1 , x , y , PT_SPAWN ) ;
}
if ( t = = PT_STKM2 )
{
if ( player2 . spwn = = 0 )
{
parts [ i ] . x = ( float ) x ;
parts [ i ] . y = ( float ) y ;
parts [ i ] . type = PT_STKM2 ;
parts [ i ] . vx = 0 ;
parts [ i ] . vy = 0 ;
parts [ i ] . life = 100 ;
parts [ i ] . ctype = 0 ;
parts [ i ] . temp = ptypes [ t ] . heat ;
STKM_init_legs ( this , & player2 , i ) ;
player2 . spwn = 1 ;
}
else
{
return - 1 ;
}
create_part ( - 1 , x , y , PT_SPAWN2 ) ;
}
if ( t = = PT_FIGH )
{
unsigned char fcount = 0 ;
while ( fcount < 100 & & fcount < ( fighcount + 1 ) & & fighters [ fcount ] . spwn = = 1 ) fcount + + ;
if ( fcount < 100 & & fighters [ fcount ] . spwn = = 0 )
{
parts [ i ] . x = ( float ) x ;
parts [ i ] . y = ( float ) y ;
parts [ i ] . type = PT_FIGH ;
parts [ i ] . vx = 0 ;
parts [ i ] . vy = 0 ;
parts [ i ] . life = 100 ;
parts [ i ] . ctype = 0 ;
parts [ i ] . tmp = fcount ;
parts [ i ] . temp = ptypes [ t ] . heat ;
STKM_init_legs ( this , & fighters [ fcount ] , i ) ;
fighters [ fcount ] . spwn = 1 ;
fighters [ fcount ] . elem = PT_DUST ;
fighcount + + ;
return i ;
}
return - 1 ;
}
if ( t = = PT_BIZR | | t = = PT_BIZRG | | t = = PT_BIZRS )
parts [ i ] . ctype = 0x47FFFF ;
//and finally set the pmap/photon maps to the newly created particle
if ( t = = PT_PHOT | | t = = PT_NEUT | | t = = PT_ELEC )
photons [ y ] [ x ] = t | ( i < < 8 ) ;
if ( t ! = PT_STKM & & t ! = PT_STKM2 & & t ! = PT_FIGH & & t ! = PT_PHOT & & t ! = PT_NEUT )
pmap [ y ] [ x ] = t | ( i < < 8 ) ;
//Fancy dust effects for powder types
if ( ( ptypes [ t ] . properties & TYPE_PART ) & & pretty_powder )
{
int colr , colg , colb , randa ;
randa = ( rand ( ) % 30 ) - 15 ;
colr = ( PIXR ( ptypes [ t ] . pcolors ) + sandcolour_r + ( rand ( ) % 20 ) - 10 + randa ) ;
colg = ( PIXG ( ptypes [ t ] . pcolors ) + sandcolour_g + ( rand ( ) % 20 ) - 10 + randa ) ;
colb = ( PIXB ( ptypes [ t ] . pcolors ) + sandcolour_b + ( rand ( ) % 20 ) - 10 + randa ) ;
colr = colr > 255 ? 255 : ( colr < 0 ? 0 : colr ) ;
colg = colg > 255 ? 255 : ( colg < 0 ? 0 : colg ) ;
colb = colb > 255 ? 255 : ( colb < 0 ? 0 : colb ) ;
parts [ i ] . dcolour = 0xFF000000 | ( colr < < 16 ) | ( colg < < 8 ) | colb ;
}
elementCount [ t ] + + ;
return i ;
}
void Simulation : : create_gain_photon ( int pp ) //photons from PHOT going through GLOW
{
float xx , yy ;
int i , lr , temp_bin , nx , ny ;
if ( pfree = = - 1 )
return ;
i = pfree ;
lr = rand ( ) % 2 ;
if ( lr ) {
xx = parts [ pp ] . x - 0.3 * parts [ pp ] . vy ;
yy = parts [ pp ] . y + 0.3 * parts [ pp ] . vx ;
} else {
xx = parts [ pp ] . x + 0.3 * parts [ pp ] . vy ;
yy = parts [ pp ] . y - 0.3 * parts [ pp ] . vx ;
}
nx = ( int ) ( xx + 0.5f ) ;
ny = ( int ) ( yy + 0.5f ) ;
if ( nx < 0 | | ny < 0 | | nx > = XRES | | ny > = YRES )
return ;
if ( ( pmap [ ny ] [ nx ] & 0xFF ) ! = PT_GLOW )
return ;
pfree = parts [ i ] . life ;
if ( i > parts_lastActiveIndex ) parts_lastActiveIndex = i ;
parts [ i ] . type = PT_PHOT ;
parts [ i ] . life = 680 ;
parts [ i ] . x = xx ;
parts [ i ] . y = yy ;
parts [ i ] . vx = parts [ pp ] . vx ;
parts [ i ] . vy = parts [ pp ] . vy ;
parts [ i ] . temp = parts [ pmap [ ny ] [ nx ] > > 8 ] . temp ;
parts [ i ] . tmp = 0 ;
parts [ i ] . pavg [ 0 ] = parts [ i ] . pavg [ 1 ] = 0.0f ;
photons [ ny ] [ nx ] = PT_PHOT | ( i < < 8 ) ;
temp_bin = ( int ) ( ( parts [ i ] . temp - 273.0f ) * 0.25f ) ;
if ( temp_bin < 0 ) temp_bin = 0 ;
if ( temp_bin > 25 ) temp_bin = 25 ;
parts [ i ] . ctype = 0x1F < < temp_bin ;
}
void Simulation : : create_cherenkov_photon ( int pp ) //photons from NEUT going through GLAS
{
int i , lr , nx , ny ;
float r , eff_ior ;
if ( pfree = = - 1 )
return ;
i = pfree ;
nx = ( int ) ( parts [ pp ] . x + 0.5f ) ;
ny = ( int ) ( parts [ pp ] . y + 0.5f ) ;
if ( ( pmap [ ny ] [ nx ] & 0xFF ) ! = PT_GLAS )
return ;
if ( hypotf ( parts [ pp ] . vx , parts [ pp ] . vy ) < 1.44f )
return ;
pfree = parts [ i ] . life ;
if ( i > parts_lastActiveIndex ) parts_lastActiveIndex = i ;
lr = rand ( ) % 2 ;
parts [ i ] . type = PT_PHOT ;
parts [ i ] . ctype = 0x00000F80 ;
parts [ i ] . life = 680 ;
parts [ i ] . x = parts [ pp ] . x ;
parts [ i ] . y = parts [ pp ] . y ;
parts [ i ] . temp = parts [ pmap [ ny ] [ nx ] > > 8 ] . temp ;
parts [ i ] . tmp = 0 ;
parts [ i ] . pavg [ 0 ] = parts [ i ] . pavg [ 1 ] = 0.0f ;
photons [ ny ] [ nx ] = PT_PHOT | ( i < < 8 ) ;
if ( lr ) {
parts [ i ] . vx = parts [ pp ] . vx - 2.5f * parts [ pp ] . vy ;
parts [ i ] . vy = parts [ pp ] . vy + 2.5f * parts [ pp ] . vx ;
} else {
parts [ i ] . vx = parts [ pp ] . vx + 2.5f * parts [ pp ] . vy ;
parts [ i ] . vy = parts [ pp ] . vy - 2.5f * parts [ pp ] . vx ;
}
/* photons have speed of light. no discussion. */
r = 1.269 / hypotf ( parts [ i ] . vx , parts [ i ] . vy ) ;
parts [ i ] . vx * = r ;
parts [ i ] . vy * = r ;
}
void Simulation : : delete_part ( int x , int y , int flags ) //calls kill_part with the particle located at x,y
{
unsigned i ;
if ( x < 0 | | y < 0 | | x > = XRES | | y > = YRES )
return ;
if ( photons [ y ] [ x ] ) {
i = photons [ y ] [ x ] ;
} else {
i = pmap [ y ] [ x ] ;
}
if ( ! i )
return ;
kill_part ( i > > 8 ) ;
}
void Simulation : : update_particles_i ( int start , int inc )
{
int i , j , x , y , t , nx , ny , r , surround_space , s , lt , rt , nt , nnx , nny , q , golnum , goldelete , z , neighbors , createdsomething ;
float mv , dx , dy , ix , iy , lx , ly , nrx , nry , dp , ctemph , ctempl , gravtot ;
int fin_x , fin_y , clear_x , clear_y , stagnant ;
float fin_xf , fin_yf , clear_xf , clear_yf ;
float nn , ct1 , ct2 , swappage ;
float pt = R_TEMP ;
float c_heat = 0.0f ;
int h_count = 0 ;
int starti = ( start * - 1 ) ;
int surround [ 8 ] ;
int surround_hconduct [ 8 ] ;
int lighting_ok = 1 ;
float pGravX , pGravY , pGravD ;
if ( sys_pause & & lighting_recreate > 0 )
{
for ( i = 0 ; i < = parts_lastActiveIndex ; i + + )
{
if ( parts [ i ] . type = = PT_LIGH & & parts [ i ] . tmp2 > 0 )
{
lighting_ok = 0 ;
break ;
}
}
}
if ( lighting_ok )
lighting_recreate - - ;
if ( lighting_recreate < 0 )
lighting_recreate = 1 ;
if ( lighting_recreate > 21 )
lighting_recreate = 21 ;
if ( sys_pause & & ! framerender ) //do nothing if paused
return ;
//wire!
if ( elementCount [ PT_WIRE ] > 0 )
{
for ( nx = 0 ; nx < XRES ; nx + + )
{
for ( ny = 0 ; ny < YRES ; ny + + )
{
r = pmap [ ny ] [ nx ] ;
if ( ! r )
continue ;
if ( parts [ r > > 8 ] . type = = PT_WIRE )
parts [ r > > 8 ] . tmp = parts [ r > > 8 ] . ctype ;
}
}
}
//game of life!
if ( elementCount [ PT_LIFE ] > 0 & & + + CGOL > = GSPEED ) //GSPEED is frames per generation
{
int createdsomething = 0 ;
CGOL = 0 ;
ISGOL = 0 ;
for ( nx = CELL ; nx < XRES - CELL ; nx + + )
{ //go through every particle and set neighbor map
for ( ny = CELL ; ny < YRES - CELL ; ny + + )
{
r = pmap [ ny ] [ nx ] ;
if ( ! r )
{
gol [ nx ] [ ny ] = 0 ;
continue ;
}
else
{
//for ( golnum=1; golnum<=NGOL; golnum++) //This shouldn't be necessary any more.
//{
if ( parts [ r > > 8 ] . type = = PT_LIFE /* && parts[r>>8].ctype==golnum-1*/ )
{
golnum = parts [ r > > 8 ] . ctype + 1 ;
if ( golnum < = 0 | | golnum > NGOLALT ) {
parts [ r > > 8 ] . type = PT_NONE ;
continue ;
}
if ( parts [ r > > 8 ] . tmp = = grule [ golnum ] [ 9 ] - 1 ) {
gol [ nx ] [ ny ] = golnum ;
for ( nnx = - 1 ; nnx < 2 ; nnx + + )
{
for ( nny = - 1 ; nny < 2 ; nny + + ) //it will count itself as its own neighbor, which is needed, but will have 1 extra for delete check
{
rt = pmap [ ( ( ny + nny + YRES - 3 * CELL ) % ( YRES - 2 * CELL ) ) + CELL ] [ ( ( nx + nnx + XRES - 3 * CELL ) % ( XRES - 2 * CELL ) ) + CELL ] ;
if ( ! rt | | ( rt & 0xFF ) = = PT_LIFE )
{
gol2 [ ( ( nx + nnx + XRES - 3 * CELL ) % ( XRES - 2 * CELL ) ) + CELL ] [ ( ( ny + nny + YRES - 3 * CELL ) % ( YRES - 2 * CELL ) ) + CELL ] [ golnum ] + + ;
gol2 [ ( ( nx + nnx + XRES - 3 * CELL ) % ( XRES - 2 * CELL ) ) + CELL ] [ ( ( ny + nny + YRES - 3 * CELL ) % ( YRES - 2 * CELL ) ) + CELL ] [ 0 ] + + ;
}
}
}
} else {
parts [ r > > 8 ] . tmp - - ;
if ( parts [ r > > 8 ] . tmp < = 0 )
parts [ r > > 8 ] . type = PT_NONE ; //using kill_part makes it not work
}
}
//}
}
}
}
for ( nx = CELL ; nx < XRES - CELL ; nx + + )
{ //go through every particle again, but check neighbor map, then update particles
for ( ny = CELL ; ny < YRES - CELL ; ny + + )
{
r = pmap [ ny ] [ nx ] ;
neighbors = gol2 [ nx ] [ ny ] [ 0 ] ;
if ( neighbors = = 0 | | ! ( ( r & 0xFF ) = = PT_LIFE | | ! ( r & 0xFF ) ) )
continue ;
for ( golnum = 1 ; golnum < = NGOL ; golnum + + )
{
goldelete = neighbors ;
if ( gol [ nx ] [ ny ] = = 0 & & grule [ golnum ] [ goldelete ] > = 2 & & gol2 [ nx ] [ ny ] [ golnum ] > = ( goldelete % 2 ) + goldelete / 2 )
{
if ( create_part ( - 1 , nx , ny , PT_LIFE | ( ( golnum - 1 ) < < 8 ) ) )
createdsomething = 1 ;
}
else if ( gol [ nx ] [ ny ] = = golnum & & ( grule [ golnum ] [ goldelete - 1 ] = = 0 | | grule [ golnum ] [ goldelete - 1 ] = = 2 ) ) //subtract 1 because it counted itself
{
if ( parts [ r > > 8 ] . tmp = = grule [ golnum ] [ 9 ] - 1 )
parts [ r > > 8 ] . tmp - - ;
}
if ( r & & parts [ r > > 8 ] . tmp < = 0 )
parts [ r > > 8 ] . type = PT_NONE ; //using kill_part makes it not work
}
for ( z = 0 ; z < = NGOL ; z + + )
gol2 [ nx ] [ ny ] [ z ] = 0 ; //this improves performance A LOT compared to the memset, i was getting ~23 more fps with this.
}
}
//memset(gol2, 0, sizeof(gol2));
}
if ( ISWIRE = = 1 ) //wifi channel reseting
{
for ( q = 0 ; q < ( int ) ( MAX_TEMP - 73.15f ) / 100 + 2 ; q + + )
if ( ! wireless [ q ] [ 1 ] )
{
wireless [ q ] [ 0 ] = 0 ;
}
else
wireless [ q ] [ 1 ] = 0 ;
}
//the main particle loop function, goes over all particles.
for ( i = 0 ; i < = parts_lastActiveIndex ; i + + )
if ( parts [ i ] . type )
{
lx = parts [ i ] . x ;
ly = parts [ i ] . y ;
t = parts [ i ] . type ;
if ( t < 0 | | t > = PT_NUM )
{
kill_part ( i ) ;
continue ;
}
//printf("parts[%d].type: %d\n", i, parts[i].type);
if ( parts [ i ] . life > 0 & & ( ptypes [ t ] . properties & PROP_LIFE_DEC ) )
{
// automatically decrease life
parts [ i ] . life - - ;
if ( parts [ i ] . life < = 0 & & ( ptypes [ t ] . properties & ( PROP_LIFE_KILL_DEC | PROP_LIFE_KILL ) ) )
{
// kill on change to no life
kill_part ( i ) ;
continue ;
}
}
else if ( parts [ i ] . life < = 0 & & ( ptypes [ t ] . properties & PROP_LIFE_KILL ) )
{
// kill if no life
kill_part ( i ) ;
continue ;
}
x = ( int ) ( parts [ i ] . x + 0.5f ) ;
y = ( int ) ( parts [ i ] . y + 0.5f ) ;
//this kills any particle out of the screen, or in a wall where it isn't supposed to go
if ( x < CELL | | y < CELL | | x > = XRES - CELL | | y > = YRES - CELL | |
( bmap [ y / CELL ] [ x / CELL ] & &
( bmap [ y / CELL ] [ x / CELL ] = = WL_WALL | |
bmap [ y / CELL ] [ x / CELL ] = = WL_WALLELEC | |
bmap [ y / CELL ] [ x / CELL ] = = WL_ALLOWAIR | |
( bmap [ y / CELL ] [ x / CELL ] = = WL_DESTROYALL ) | |
( bmap [ y / CELL ] [ x / CELL ] = = WL_ALLOWLIQUID & & ptypes [ t ] . falldown ! = 2 ) | |
( bmap [ y / CELL ] [ x / CELL ] = = WL_ALLOWSOLID & & ptypes [ t ] . falldown ! = 1 ) | |
( bmap [ y / CELL ] [ x / CELL ] = = WL_ALLOWGAS & & ! ( ptypes [ t ] . properties & TYPE_GAS ) ) | | //&& ptypes[t].falldown!=0 && parts[i].type!=PT_FIRE && parts[i].type!=PT_SMKE && parts[i].type!=PT_HFLM) ||
( bmap [ y / CELL ] [ x / CELL ] = = WL_ALLOWENERGY & & ! ( ptypes [ t ] . properties & TYPE_ENERGY ) ) | |
( bmap [ y / CELL ] [ x / CELL ] = = WL_DETECT & & ( t = = PT_METL | | t = = PT_SPRK ) ) | |
( bmap [ y / CELL ] [ x / CELL ] = = WL_EWALL & & ! emap [ y / CELL ] [ x / CELL ] ) ) & & ( t ! = PT_STKM ) & & ( t ! = PT_STKM2 ) & & ( t ! = PT_FIGH ) ) )
{
kill_part ( i ) ;
continue ;
}
if ( bmap [ y / CELL ] [ x / CELL ] = = WL_DETECT & & emap [ y / CELL ] [ x / CELL ] < 8 )
set_emap ( x / CELL , y / CELL ) ;
//adding to velocity from the particle's velocity
vx [ y / CELL ] [ x / CELL ] = vx [ y / CELL ] [ x / CELL ] * ptypes [ t ] . airloss + ptypes [ t ] . airdrag * parts [ i ] . vx ;
vy [ y / CELL ] [ x / CELL ] = vy [ y / CELL ] [ x / CELL ] * ptypes [ t ] . airloss + ptypes [ t ] . airdrag * parts [ i ] . vy ;
if ( t = = PT_GAS | | t = = PT_NBLE )
{
if ( pv [ y / CELL ] [ x / CELL ] < 3.5f )
pv [ y / CELL ] [ x / CELL ] + = ptypes [ t ] . hotair * ( 3.5f - pv [ y / CELL ] [ x / CELL ] ) ;
if ( y + CELL < YRES & & pv [ y / CELL + 1 ] [ x / CELL ] < 3.5f )
pv [ y / CELL + 1 ] [ x / CELL ] + = ptypes [ t ] . hotair * ( 3.5f - pv [ y / CELL + 1 ] [ x / CELL ] ) ;
if ( x + CELL < XRES )
{
if ( pv [ y / CELL ] [ x / CELL + 1 ] < 3.5f )
pv [ y / CELL ] [ x / CELL + 1 ] + = ptypes [ t ] . hotair * ( 3.5f - pv [ y / CELL ] [ x / CELL + 1 ] ) ;
if ( y + CELL < YRES & & pv [ y / CELL + 1 ] [ x / CELL + 1 ] < 3.5f )
pv [ y / CELL + 1 ] [ x / CELL + 1 ] + = ptypes [ t ] . hotair * ( 3.5f - pv [ y / CELL + 1 ] [ x / CELL + 1 ] ) ;
}
}
else //add the hotair variable to the pressure map, like black hole, or white hole.
{
pv [ y / CELL ] [ x / CELL ] + = ptypes [ t ] . hotair ;
if ( y + CELL < YRES )
pv [ y / CELL + 1 ] [ x / CELL ] + = ptypes [ t ] . hotair ;
if ( x + CELL < XRES )
{
pv [ y / CELL ] [ x / CELL + 1 ] + = ptypes [ t ] . hotair ;
if ( y + CELL < YRES )
pv [ y / CELL + 1 ] [ x / CELL + 1 ] + = ptypes [ t ] . hotair ;
}
}
//Gravity mode by Moach
switch ( gravityMode )
{
default :
case 0 :
pGravX = 0.0f ;
pGravY = ptypes [ t ] . gravity ;
break ;
case 1 :
pGravX = pGravY = 0.0f ;
break ;
case 2 :
pGravD = 0.01f - hypotf ( ( x - XCNTR ) , ( y - YCNTR ) ) ;
pGravX = ptypes [ t ] . gravity * ( ( float ) ( x - XCNTR ) / pGravD ) ;
pGravY = ptypes [ t ] . gravity * ( ( float ) ( y - YCNTR ) / pGravD ) ;
break ;
}
//Get some gravity from the gravity map
if ( t = = PT_ANAR )
{
// perhaps we should have a ptypes variable for this
pGravX - = gravx [ ( y / CELL ) * ( XRES / CELL ) + ( x / CELL ) ] ;
pGravY - = gravy [ ( y / CELL ) * ( XRES / CELL ) + ( x / CELL ) ] ;
}
else if ( t ! = PT_STKM & & t ! = PT_STKM2 & & t ! = PT_FIGH & & ! ( ptypes [ t ] . properties & TYPE_SOLID ) )
{
pGravX + = gravx [ ( y / CELL ) * ( XRES / CELL ) + ( x / CELL ) ] ;
pGravY + = gravy [ ( y / CELL ) * ( XRES / CELL ) + ( x / CELL ) ] ;
}
//velocity updates for the particle
parts [ i ] . vx * = ptypes [ t ] . loss ;
parts [ i ] . vy * = ptypes [ t ] . loss ;
//particle gets velocity from the vx and vy maps
parts [ i ] . vx + = ptypes [ t ] . advection * vx [ y / CELL ] [ x / CELL ] + pGravX ;
parts [ i ] . vy + = ptypes [ t ] . advection * vy [ y / CELL ] [ x / CELL ] + pGravY ;
if ( ptypes [ t ] . diffusion ) //the random diffusion that gasses have
{
parts [ i ] . vx + = ptypes [ t ] . diffusion * ( rand ( ) / ( 0.5f * RAND_MAX ) - 1.0f ) ;
parts [ i ] . vy + = ptypes [ t ] . diffusion * ( rand ( ) / ( 0.5f * RAND_MAX ) - 1.0f ) ;
}
j = surround_space = nt = 0 ; //if nt is 1 after this, then there is a particle around the current particle, that is NOT the current particle's type, for water movement.
for ( nx = - 1 ; nx < 2 ; nx + + )
for ( ny = - 1 ; ny < 2 ; ny + + ) {
if ( nx | | ny ) {
surround [ j ] = r = pmap [ y + ny ] [ x + nx ] ;
j + + ;
if ( ! ( r & 0xFF ) )
surround_space = 1 ; //there is empty space
if ( ( r & 0xFF ) ! = t )
nt = 1 ; //there is nothing or a different particle
}
}
if ( ! legacy_enable )
{
if ( y - 2 > = 0 & & y - 2 < YRES & & ( ptypes [ t ] . properties & TYPE_LIQUID ) ) { //some heat convection for liquids
r = pmap [ y - 2 ] [ x ] ;
if ( ! ( ! r | | parts [ i ] . type ! = ( r & 0xFF ) ) ) {
if ( parts [ i ] . temp > parts [ r > > 8 ] . temp ) {
swappage = parts [ i ] . temp ;
parts [ i ] . temp = parts [ r > > 8 ] . temp ;
parts [ r > > 8 ] . temp = swappage ;
}
}
}
//heat transfer code
h_count = 0 ;
# ifdef REALHEAT
if ( t & & ( t ! = PT_HSWC | | parts [ i ] . life = = 10 ) )
{
float c_Cm = 0.0f ;
# else
if ( t & & ( t ! = PT_HSWC | | parts [ i ] . life = = 10 ) & & ptypes [ t ] . hconduct > ( rand ( ) % 250 ) )
{
float c_Cm = 0.0f ;
# endif
if ( aheat_enable )
{
c_heat = ( hv [ y / CELL ] [ x / CELL ] - parts [ i ] . temp ) * 0.04 ;
c_heat = restrict_flt ( c_heat , - MAX_TEMP + MIN_TEMP , MAX_TEMP - MIN_TEMP ) ;
parts [ i ] . temp + = c_heat ;
hv [ y / CELL ] [ x / CELL ] - = c_heat ;
}
c_heat = 0.0f ;
for ( j = 0 ; j < 8 ; j + + )
{
surround_hconduct [ j ] = i ;
r = surround [ j ] ;
if ( ! r )
continue ;
rt = r & 0xFF ;
if ( rt & & ptypes [ rt ] . hconduct & & ( rt ! = PT_HSWC | | parts [ r > > 8 ] . life = = 10 )
& & ( t ! = PT_FILT | | ( rt ! = PT_BRAY & & rt ! = PT_BIZR & & rt ! = PT_BIZRG ) )
& & ( rt ! = PT_FILT | | ( t ! = PT_BRAY & & t ! = PT_PHOT & & t ! = PT_BIZR & & t ! = PT_BIZRG ) ) )
{
surround_hconduct [ j ] = r > > 8 ;
# ifdef REALHEAT
c_heat + = parts [ r > > 8 ] . temp * 96.645 / ptypes [ rt ] . hconduct * fabs ( ptypes [ rt ] . weight ) ;
c_Cm + = 96.645 / ptypes [ rt ] . hconduct * fabs ( ptypes [ rt ] . weight ) ;
# else
c_heat + = parts [ r > > 8 ] . temp ;
# endif
h_count + + ;
}
}
# ifdef REALHEAT
if ( t = = PT_PHOT )
pt = ( c_heat + parts [ i ] . temp * 96.645 ) / ( c_Cm + 96.645 ) ;
else
pt = ( c_heat + parts [ i ] . temp * 96.645 / ptypes [ t ] . hconduct * fabs ( ptypes [ t ] . weight ) ) / ( c_Cm + 96.645 / ptypes [ t ] . hconduct * fabs ( ptypes [ t ] . weight ) ) ;
# else
pt = ( c_heat + parts [ i ] . temp ) / ( h_count + 1 ) ;
# endif
pt = parts [ i ] . temp = restrict_flt ( pt , MIN_TEMP , MAX_TEMP ) ;
for ( j = 0 ; j < 8 ; j + + )
{
parts [ surround_hconduct [ j ] ] . temp = pt ;
}
ctemph = ctempl = pt ;
// change boiling point with pressure
if ( ( ptypes [ t ] . state = = ST_LIQUID & & ptransitions [ t ] . tht > - 1 & & ptransitions [ t ] . tht < PT_NUM & & ptypes [ ptransitions [ t ] . tht ] . state = = ST_GAS )
| | t = = PT_LNTG | | t = = PT_SLTW )
ctemph - = 2.0f * pv [ y / CELL ] [ x / CELL ] ;
else if ( ( ptypes [ t ] . state = = ST_GAS & & ptransitions [ t ] . tlt > - 1 & & ptransitions [ t ] . tlt < PT_NUM & & ptypes [ ptransitions [ t ] . tlt ] . state = = ST_LIQUID )
| | t = = PT_WTRV )
ctempl - = 2.0f * pv [ y / CELL ] [ x / CELL ] ;
s = 1 ;
if ( ctemph > ptransitions [ t ] . thv & & ptransitions [ t ] . tht > - 1 ) {
// particle type change due to high temperature
if ( ptransitions [ t ] . tht ! = PT_NUM )
t = ptransitions [ t ] . tht ;
else if ( t = = PT_ICEI ) {
if ( parts [ i ] . ctype > 0 & & parts [ i ] . ctype < PT_NUM & & parts [ i ] . ctype ! = PT_ICEI ) {
if ( ptransitions [ parts [ i ] . ctype ] . tlt = = PT_ICEI & & pt < = ptransitions [ parts [ i ] . ctype ] . tlv ) s = 0 ;
else {
t = parts [ i ] . ctype ;
parts [ i ] . ctype = PT_NONE ;
parts [ i ] . life = 0 ;
}
}
else if ( pt > 274.0f ) t = PT_WATR ;
else s = 0 ;
}
else if ( t = = PT_SLTW ) {
if ( 1 > rand ( ) % 6 ) t = PT_SALT ;
else t = PT_WTRV ;
}
else s = 0 ;
} else if ( ctempl < ptransitions [ t ] . tlv & & ptransitions [ t ] . tlt > - 1 ) {
// particle type change due to low temperature
if ( ptransitions [ t ] . tlt ! = PT_NUM )
t = ptransitions [ t ] . tlt ;
else if ( t = = PT_WTRV ) {
if ( pt < 273.0f ) t = PT_RIME ;
else t = PT_DSTW ;
}
else if ( t = = PT_LAVA ) {
if ( parts [ i ] . ctype > 0 & & parts [ i ] . ctype < PT_NUM & & parts [ i ] . ctype ! = PT_LAVA ) {
if ( parts [ i ] . ctype = = PT_THRM & & pt > = ptransitions [ PT_BMTL ] . thv ) s = 0 ;
else if ( ptransitions [ parts [ i ] . ctype ] . tht = = PT_LAVA ) {
if ( pt > = ptransitions [ parts [ i ] . ctype ] . thv ) s = 0 ;
}
else if ( pt > = 973.0f ) s = 0 ; // freezing point for lava with any other (not listed in ptransitions as turning into lava) ctype
if ( s ) {
t = parts [ i ] . ctype ;
parts [ i ] . ctype = PT_NONE ;
if ( t = = PT_THRM ) {
parts [ i ] . tmp = 0 ;
t = PT_BMTL ;
}
if ( t = = PT_PLUT )
{
parts [ i ] . tmp = 0 ;
t = PT_LAVA ;
}
}
}
else if ( pt < 973.0f ) t = PT_STNE ;
else s = 0 ;
}
else s = 0 ;
}
else s = 0 ;
if ( s ) { // particle type change occurred
if ( t = = PT_ICEI | | t = = PT_LAVA )
parts [ i ] . ctype = parts [ i ] . type ;
if ( ! ( t = = PT_ICEI & & parts [ i ] . ctype = = PT_FRZW ) ) parts [ i ] . life = 0 ;
if ( ptypes [ t ] . state = = ST_GAS & & ptypes [ parts [ i ] . type ] . state ! = ST_GAS )
pv [ y / CELL ] [ x / CELL ] + = 0.50f ;
part_change_type ( i , x , y , t ) ;
if ( t = = PT_FIRE | | t = = PT_PLSM | | t = = PT_HFLM )
parts [ i ] . life = rand ( ) % 50 + 120 ;
if ( t = = PT_LAVA ) {
if ( parts [ i ] . ctype = = PT_BRMT ) parts [ i ] . ctype = PT_BMTL ;
else if ( parts [ i ] . ctype = = PT_SAND ) parts [ i ] . ctype = PT_GLAS ;
else if ( parts [ i ] . ctype = = PT_BGLA ) parts [ i ] . ctype = PT_GLAS ;
else if ( parts [ i ] . ctype = = PT_PQRT ) parts [ i ] . ctype = PT_QRTZ ;
parts [ i ] . life = rand ( ) % 120 + 240 ;
}
if ( t = = PT_NONE ) {
kill_part ( i ) ;
goto killed ;
}
}
pt = parts [ i ] . temp = restrict_flt ( parts [ i ] . temp , MIN_TEMP , MAX_TEMP ) ;
if ( t = = PT_LAVA ) {
parts [ i ] . life = restrict_flt ( ( parts [ i ] . temp - 700 ) / 7 , 0.0f , 400.0f ) ;
if ( parts [ i ] . ctype = = PT_THRM & & parts [ i ] . tmp > 0 )
{
parts [ i ] . tmp - - ;
parts [ i ] . temp = 3500 ;
}
if ( parts [ i ] . ctype = = PT_PLUT & & parts [ i ] . tmp > 0 )
{
parts [ i ] . tmp - - ;
parts [ i ] . temp = MAX_TEMP ;
}
}
}
}
if ( t = = PT_LIFE )
{
parts [ i ] . temp = restrict_flt ( parts [ i ] . temp - 50.0f , MIN_TEMP , MAX_TEMP ) ;
//ISGOL=1;//means there is a life particle on screen
}
if ( t = = PT_WIRE )
{
//wire_placed = 1;
}
//spark updates from walls
if ( ( ptypes [ t ] . properties & PROP_CONDUCTS ) | | t = = PT_SPRK )
{
nx = x % CELL ;
if ( nx = = 0 )
nx = x / CELL - 1 ;
else if ( nx = = CELL - 1 )
nx = x / CELL + 1 ;
else
nx = x / CELL ;
ny = y % CELL ;
if ( ny = = 0 )
ny = y / CELL - 1 ;
else if ( ny = = CELL - 1 )
ny = y / CELL + 1 ;
else
ny = y / CELL ;
if ( nx > = 0 & & ny > = 0 & & nx < XRES / CELL & & ny < YRES / CELL )
{
if ( t ! = PT_SPRK )
{
if ( emap [ ny ] [ nx ] = = 12 & & ! parts [ i ] . life )
{
part_change_type ( i , x , y , PT_SPRK ) ;
parts [ i ] . life = 4 ;
parts [ i ] . ctype = t ;
t = PT_SPRK ;
}
}
else if ( bmap [ ny ] [ nx ] = = WL_DETECT | | bmap [ ny ] [ nx ] = = WL_EWALL | | bmap [ ny ] [ nx ] = = WL_ALLOWLIQUID | | bmap [ ny ] [ nx ] = = WL_WALLELEC | | bmap [ ny ] [ nx ] = = WL_ALLOWALLELEC | | bmap [ ny ] [ nx ] = = WL_EHOLE )
set_emap ( nx , ny ) ;
}
}
//the basic explosion, from the .explosive variable
if ( ( ptypes [ t ] . explosive & 2 ) & & pv [ y / CELL ] [ x / CELL ] > 2.5f )
{
parts [ i ] . life = rand ( ) % 80 + 180 ;
parts [ i ] . temp = restrict_flt ( ptypes [ PT_FIRE ] . heat + ( ptypes [ t ] . flammable / 2 ) , MIN_TEMP , MAX_TEMP ) ;
t = PT_FIRE ;
part_change_type ( i , x , y , t ) ;
pv [ y / CELL ] [ x / CELL ] + = 0.25f * CFDS ;
}
s = 1 ;
gravtot = fabs ( gravy [ ( y / CELL ) * ( XRES / CELL ) + ( x / CELL ) ] ) + fabs ( gravx [ ( y / CELL ) * ( XRES / CELL ) + ( x / CELL ) ] ) ;
if ( pv [ y / CELL ] [ x / CELL ] > ptransitions [ t ] . phv & & ptransitions [ t ] . pht > - 1 ) {
// particle type change due to high pressure
if ( ptransitions [ t ] . pht ! = PT_NUM )
t = ptransitions [ t ] . pht ;
else if ( t = = PT_BMTL ) {
if ( pv [ y / CELL ] [ x / CELL ] > 2.5f )
t = PT_BRMT ;
else if ( pv [ y / CELL ] [ x / CELL ] > 1.0f & & parts [ i ] . tmp = = 1 )
t = PT_BRMT ;
else s = 0 ;
}
else s = 0 ;
} else if ( pv [ y / CELL ] [ x / CELL ] < ptransitions [ t ] . plv & & ptransitions [ t ] . plt > - 1 ) {
// particle type change due to low pressure
if ( ptransitions [ t ] . plt ! = PT_NUM )
t = ptransitions [ t ] . plt ;
else s = 0 ;
} else if ( gravtot > ( ptransitions [ t ] . phv / 4.0f ) & & ptransitions [ t ] . pht > - 1 ) {
// particle type change due to high gravity
if ( ptransitions [ t ] . pht ! = PT_NUM )
t = ptransitions [ t ] . pht ;
else if ( t = = PT_BMTL ) {
if ( gravtot > 0.625f )
t = PT_BRMT ;
else if ( gravtot > 0.25f & & parts [ i ] . tmp = = 1 )
t = PT_BRMT ;
else s = 0 ;
}
else s = 0 ;
} else s = 0 ;
if ( s ) { // particle type change occurred
parts [ i ] . life = 0 ;
part_change_type ( i , x , y , t ) ;
if ( t = = PT_FIRE )
parts [ i ] . life = rand ( ) % 50 + 120 ;
if ( t = = PT_NONE ) {
kill_part ( i ) ;
goto killed ;
}
}
//call the particle update function, if there is one
# ifdef LUACONSOLE
if ( ptypes [ t ] . update_func & & lua_el_mode [ t ] ! = 2 )
# else
if ( ptypes [ t ] . update_func )
# endif
{
if ( ( * ( ptypes [ t ] . update_func ) ) ( this , i , x , y , surround_space , nt , parts , pmap ) )
continue ;
}
# ifdef LUACONSOLE
if ( lua_el_mode [ t ] )
{
if ( luacon_part_update ( t , i , x , y , surround_space , nt ) )
continue ;
}
# endif
if ( legacy_enable ) //if heat sim is off
update_legacy_all ( this , i , x , y , surround_space , nt , parts , pmap ) ;
killed :
if ( parts [ i ] . type = = PT_NONE ) //if its dead, skip to next particle
continue ;
if ( ! parts [ i ] . vx & & ! parts [ i ] . vy ) //if its not moving, skip to next particle, movement code it next
continue ;
# if defined(WIN32) && !defined(__GNUC__)
mv = max ( fabsf ( parts [ i ] . vx ) , fabsf ( parts [ i ] . vy ) ) ;
# else
mv = fmaxf ( fabsf ( parts [ i ] . vx ) , fabsf ( parts [ i ] . vy ) ) ;
# endif
if ( mv < ISTP )
{
clear_x = x ;
clear_y = y ;
clear_xf = parts [ i ] . x ;
clear_yf = parts [ i ] . y ;
fin_xf = clear_xf + parts [ i ] . vx ;
fin_yf = clear_yf + parts [ i ] . vy ;
fin_x = ( int ) ( fin_xf + 0.5f ) ;
fin_y = ( int ) ( fin_yf + 0.5f ) ;
}
else
{
// interpolate to see if there is anything in the way
dx = parts [ i ] . vx * ISTP / mv ;
dy = parts [ i ] . vy * ISTP / mv ;
fin_xf = parts [ i ] . x ;
fin_yf = parts [ i ] . y ;
while ( 1 )
{
mv - = ISTP ;
fin_xf + = dx ;
fin_yf + = dy ;
fin_x = ( int ) ( fin_xf + 0.5f ) ;
fin_y = ( int ) ( fin_yf + 0.5f ) ;
if ( mv < = 0.0f )
{
// nothing found
fin_xf = parts [ i ] . x + parts [ i ] . vx ;
fin_yf = parts [ i ] . y + parts [ i ] . vy ;
fin_x = ( int ) ( fin_xf + 0.5f ) ;
fin_y = ( int ) ( fin_yf + 0.5f ) ;
clear_xf = fin_xf - dx ;
clear_yf = fin_yf - dy ;
clear_x = ( int ) ( clear_xf + 0.5f ) ;
clear_y = ( int ) ( clear_yf + 0.5f ) ;
break ;
}
if ( fin_x < CELL | | fin_y < CELL | | fin_x > = XRES - CELL | | fin_y > = YRES - CELL | | pmap [ fin_y ] [ fin_x ] | | ( bmap [ fin_y / CELL ] [ fin_x / CELL ] & & ( bmap [ fin_y / CELL ] [ fin_x / CELL ] = = WL_DESTROYALL | | bmap [ fin_y / CELL ] [ fin_x / CELL ] = = WL_DETECT | | ! eval_move ( t , fin_x , fin_y , NULL ) ) ) )
{
// found an obstacle
clear_xf = fin_xf - dx ;
clear_yf = fin_yf - dy ;
clear_x = ( int ) ( clear_xf + 0.5f ) ;
clear_y = ( int ) ( clear_yf + 0.5f ) ;
break ;
}
}
}
stagnant = parts [ i ] . flags & FLAG_STAGNANT ;
parts [ i ] . flags & = ~ FLAG_STAGNANT ;
if ( ( t = = PT_PHOT | | t = = PT_NEUT | | t = = PT_ELEC ) ) {
if ( t = = PT_PHOT ) {
rt = pmap [ fin_y ] [ fin_x ] & 0xFF ;
lt = pmap [ y ] [ x ] & 0xFF ;
r = eval_move ( PT_PHOT , fin_x , fin_y , NULL ) ;
if ( ( ( rt = = PT_GLAS & & lt ! = PT_GLAS ) | | ( rt ! = PT_GLAS & & lt = = PT_GLAS ) ) & & r ) {
if ( ! get_normal_interp ( REFRACT | t , parts [ i ] . x , parts [ i ] . y , parts [ i ] . vx , parts [ i ] . vy , & nrx , & nry ) ) {
kill_part ( i ) ;
continue ;
}
r = get_wavelength_bin ( & parts [ i ] . ctype ) ;
if ( r = = - 1 ) {
kill_part ( i ) ;
continue ;
}
nn = GLASS_IOR - GLASS_DISP * ( r - 15 ) / 15.0f ;
nn * = nn ;
nrx = - nrx ;
nry = - nry ;
if ( rt = = PT_GLAS & & lt ! = PT_GLAS )
nn = 1.0f / nn ;
ct1 = parts [ i ] . vx * nrx + parts [ i ] . vy * nry ;
ct2 = 1.0f - ( nn * nn ) * ( 1.0f - ( ct1 * ct1 ) ) ;
if ( ct2 < 0.0f ) {
// total internal reflection
parts [ i ] . vx - = 2.0f * ct1 * nrx ;
parts [ i ] . vy - = 2.0f * ct1 * nry ;
fin_xf = parts [ i ] . x ;
fin_yf = parts [ i ] . y ;
fin_x = x ;
fin_y = y ;
} else {
// refraction
ct2 = sqrtf ( ct2 ) ;
ct2 = ct2 - nn * ct1 ;
parts [ i ] . vx = nn * parts [ i ] . vx + ct2 * nrx ;
parts [ i ] . vy = nn * parts [ i ] . vy + ct2 * nry ;
}
}
}
if ( stagnant ) //FLAG_STAGNANT set, was reflected on previous frame
{
// cast coords as int then back to float for compatibility with existing saves
if ( ! do_move ( i , x , y , ( float ) fin_x , ( float ) fin_y ) ) {
kill_part ( i ) ;
continue ;
}
}
else if ( ! do_move ( i , x , y , fin_xf , fin_yf ) )
{
// reflection
parts [ i ] . flags | = FLAG_STAGNANT ;
if ( t = = PT_NEUT & & 100 > ( rand ( ) % 1000 ) )
{
kill_part ( i ) ;
continue ;
}
r = pmap [ fin_y ] [ fin_x ] ;
if ( ( r & 0xFF ) = = PT_PIPE & & ! ( parts [ r > > 8 ] . tmp & 0xFF ) )
{
parts [ r > > 8 ] . tmp = ( parts [ r > > 8 ] . tmp & ~ 0xFF ) | parts [ i ] . type ;
parts [ r > > 8 ] . temp = parts [ i ] . temp ;
parts [ r > > 8 ] . flags = parts [ i ] . life ;
parts [ r > > 8 ] . pavg [ 0 ] = parts [ i ] . tmp ;
parts [ r > > 8 ] . pavg [ 1 ] = parts [ i ] . ctype ;
kill_part ( i ) ;
continue ;
}
// this should be replaced with a particle type attribute ("photwl" or something)
if ( ( r & 0xFF ) = = PT_PSCN ) parts [ i ] . ctype = 0x00000000 ;
if ( ( r & 0xFF ) = = PT_NSCN ) parts [ i ] . ctype = 0x00000000 ;
if ( ( r & 0xFF ) = = PT_SPRK ) parts [ i ] . ctype = 0x00000000 ;
if ( ( r & 0xFF ) = = PT_COAL ) parts [ i ] . ctype = 0x00000000 ;
if ( ( r & 0xFF ) = = PT_BCOL ) parts [ i ] . ctype = 0x00000000 ;
if ( ( r & 0xFF ) = = PT_PLEX ) parts [ i ] . ctype & = 0x1F00003E ;
if ( ( r & 0xFF ) = = PT_NITR ) parts [ i ] . ctype & = 0x0007C000 ;
if ( ( r & 0xFF ) = = PT_NBLE ) parts [ i ] . ctype & = 0x3FFF8000 ;
if ( ( r & 0xFF ) = = PT_LAVA ) parts [ i ] . ctype & = 0x3FF00000 ;
if ( ( r & 0xFF ) = = PT_ACID ) parts [ i ] . ctype & = 0x1FE001FE ;
if ( ( r & 0xFF ) = = PT_DUST ) parts [ i ] . ctype & = 0x3FFFFFC0 ;
if ( ( r & 0xFF ) = = PT_SNOW ) parts [ i ] . ctype & = 0x03FFFFFF ;
if ( ( r & 0xFF ) = = PT_GOO ) parts [ i ] . ctype & = 0x3FFAAA00 ;
if ( ( r & 0xFF ) = = PT_PLNT ) parts [ i ] . ctype & = 0x0007C000 ;
if ( ( r & 0xFF ) = = PT_PLUT ) parts [ i ] . ctype & = 0x001FCE00 ;
if ( ( r & 0xFF ) = = PT_URAN ) parts [ i ] . ctype & = 0x003FC000 ;
if ( get_normal_interp ( t , parts [ i ] . x , parts [ i ] . y , parts [ i ] . vx , parts [ i ] . vy , & nrx , & nry ) ) {
dp = nrx * parts [ i ] . vx + nry * parts [ i ] . vy ;
parts [ i ] . vx - = 2.0f * dp * nrx ;
parts [ i ] . vy - = 2.0f * dp * nry ;
// leave the actual movement until next frame so that reflection of fast particles and refraction happen correctly
} else {
if ( t ! = PT_NEUT )
kill_part ( i ) ;
continue ;
}
if ( ! parts [ i ] . ctype & & t ! = PT_NEUT & & t ! = PT_ELEC ) {
kill_part ( i ) ;
continue ;
}
}
}
else if ( ptypes [ t ] . falldown = = 0 )
{
// gasses and solids (but not powders)
if ( ! do_move ( i , x , y , fin_xf , fin_yf ) )
{
// can't move there, so bounce off
// TODO
if ( fin_x > x + ISTP ) fin_x = x + ISTP ;
if ( fin_x < x - ISTP ) fin_x = x - ISTP ;
if ( fin_y > y + ISTP ) fin_y = y + ISTP ;
if ( fin_y < y - ISTP ) fin_y = y - ISTP ;
if ( do_move ( i , x , y , 0.25f + ( float ) ( 2 * x - fin_x ) , 0.25f + fin_y ) )
{
parts [ i ] . vx * = ptypes [ t ] . collision ;
}
else if ( do_move ( i , x , y , 0.25f + fin_x , 0.25f + ( float ) ( 2 * y - fin_y ) ) )
{
parts [ i ] . vy * = ptypes [ t ] . collision ;
}
else
{
parts [ i ] . vx * = ptypes [ t ] . collision ;
parts [ i ] . vy * = ptypes [ t ] . collision ;
}
}
}
else
{
if ( water_equal_test & & ptypes [ t ] . falldown = = 2 & & 1 > = rand ( ) % 400 ) //checking stagnant is cool, but then it doesn't update when you change it later.
{
if ( ! flood_water ( x , y , i , y , parts [ i ] . tmp2 ) )
goto movedone ;
}
// liquids and powders
if ( ! do_move ( i , x , y , fin_xf , fin_yf ) )
{
if ( fin_x ! = x & & do_move ( i , x , y , fin_xf , clear_yf ) )
{
parts [ i ] . vx * = ptypes [ t ] . collision ;
parts [ i ] . vy * = ptypes [ t ] . collision ;
}
else if ( fin_y ! = y & & do_move ( i , x , y , clear_xf , fin_yf ) )
{
parts [ i ] . vx * = ptypes [ t ] . collision ;
parts [ i ] . vy * = ptypes [ t ] . collision ;
}
else
{
s = 1 ;
r = ( rand ( ) % 2 ) * 2 - 1 ;
if ( ( clear_x ! = x | | clear_y ! = y | | nt | | surround_space ) & &
( fabsf ( parts [ i ] . vx ) > 0.01f | | fabsf ( parts [ i ] . vy ) > 0.01f ) )
{
// allow diagonal movement if target position is blocked
// but no point trying this if particle is stuck in a block of identical particles
dx = parts [ i ] . vx - parts [ i ] . vy * r ;
dy = parts [ i ] . vy + parts [ i ] . vx * r ;
if ( fabsf ( dy ) > fabsf ( dx ) )
mv = fabsf ( dy ) ;
else
mv = fabsf ( dx ) ;
dx / = mv ;
dy / = mv ;
if ( do_move ( i , x , y , clear_xf + dx , clear_yf + dy ) )
{
parts [ i ] . vx * = ptypes [ t ] . collision ;
parts [ i ] . vy * = ptypes [ t ] . collision ;
goto movedone ;
}
swappage = dx ;
dx = dy * r ;
dy = - swappage * r ;
if ( do_move ( i , x , y , clear_xf + dx , clear_yf + dy ) )
{
parts [ i ] . vx * = ptypes [ t ] . collision ;
parts [ i ] . vy * = ptypes [ t ] . collision ;
goto movedone ;
}
}
if ( ptypes [ t ] . falldown > 1 & & ! ngrav_enable & & gravityMode = = 0 & & parts [ i ] . vy > fabsf ( parts [ i ] . vx ) )
{
s = 0 ;
// stagnant is true if FLAG_STAGNANT was set for this particle in previous frame
if ( ! stagnant | | nt ) //nt is if there is an something else besides the current particle type, around the particle
rt = 30 ; //slight less water lag, although it changes how it moves a lot
else
rt = 10 ;
for ( j = clear_x + r ; j > = 0 & & j > = clear_x - rt & & j < clear_x + rt & & j < XRES ; j + = r )
{
if ( ( ( pmap [ fin_y ] [ j ] & 0xFF ) ! = t | | bmap [ fin_y / CELL ] [ j / CELL ] )
& & ( s = do_move ( i , x , y , ( float ) j , fin_yf ) ) )
{
nx = ( int ) ( parts [ i ] . x + 0.5f ) ;
ny = ( int ) ( parts [ i ] . y + 0.5f ) ;
break ;
}
if ( fin_y ! = clear_y & & ( ( pmap [ clear_y ] [ j ] & 0xFF ) ! = t | | bmap [ clear_y / CELL ] [ j / CELL ] )
& & ( s = do_move ( i , x , y , ( float ) j , clear_yf ) ) )
{
nx = ( int ) ( parts [ i ] . x + 0.5f ) ;
ny = ( int ) ( parts [ i ] . y + 0.5f ) ;
break ;
}
if ( ( pmap [ clear_y ] [ j ] & 0xFF ) ! = t | | ( bmap [ clear_y / CELL ] [ j / CELL ] & & bmap [ clear_y / CELL ] [ j / CELL ] ! = WL_STREAM ) )
break ;
}
if ( parts [ i ] . vy > 0 )
r = 1 ;
else
r = - 1 ;
if ( s = = 1 )
for ( j = ny + r ; j > = 0 & & j < YRES & & j > = ny - rt & & j < ny + rt ; j + = r )
{
if ( ( ( pmap [ j ] [ nx ] & 0xFF ) ! = t | | bmap [ j / CELL ] [ nx / CELL ] ) & & do_move ( i , nx , ny , ( float ) nx , ( float ) j ) )
break ;
if ( ( pmap [ j ] [ nx ] & 255 ) ! = t | | ( bmap [ j / CELL ] [ nx / CELL ] & & bmap [ j / CELL ] [ nx / CELL ] ! = WL_STREAM ) )
break ;
}
else if ( s = = - 1 ) { } // particle is out of bounds
else if ( ( clear_x ! = x | | clear_y ! = y ) & & do_move ( i , x , y , clear_xf , clear_yf ) ) { }
else parts [ i ] . flags | = FLAG_STAGNANT ;
parts [ i ] . vx * = ptypes [ t ] . collision ;
parts [ i ] . vy * = ptypes [ t ] . collision ;
}
else if ( ptypes [ t ] . falldown > 1 & & fabsf ( pGravX * parts [ i ] . vx + pGravY * parts [ i ] . vy ) > fabsf ( pGravY * parts [ i ] . vx - pGravX * parts [ i ] . vy ) )
{
float nxf , nyf , prev_pGravX , prev_pGravY , ptGrav = ptypes [ t ] . gravity ;
s = 0 ;
// stagnant is true if FLAG_STAGNANT was set for this particle in previous frame
if ( ! stagnant | | nt ) //nt is if there is an something else besides the current particle type, around the particle
rt = 30 ; //slight less water lag, although it changes how it moves a lot
else
rt = 10 ;
nxf = clear_xf ;
nyf = clear_yf ;
for ( j = 0 ; j < rt ; j + + )
{
switch ( gravityMode )
{
default :
case 0 :
pGravX = 0.0f ;
pGravY = ptGrav ;
break ;
case 1 :
pGravX = pGravY = 0.0f ;
break ;
case 2 :
pGravD = 0.01f - hypotf ( ( nx - XCNTR ) , ( ny - YCNTR ) ) ;
pGravX = ptGrav * ( ( float ) ( nx - XCNTR ) / pGravD ) ;
pGravY = ptGrav * ( ( float ) ( ny - YCNTR ) / pGravD ) ;
break ;
}
pGravX + = gravx [ ( ny / CELL ) * ( XRES / CELL ) + ( nx / CELL ) ] ;
pGravY + = gravy [ ( ny / CELL ) * ( XRES / CELL ) + ( nx / CELL ) ] ;
if ( fabsf ( pGravY ) > fabsf ( pGravX ) )
mv = fabsf ( pGravY ) ;
else
mv = fabsf ( pGravX ) ;
if ( mv < 0.0001f ) break ;
pGravX / = mv ;
pGravY / = mv ;
if ( j )
{
nxf + = r * ( pGravY * 2.0f - prev_pGravY ) ;
nyf + = - r * ( pGravX * 2.0f - prev_pGravX ) ;
}
else
{
nxf + = r * pGravY ;
nyf + = - r * pGravX ;
}
prev_pGravX = pGravX ;
prev_pGravY = pGravY ;
nx = ( int ) ( nxf + 0.5f ) ;
ny = ( int ) ( nyf + 0.5f ) ;
if ( nx < 0 | | ny < 0 | | nx > = XRES | | ny > = YRES )
break ;
if ( ( pmap [ ny ] [ nx ] & 0xFF ) ! = t | | bmap [ ny / CELL ] [ nx / CELL ] )
{
s = do_move ( i , x , y , nxf , nyf ) ;
if ( s )
{
nx = ( int ) ( parts [ i ] . x + 0.5f ) ;
ny = ( int ) ( parts [ i ] . y + 0.5f ) ;
break ;
}
if ( bmap [ ny / CELL ] [ nx / CELL ] ! = WL_STREAM )
break ;
}
}
if ( s = = 1 )
{
clear_x = nx ;
clear_y = ny ;
for ( j = 0 ; j < rt ; j + + )
{
switch ( gravityMode )
{
default :
case 0 :
pGravX = 0.0f ;
pGravY = ptGrav ;
break ;
case 1 :
pGravX = pGravY = 0.0f ;
break ;
case 2 :
pGravD = 0.01f - hypotf ( ( nx - XCNTR ) , ( ny - YCNTR ) ) ;
pGravX = ptGrav * ( ( float ) ( nx - XCNTR ) / pGravD ) ;
pGravY = ptGrav * ( ( float ) ( ny - YCNTR ) / pGravD ) ;
break ;
}
pGravX + = gravx [ ( ny / CELL ) * ( XRES / CELL ) + ( nx / CELL ) ] ;
pGravY + = gravy [ ( ny / CELL ) * ( XRES / CELL ) + ( nx / CELL ) ] ;
if ( fabsf ( pGravY ) > fabsf ( pGravX ) )
mv = fabsf ( pGravY ) ;
else
mv = fabsf ( pGravX ) ;
if ( mv < 0.0001f ) break ;
pGravX / = mv ;
pGravY / = mv ;
nxf + = pGravX ;
nyf + = pGravY ;
nx = ( int ) ( nxf + 0.5f ) ;
ny = ( int ) ( nyf + 0.5f ) ;
if ( nx < 0 | | ny < 0 | | nx > = XRES | | ny > = YRES )
break ;
if ( ( pmap [ ny ] [ nx ] & 0xFF ) ! = t | | bmap [ ny / CELL ] [ nx / CELL ] )
{
s = do_move ( i , clear_x , clear_y , nxf , nyf ) ;
if ( s | | bmap [ ny / CELL ] [ nx / CELL ] ! = WL_STREAM )
break ;
}
}
}
else if ( s = = - 1 ) { } // particle is out of bounds
else if ( ( clear_x ! = x | | clear_y ! = y ) & & do_move ( i , x , y , clear_xf , clear_yf ) ) { }
else parts [ i ] . flags | = FLAG_STAGNANT ;
parts [ i ] . vx * = ptypes [ t ] . collision ;
parts [ i ] . vy * = ptypes [ t ] . collision ;
}
else
{
// if interpolation was done, try moving to last clear position
if ( ( clear_x ! = x | | clear_y ! = y ) & & do_move ( i , x , y , clear_xf , clear_yf ) ) { }
else parts [ i ] . flags | = FLAG_STAGNANT ;
parts [ i ] . vx * = ptypes [ t ] . collision ;
parts [ i ] . vy * = ptypes [ t ] . collision ;
}
}
}
}
movedone :
continue ;
}
}
void Simulation : : update_particles ( ) //doesn't update the particles themselves, but some other things
{
int i , j , x , y , t , nx , ny , r , cr , cg , cb , l = - 1 ;
float lx , ly ;
int lastPartUsed = 0 ;
int lastPartUnused = - 1 ;
# ifdef MT
int pt = 0 , pc = 0 ;
pthread_t * InterThreads ;
# endif
2012-01-11 16:59:45 -06:00
air - > update_air ( ) ;
2012-01-08 11:39:03 -06:00
memset ( pmap , 0 , sizeof ( pmap ) ) ;
memset ( photons , 0 , sizeof ( photons ) ) ;
NUM_PARTS = 0 ;
for ( i = 0 ; i < = parts_lastActiveIndex ; i + + ) //the particle loop that resets the pmap/photon maps every frame, to update them.
{
if ( parts [ i ] . type )
{
t = parts [ i ] . type ;
x = ( int ) ( parts [ i ] . x + 0.5f ) ;
y = ( int ) ( parts [ i ] . y + 0.5f ) ;
if ( x > = 0 & & y > = 0 & & x < XRES & & y < YRES )
{
if ( t = = PT_PHOT | | t = = PT_NEUT )
photons [ y ] [ x ] = t | ( i < < 8 ) ;
else
pmap [ y ] [ x ] = t | ( i < < 8 ) ;
}
lastPartUsed = i ;
NUM_PARTS + + ;
}
else
{
if ( lastPartUnused < 0 ) pfree = i ;
else parts [ lastPartUnused ] . life = i ;
lastPartUnused = i ;
}
}
if ( lastPartUnused = = - 1 )
{
if ( parts_lastActiveIndex > = NPART - 1 ) pfree = - 1 ;
else pfree = parts_lastActiveIndex + 1 ;
}
else
{
if ( parts_lastActiveIndex > = NPART - 1 ) parts [ lastPartUnused ] . life = - 1 ;
else parts [ lastPartUnused ] . life = parts_lastActiveIndex + 1 ;
}
parts_lastActiveIndex = lastPartUsed ;
if ( ! sys_pause | | framerender )
{
for ( y = 0 ; y < YRES / CELL ; y + + )
{
for ( x = 0 ; x < XRES / CELL ; x + + )
{
if ( emap [ y ] [ x ] )
emap [ y ] [ x ] - - ;
}
}
}
update_particles_i ( 0 , 1 ) ;
// this should probably be elsewhere
/*for (y=0; y<YRES/CELL; y++)
for ( x = 0 ; x < XRES / CELL ; x + + )
if ( bmap [ y ] [ x ] = = WL_STREAM )
{
lx = x * CELL + CELL * 0.5f ;
ly = y * CELL + CELL * 0.5f ;
for ( t = 0 ; t < 1024 ; t + + )
{
nx = ( int ) ( lx + 0.5f ) ;
ny = ( int ) ( ly + 0.5f ) ;
if ( nx < 0 | | nx > = XRES | | ny < 0 | | ny > = YRES )
break ;
addpixel ( vid , nx , ny , 255 , 255 , 255 , 64 ) ;
i = nx / CELL ;
j = ny / CELL ;
lx + = vx [ j ] [ i ] * 0.125f ;
ly + = vy [ j ] [ i ] * 0.125f ;
if ( bmap [ j ] [ i ] = = WL_STREAM & & i ! = x & & j ! = y )
break ;
}
drawtext ( vid , x * CELL , y * CELL - 2 , " \x8D " , 255 , 255 , 255 , 128 ) ;
}
*/
}
2012-01-21 07:19:10 -06:00
Simulation : : ~ Simulation ( )
{
free ( signs ) ;
delete grav ;
delete air ;
}
Simulation : : Simulation ( ) :
sys_pause ( 0 )
2012-01-08 11:39:03 -06:00
{
//Create and attach gravity simulation
grav = new Gravity ( ) ;
//Give air sim references to our data
grav - > bmap = bmap ;
//Gravity sim gives us maps to use
gravx = grav - > gravx ;
gravy = grav - > gravy ;
gravp = grav - > gravp ;
gravmap = grav - > gravmap ;
//Create and attach air simulation
air = new Air ( ) ;
//Give air sim references to our data
air - > bmap = bmap ;
air - > emap = emap ;
air - > fvx = fvx ;
air - > fvy = fvy ;
//Air sim gives us maps to use
vx = air - > vx ;
vy = air - > vy ;
pv = air - > pv ;
hv = air - > hv ;
2012-01-20 17:42:17 -06:00
signs = ( sign * ) calloc ( MAXSIGNS , sizeof ( sign ) ) ;
2012-01-08 11:39:03 -06:00
//ptypes[0] = {"", PIXPACK(0x000000), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, 0, R_TEMP+0.0f +273.15f, 251, "Erases particles.", ST_NONE, 0, NULL, NULL};
//ptypes[1] = {"DUST", PIXPACK(0xFFE0A0), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 10, 0, 0, 30, 1, 1, 85, 0, R_TEMP+0.0f +273.15f, 70, "Very light dust. Flammable.", ST_SOLID, TYPE_PART|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, NULL, &graphics_DUST};
//ptypes[2] = {"WATR", PIXPACK(0x2030D0), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 30, 0, R_TEMP-2.0f +273.15f, 29, "Liquid. Conducts electricity. Freezes. Extinguishes fires.", ST_LIQUID, TYPE_LIQUID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_NEUTPENETRATE, &update_WATR, NULL};
# define SC_WALL 0
# define SC_ELEC 1
# define SC_POWERED 2
# define SC_EXPLOSIVE 3
# define SC_GAS 4
# define SC_LIQUID 5
# define SC_POWDERS 6
# define SC_SOLIDS 7
# define SC_NUCLEAR 8
# define SC_SPECIAL 9
# define SC_LIFE 10
# define SC_TOOL 11
# define SC_CRACKER 13
# define SC_CRACKER2 14
# define SC_TOTAL 12
part_type ptypest [ PT_NUM ] =
{
//Name Colour Advec Airdrag Airloss Loss Collid Grav Diffus Hotair Fal Burn Exp Mel Hrd M Use Weight Section H Ins Description
{ " " , PIXPACK ( 0x000000 ) , 0.0f , 0.00f * CFDS , 1.00f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 100 , SC_SPECIAL , R_TEMP + 0.0f + 273.15f , 251 , " Erases particles. " , ST_NONE , 0 , NULL , NULL } ,
{ " DUST " , PIXPACK ( 0xFFE0A0 ) , 0.7f , 0.02f * CFDS , 0.96f , 0.80f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 1 , 10 , 0 , 0 , 30 , 1 , 1 , 85 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 70 , " Very light dust. Flammable. " , ST_SOLID , TYPE_PART | PROP_LIFE_DEC | PROP_LIFE_KILL_DEC , NULL , & graphics_DUST } ,
{ " WATR " , PIXPACK ( 0x2030D0 ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 2 , 0 , 0 , 0 , 20 , 1 , 1 , 30 , SC_LIQUID , R_TEMP - 2.0f + 273.15f , 29 , " Liquid. Conducts electricity. Freezes. Extinguishes fires. " , ST_LIQUID , TYPE_LIQUID | PROP_CONDUCTS | PROP_LIFE_DEC | PROP_NEUTPENETRATE , & update_WATR , NULL } ,
{ " OIL " , PIXPACK ( 0x404010 ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 2 , 20 , 0 , 0 , 5 , 1 , 1 , 20 , SC_LIQUID , R_TEMP + 0.0f + 273.15f , 42 , " Liquid. Flammable. " , ST_LIQUID , TYPE_LIQUID , NULL , NULL } ,
{ " FIRE " , PIXPACK ( 0xFF1000 ) , 0.9f , 0.04f * CFDS , 0.97f , 0.20f , 0.0f , - 0.1f , 0.00f , 0.001f * CFDS , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 2 , SC_EXPLOSIVE , R_TEMP + 400.0f + 273.15f , 88 , " Ignites flammable materials. Heats air. " , ST_GAS , TYPE_GAS | PROP_LIFE_DEC | PROP_LIFE_KILL , & update_PYRO , & graphics_FIRE } ,
{ " STNE " , PIXPACK ( 0xA0A0A0 ) , 0.4f , 0.04f * CFDS , 0.94f , 0.95f , - 0.1f , 0.3f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 5 , 1 , 1 , 1 , 90 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 150 , " Heavy particles. Meltable. " , ST_SOLID , TYPE_PART , NULL , NULL } ,
{ " LAVA " , PIXPACK ( 0xE05010 ) , 0.3f , 0.02f * CFDS , 0.95f , 0.80f , 0.0f , 0.15f , 0.00f , 0.0003f * CFDS , 2 , 0 , 0 , 0 , 2 , 1 , 1 , 45 , SC_LIQUID , R_TEMP + 1500.0f + 273.15f , 60 , " Heavy liquid. Ignites flammable materials. Solidifies when cold. " , ST_LIQUID , TYPE_LIQUID | PROP_LIFE_DEC , & update_PYRO , & graphics_LAVA } ,
{ " GUN " , PIXPACK ( 0xC0C0D0 ) , 0.7f , 0.02f * CFDS , 0.94f , 0.80f , - 0.1f , 0.1f , 0.00f , 0.000f * CFDS , 1 , 600 , 1 , 0 , 10 , 1 , 1 , 85 , SC_EXPLOSIVE , R_TEMP + 0.0f + 273.15f , 97 , " Light dust. Explosive. " , ST_SOLID , TYPE_PART , NULL , NULL } ,
{ " NITR " , PIXPACK ( 0x20E010 ) , 0.5f , 0.02f * CFDS , 0.92f , 0.97f , 0.0f , 0.2f , 0.00f , 0.000f * CFDS , 2 , 1000 , 2 , 0 , 3 , 1 , 1 , 23 , SC_EXPLOSIVE , R_TEMP + 0.0f + 273.15f , 50 , " Liquid. Pressure sensitive explosive. " , ST_LIQUID , TYPE_LIQUID , NULL , NULL } ,
{ " CLNE " , PIXPACK ( 0xFFD010 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 100 , SC_SPECIAL , R_TEMP + 0.0f + 273.15f , 251 , " Solid. Duplicates any particles it touches. " , ST_SOLID , TYPE_SOLID , & update_CLNE , NULL } ,
{ " GAS " , PIXPACK ( 0xE0FF20 ) , 1.0f , 0.01f * CFDS , 0.99f , 0.30f , - 0.1f , 0.0f , 0.75f , 0.001f * CFDS , 0 , 600 , 0 , 0 , 1 , 1 , 1 , 1 , SC_GAS , R_TEMP + 2.0f + 273.15f , 42 , " Gas. Diffuses. Flammable. Liquefies under pressure. " , ST_GAS , TYPE_GAS , NULL , NULL } ,
{ " C-4 " , PIXPACK ( 0xD080E0 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 1000 , 2 , 50 , 1 , 1 , 1 , 100 , SC_EXPLOSIVE , R_TEMP + 0.0f + 273.15f , 88 , " Solid. Pressure sensitive explosive. " , ST_SOLID , TYPE_SOLID | PROP_NEUTPENETRATE , NULL , NULL } ,
{ " GOO " , PIXPACK ( 0x804000 ) , 0.0f , 0.00f * CFDS , 0.97f , 0.50f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 12 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 75 , " Solid. Deforms and disappears under pressure. " , ST_SOLID , TYPE_SOLID | PROP_NEUTPENETRATE | PROP_LIFE_DEC | PROP_LIFE_KILL_DEC , & update_GOO , NULL } ,
{ " ICE " , PIXPACK ( 0xA0C0FF ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , - 0.0003f * CFDS , 0 , 0 , 0 , 0 , 20 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP - 50.0f + 273.15f , 46 , " Solid. Freezes water. Crushes under pressure. Cools down air. " , ST_SOLID , TYPE_SOLID | PROP_LIFE_DEC , & update_ICEI , NULL } ,
{ " METL " , PIXPACK ( 0x404060 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 251 , " Solid. Conducts electricity. Meltable. " , ST_SOLID , TYPE_SOLID | PROP_CONDUCTS | PROP_LIFE_DEC | PROP_HOT_GLOW , NULL , NULL } ,
{ " SPRK " , PIXPACK ( 0xFFFF80 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.001f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 251 , " Electricity. Conducted by metal and water. " , ST_SOLID , TYPE_SOLID | PROP_LIFE_DEC , & update_SPRK , & graphics_SPRK } ,
{ " SNOW " , PIXPACK ( 0xC0E0FF ) , 0.7f , 0.01f * CFDS , 0.96f , 0.90f , - 0.1f , 0.05f , 0.01f , - 0.00005f * CFDS , 1 , 0 , 0 , 0 , 20 , 1 , 1 , 50 , SC_POWDERS , R_TEMP - 30.0f + 273.15f , 46 , " Light particles. " , ST_SOLID , TYPE_PART | PROP_LIFE_DEC , & update_ICEI , NULL } ,
{ " WOOD " , PIXPACK ( 0xC0A040 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 20 , 0 , 0 , 15 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 164 , " Solid. Flammable. " , ST_SOLID , TYPE_SOLID | PROP_NEUTPENETRATE , NULL , NULL } ,
{ " NEUT " , PIXPACK ( 0x20E0FF ) , 0.0f , 0.00f * CFDS , 1.00f , 1.00f , - 0.99f , 0.0f , 0.01f , 0.002f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , - 1 , SC_NUCLEAR , R_TEMP + 4.0f + 273.15f , 60 , " Neutrons. Interact with matter in odd ways. " , ST_GAS , TYPE_ENERGY | PROP_LIFE_DEC | PROP_LIFE_KILL_DEC , & update_NEUT , & graphics_NEUT } ,
{ " PLUT " , PIXPACK ( 0x407020 ) , 0.4f , 0.01f * CFDS , 0.99f , 0.95f , 0.0f , 0.4f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 90 , SC_NUCLEAR , R_TEMP + 4.0f + 273.15f , 251 , " Heavy particles. Fissile. Generates neutrons under pressure. " , ST_SOLID , TYPE_PART | PROP_NEUTPENETRATE | PROP_RADIOACTIVE , & update_PLUT , NULL } ,
{ " PLNT " , PIXPACK ( 0x0CAC00 ) , 0.0f , 0.00f * CFDS , 0.95f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 20 , 0 , 0 , 10 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 65 , " Plant, drinks water and grows. " , ST_SOLID , TYPE_SOLID | PROP_NEUTPENETRATE | PROP_LIFE_DEC , & update_PLNT , NULL } ,
{ " ACID " , PIXPACK ( 0xED55FF ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 2 , 40 , 0 , 0 , 1 , 1 , 1 , 10 , SC_LIQUID , R_TEMP + 0.0f + 273.15f , 34 , " Dissolves almost everything. " , ST_LIQUID , TYPE_LIQUID | PROP_DEADLY , & update_ACID , & graphics_ACID } ,
{ " VOID " , PIXPACK ( 0x790B0B ) , 0.0f , 0.00f * CFDS , 1.00f , 0.00f , 0.0f , 0.0f , 0.00f , - 0.0003f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 100 , SC_SPECIAL , R_TEMP + 0.0f + 273.15f , 251 , " Hole, will drain away any particles. " , ST_SOLID , TYPE_SOLID , NULL , NULL } ,
{ " WTRV " , PIXPACK ( 0xA0A0FF ) , 1.0f , 0.01f * CFDS , 0.99f , 0.30f , - 0.1f , - 0.1f , 0.75f , 0.0003f * CFDS , 0 , 0 , 0 , 0 , 4 , 1 , 1 , 1 , SC_GAS , R_TEMP + 100.0f + 273.15f , 48 , " Steam, heats up air, produced from hot water. " , ST_GAS , TYPE_GAS , & update_WTRV , NULL } ,
{ " CNCT " , PIXPACK ( 0xC0C0C0 ) , 0.4f , 0.04f * CFDS , 0.94f , 0.95f , - 0.1f , 0.3f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 2 , 2 , 1 , 1 , 55 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 100 , " Concrete, stronger than stone. " , ST_SOLID , TYPE_PART | PROP_HOT_GLOW , NULL , NULL } ,
{ " DSTW " , PIXPACK ( 0x1020C0 ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 2 , 0 , 0 , 0 , 20 , 1 , 1 , 30 , SC_LIQUID , R_TEMP - 2.0f + 273.15f , 23 , " Distilled water, does not conduct electricity. " , ST_LIQUID , TYPE_LIQUID | PROP_NEUTPENETRATE , & update_DSTW , NULL } ,
{ " SALT " , PIXPACK ( 0xFFFFFF ) , 0.4f , 0.04f * CFDS , 0.94f , 0.95f , - 0.1f , 0.3f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 5 , 1 , 1 , 1 , 75 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 110 , " Salt, dissolves in water. " , ST_SOLID , TYPE_PART , NULL , NULL } ,
{ " SLTW " , PIXPACK ( 0x4050F0 ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 2 , 0 , 0 , 0 , 20 , 1 , 1 , 35 , SC_LIQUID , R_TEMP + 0.0f + 273.15f , 75 , " Saltwater, conducts electricity, difficult to freeze. " , ST_LIQUID , TYPE_LIQUID | PROP_CONDUCTS | PROP_LIFE_DEC | PROP_NEUTPENETRATE , & update_SLTW , NULL } ,
{ " DMND " , PIXPACK ( 0xCCFFFF ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 186 , " Diamond. Indestructible. " , ST_SOLID , TYPE_SOLID , NULL , NULL } ,
{ " BMTL " , PIXPACK ( 0x505070 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 251 , " Breakable metal. " , ST_SOLID , TYPE_SOLID | PROP_CONDUCTS | PROP_LIFE_DEC | PROP_HOT_GLOW , & update_BMTL , NULL } ,
{ " BRMT " , PIXPACK ( 0x705060 ) , 0.4f , 0.04f * CFDS , 0.94f , 0.95f , - 0.1f , 0.3f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 2 , 2 , 1 , 1 , 90 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 211 , " Broken metal. " , ST_SOLID , TYPE_PART | PROP_CONDUCTS | PROP_LIFE_DEC | PROP_HOT_GLOW , & update_BRMT , NULL } ,
{ " PHOT " , PIXPACK ( 0xFFFFFF ) , 0.0f , 0.00f * CFDS , 1.00f , 1.00f , - 0.99f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , - 1 , SC_NUCLEAR , R_TEMP + 900.0f + 273.15f , 251 , " Photons. Travel in straight lines. " , ST_GAS , TYPE_ENERGY | PROP_LIFE_DEC | PROP_LIFE_KILL_DEC , & update_PHOT , & graphics_PHOT } ,
{ " URAN " , PIXPACK ( 0x707020 ) , 0.4f , 0.01f * CFDS , 0.99f , 0.95f , 0.0f , 0.4f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 90 , SC_NUCLEAR , R_TEMP + 30.0f + 273.15f , 251 , " Heavy particles. Generates heat under pressure. " , ST_SOLID , TYPE_PART | PROP_RADIOACTIVE , & update_URAN , NULL } ,
{ " WAX " , PIXPACK ( 0xF0F0BB ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 10 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 44 , " Wax. Melts at moderately high temperatures. " , ST_SOLID , TYPE_SOLID , NULL , NULL } ,
{ " MWAX " , PIXPACK ( 0xE0E0AA ) , 0.3f , 0.02f * CFDS , 0.95f , 0.80f , 0.0f , 0.15f , 0.00f , 0.000001f * CFDS , 2 , 5 , 0 , 0 , 2 , 1 , 1 , 25 , SC_LIQUID , R_TEMP + 28.0f + 273.15f , 44 , " Liquid Wax. " , ST_LIQUID , TYPE_LIQUID , NULL , NULL } ,
{ " PSCN " , PIXPACK ( 0x805050 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 251 , " P-Type Silicon, Will transfer current to any conductor. " , ST_SOLID , TYPE_SOLID | PROP_CONDUCTS | PROP_LIFE_DEC , NULL , NULL } ,
{ " NSCN " , PIXPACK ( 0x505080 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 251 , " N-Type Silicon, Will not transfer current to P-Type Silicon. " , ST_SOLID , TYPE_SOLID | PROP_CONDUCTS | PROP_LIFE_DEC , NULL , NULL } ,
{ " LN2 " , PIXPACK ( 0x80A0DF ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 2 , 0 , 0 , 0 , 0 , 1 , 1 , 30 , SC_LIQUID , 70.15f , 70 , " Liquid Nitrogen. Very cold. " , ST_SOLID , TYPE_LIQUID , NULL , NULL } ,
{ " INSL " , PIXPACK ( 0x9EA3B6 ) , 0.0f , 0.00f * CFDS , 0.95f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 7 , 0 , 0 , 10 , 1 , 1 , 100 , SC_SPECIAL , R_TEMP + 0.0f + 273.15f , 0 , " Insulator, does not conduct heat or electricity. " , ST_SOLID , TYPE_SOLID , NULL , NULL } ,
{ " VACU " , PIXPACK ( 0x303030 ) , 0.0f , 0.00f * CFDS , 0.95f , 0.00f , 0.0f , 0.0f , 0.00f , - 0.01f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 100 , SC_SPECIAL , R_TEMP + 70.0f + 273.15f , 255 , " Vacuum, sucks in other particles and heats up. " , ST_NONE , TYPE_SOLID , NULL , NULL } ,
{ " VENT " , PIXPACK ( 0xEFEFEF ) , 0.0f , 0.00f * CFDS , 0.95f , 0.00f , 0.0f , 0.0f , 0.00f , 0.010f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 100 , SC_SPECIAL , R_TEMP - 16.0f + 273.15f , 255 , " Air vent, creates pressure and pushes other particles away. " , ST_NONE , TYPE_SOLID , NULL , NULL } ,
{ " RBDM " , PIXPACK ( 0xCCCCCC ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 1000 , 1 , 50 , 1 , 1 , 1 , 100 , SC_EXPLOSIVE , R_TEMP + 0.0f + 273.15f , 240 , " Rubidium, explosive, especially on contact with water, low melting point " , ST_SOLID , TYPE_SOLID | PROP_CONDUCTS | PROP_LIFE_DEC , NULL , NULL } ,
{ " LRBD " , PIXPACK ( 0xAAAAAA ) , 0.3f , 0.02f * CFDS , 0.95f , 0.80f , 0.0f , 0.15f , 0.00f , 0.000001f * CFDS , 2 , 1000 , 1 , 0 , 2 , 1 , 1 , 45 , SC_EXPLOSIVE , R_TEMP + 45.0f + 273.15f , 170 , " Liquid Rubidium. " , ST_LIQUID , TYPE_LIQUID | PROP_CONDUCTS | PROP_LIFE_DEC , NULL , NULL } ,
{ " NTCT " , PIXPACK ( 0x505040 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 251 , " Semi-conductor. Only conducts electricity when hot (More than 100C) " , ST_SOLID , TYPE_SOLID | PROP_CONDUCTS | PROP_LIFE_DEC , & update_NPTCT , NULL } ,
{ " SAND " , PIXPACK ( 0xFFD090 ) , 0.4f , 0.04f * CFDS , 0.94f , 0.95f , - 0.1f , 0.3f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 5 , 1 , 1 , 1 , 90 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 150 , " Sand, Heavy particles. Meltable. " , ST_SOLID , TYPE_PART , NULL , NULL } ,
{ " GLAS " , PIXPACK ( 0x404040 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 150 , " Solid. Meltable. Shatters under pressure " , ST_SOLID , TYPE_SOLID | PROP_NEUTPASS | PROP_HOT_GLOW | PROP_SPARKSETTLE , & update_GLAS , NULL } ,
{ " PTCT " , PIXPACK ( 0x405050 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 251 , " Semi-conductor. Only conducts electricity when cold (Less than 100C) " , ST_SOLID , TYPE_SOLID | PROP_CONDUCTS | PROP_LIFE_DEC , & update_NPTCT , NULL } ,
{ " BGLA " , PIXPACK ( 0x606060 ) , 0.4f , 0.04f * CFDS , 0.94f , 0.95f , - 0.1f , 0.3f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 5 , 2 , 1 , 1 , 90 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 150 , " Broken Glass, Heavy particles. Meltable. Bagels. " , ST_SOLID , TYPE_PART | PROP_HOT_GLOW , NULL , NULL } ,
{ " THDR " , PIXPACK ( 0xFFFFA0 ) , 0.0f , 0.00f * CFDS , 1.0f , 0.30f , - 0.99f , 0.6f , 0.62f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , SC_EXPLOSIVE , 9000.0f + 273.15f , 1 , " Lightning! Very hot, inflicts damage upon most materials, transfers current to metals. " , ST_NONE , TYPE_ENERGY , & update_THDR , & graphics_THDR } ,
{ " PLSM " , PIXPACK ( 0xBB99FF ) , 0.9f , 0.04f * CFDS , 0.97f , 0.20f , 0.0f , - 0.1f , 0.30f , 0.001f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , SC_GAS , 10000.0f + 273.15f , 5 , " Plasma, extremely hot. " , ST_NONE , TYPE_GAS | PROP_LIFE_DEC | PROP_LIFE_KILL , & update_PYRO , & graphics_PLSM } ,
{ " ETRD " , PIXPACK ( 0x404040 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 251 , " Electrode. Creates a surface that allows Plasma arcs. (Use sparingly) " , ST_NONE , TYPE_SOLID | PROP_CONDUCTS | PROP_LIFE_DEC , NULL , NULL } ,
{ " NICE " , PIXPACK ( 0xC0E0FF ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , - 0.0005f * CFDS , 0 , 0 , 0 , 0 , 20 , 1 , 1 , 100 , SC_SOLIDS , 35.0f , 46 , " Nitrogen Ice. " , ST_SOLID , TYPE_SOLID , NULL , NULL } ,
{ " NBLE " , PIXPACK ( 0xEB4917 ) , 1.0f , 0.01f * CFDS , 0.99f , 0.30f , - 0.1f , 0.0f , 0.75f , 0.001f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , SC_GAS , R_TEMP + 2.0f + 273.15f , 106 , " Noble Gas. Diffuses. Conductive. Ionizes into plasma when introduced to electricity " , ST_GAS , TYPE_GAS | PROP_CONDUCTS | PROP_LIFE_DEC , NULL , NULL } ,
{ " BTRY " , PIXPACK ( 0x858505 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 251 , " Solid. Generates Electricity. " , ST_SOLID , TYPE_SOLID , & update_BTRY , NULL } ,
{ " LCRY " , PIXPACK ( 0x505050 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_POWERED , R_TEMP + 0.0f + 273.15f , 251 , " Liquid Crystal. Changes colour when charged. (PSCN Charges, NSCN Discharges) " , ST_SOLID , TYPE_SOLID , & update_LCRY , & graphics_LCRY } ,
{ " STKM " , PIXPACK ( 0x000000 ) , 0.5f , 0.00f * CFDS , 0.2f , 1.0f , 0.0f , 0.0f , 0.0f , 0.00f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 50 , SC_SPECIAL , R_TEMP + 14.6f + 273.15f , 0 , " Stickman. Don't kill him! " , ST_NONE , 0 , & update_STKM , & graphics_STKM } ,
{ " SWCH " , PIXPACK ( 0x103B11 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 251 , " Solid. Only conducts when switched on. (PSCN switches on, NSCN switches off) " , ST_SOLID , TYPE_SOLID , & update_SWCH , & graphics_SWCH } ,
{ " SMKE " , PIXPACK ( 0x222222 ) , 0.9f , 0.04f * CFDS , 0.97f , 0.20f , 0.0f , - 0.1f , 0.00f , 0.001f * CFDS , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , SC_GAS , R_TEMP + 320.0f + 273.15f , 88 , " Smoke " , ST_SOLID , TYPE_GAS | PROP_LIFE_DEC | PROP_LIFE_KILL_DEC , NULL , & graphics_SMKE } ,
{ " DESL " , PIXPACK ( 0x440000 ) , 1.0f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.0f , 0.0f * CFDS , 2 , 2 , 0 , 0 , 5 , 1 , 1 , 15 , SC_LIQUID , R_TEMP + 0.0f + 273.15f , 42 , " Liquid. Explodes under high pressure and temperatures " , ST_LIQUID , TYPE_LIQUID , NULL , NULL } ,
{ " COAL " , PIXPACK ( 0x222222 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.0f , 0.0f * CFDS , 0 , 0 , 0 , 0 , 20 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 200 , " Solid. Burns slowly. " , ST_SOLID , TYPE_SOLID , & update_COAL , & graphics_COAL } ,
{ " LOXY " , PIXPACK ( 0x80A0EF ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 2 , 5000 , 0 , 0 , 0 , 1 , 1 , 30 , SC_LIQUID , 80.0f , 70 , " Liquid Oxygen. Very cold. Reacts with fire " , ST_LIQUID , TYPE_LIQUID , NULL , NULL } ,
{ " OXYG " , PIXPACK ( 0x80A0FF ) , 2.0f , 0.00f * CFDS , 0.99f , 0.30f , - 0.1f , 0.0f , 3.0f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , SC_GAS , R_TEMP + 0.0f + 273.15f , 70 , " Gas. Ignites easily. " , ST_GAS , TYPE_GAS , & update_O2 , NULL } ,
{ " INWR " , PIXPACK ( 0x544141 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 251 , " Insulated Wire. Doesn't conduct to metal or semiconductors. " , ST_SOLID , TYPE_SOLID | PROP_CONDUCTS | PROP_LIFE_DEC , NULL , NULL } ,
{ " YEST " , PIXPACK ( 0xEEE0C0 ) , 0.7f , 0.02f * CFDS , 0.96f , 0.80f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 1 , 15 , 0 , 0 , 30 , 1 , 1 , 80 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 70 , " Yeast, grows when warm (~37C). " , ST_SOLID , TYPE_PART , & update_YEST , NULL } ,
{ " DYST " , PIXPACK ( 0xBBB0A0 ) , 0.7f , 0.02f * CFDS , 0.96f , 0.80f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 1 , 20 , 0 , 0 , 30 , 0 , 1 , 80 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 70 , " Dead Yeast. " , ST_SOLID , TYPE_PART , NULL , NULL } ,
{ " THRM " , PIXPACK ( 0xA08090 ) , 0.4f , 0.04f * CFDS , 0.94f , 0.95f , - 0.1f , 0.3f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 2 , 2 , 1 , 1 , 90 , SC_EXPLOSIVE , R_TEMP + 0.0f + 273.15f , 211 , " Thermite. Burns at extremely high temperature. " , ST_SOLID , TYPE_PART , & update_THRM , NULL } ,
{ " GLOW " , PIXPACK ( 0x445464 ) , 0.3f , 0.02f * CFDS , 0.98f , 0.80f , 0.0f , 0.15f , 0.00f , 0.000f * CFDS , 2 , 0 , 0 , 0 , 2 , 1 , 1 , 40 , SC_LIQUID , R_TEMP + 20.0f + 273.15f , 44 , " Glow, Glows under pressure " , ST_LIQUID , TYPE_LIQUID | PROP_LIFE_DEC , & update_GLOW , & graphics_GLOW } ,
{ " BRCK " , PIXPACK ( 0x808080 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 251 , " Brick, breakable building material. " , ST_SOLID , TYPE_SOLID | PROP_HOT_GLOW , NULL , NULL } ,
{ " CFLM " , PIXPACK ( 0x8080FF ) , 0.9f , 0.04f * CFDS , 0.97f , 0.20f , 0.0f , - 0.1f , 0.00f , 0.0005f * CFDS , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 2 , SC_EXPLOSIVE , 0.0f , 88 , " Sub-zero flame. " , ST_LIQUID , TYPE_GAS | PROP_LIFE_DEC | PROP_LIFE_KILL , NULL , & graphics_HFLM } ,
{ " FIRW " , PIXPACK ( 0xFFA040 ) , 0.7f , 0.02f * CFDS , 0.96f , 0.80f , - 0.99f , 0.1f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 0 , 30 , 1 , 1 , 55 , SC_EXPLOSIVE , R_TEMP + 0.0f + 273.15f , 70 , " Fireworks! " , ST_SOLID , TYPE_PART | PROP_LIFE_DEC , & update_FIRW , & graphics_FIRW } ,
{ " FUSE " , PIXPACK ( 0x0A5706 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.0f , 0.0f * CFDS , 0 , 0 , 0 , 0 , 20 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 200 , " Solid. Burns slowly. Ignites at somewhat high temperatures and electricity. " , ST_SOLID , TYPE_SOLID , & update_FUSE , NULL } ,
{ " FSEP " , PIXPACK ( 0x63AD5F ) , 0.7f , 0.02f * CFDS , 0.96f , 0.80f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 0 , 30 , 1 , 1 , 70 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 70 , " Fuse Powder. See FUSE. " , ST_SOLID , TYPE_PART , & update_FSEP , NULL } ,
{ " AMTR " , PIXPACK ( 0x808080 ) , 0.7f , 0.02f * CFDS , 0.96f , 0.80f , 0.00f , 0.10f , 1.00f , 0.0000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 100 , SC_NUCLEAR , R_TEMP + 0.0f + 273.15f , 70 , " Anti-Matter, Destroys a majority of particles " , ST_NONE , TYPE_PART , & update_AMTR , NULL } , //Maybe TYPE_ENERGY?
{ " BCOL " , PIXPACK ( 0x333333 ) , 0.4f , 0.04f * CFDS , 0.94f , 0.95f , - 0.1f , 0.3f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 5 , 2 , 1 , 1 , 90 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 150 , " Broken Coal. Heavy particles. See COAL " , ST_SOLID , TYPE_PART , & update_BCOL , NULL } ,
{ " PCLN " , PIXPACK ( 0x3B3B0A ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 100 , SC_POWERED , R_TEMP + 0.0f + 273.15f , 251 , " Solid. When activated, duplicates any particles it touches. " , ST_NONE , TYPE_SOLID , & update_PCLN , & graphics_PCLN } ,
{ " HSWC " , PIXPACK ( 0x3B0A0A ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_POWERED , R_TEMP + 0.0f + 273.15f , 251 , " Heat switch. Conducts Heat only when activated " , ST_NONE , TYPE_SOLID , & update_HSWC , & graphics_HSWC } ,
{ " IRON " , PIXPACK ( 0x707070 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 50 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 251 , " Rusts with salt, can be used for electrolysis of WATR " , ST_SOLID , TYPE_SOLID | PROP_CONDUCTS | PROP_LIFE_DEC | PROP_HOT_GLOW , & update_IRON , NULL } ,
{ " MORT " , PIXPACK ( 0xE0E0E0 ) , 0.0f , 0.00f * CFDS , 1.00f , 1.00f , - 0.99f , 0.0f , 0.01f , 0.002f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , - 1 , SC_CRACKER2 , R_TEMP + 4.0f + 273.15f , 60 , " Steam Train. " , ST_NONE , TYPE_PART , & update_MORT , NULL } ,
{ " LIFE " , PIXPACK ( 0x0CAC00 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 100 , SC_LIFE , 9000.0f , 40 , " Game Of Life! B3/S23 " , ST_NONE , TYPE_SOLID | PROP_LIFE , NULL , & graphics_LIFE } ,
{ " DLAY " , PIXPACK ( 0x753590 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_POWERED , 4.0f + 273.15f , 0 , " Conducts with temperature-dependent delay. (use HEAT/COOL). " , ST_SOLID , TYPE_SOLID , & update_DLAY , & graphics_DLAY } ,
{ " CO2 " , PIXPACK ( 0x666666 ) , 2.0f , 0.00f * CFDS , 0.99f , 0.30f , - 0.1f , 0.1f , 1.0f , 0.000f * CFDS , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , SC_GAS , R_TEMP + 273.15f , 88 , " Carbon Dioxide " , ST_GAS , TYPE_GAS , & update_CO2 , NULL } ,
{ " DRIC " , PIXPACK ( 0xE0E0E0 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , - 0.0005f * CFDS , 0 , 0 , 0 , 0 , 20 , 1 , 1 , 100 , SC_SOLIDS , 172.65f , 2 , " Dry Ice. " , ST_SOLID , TYPE_SOLID , NULL , NULL } ,
{ " BUBW " , PIXPACK ( 0x2030D0 ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 2 , 0 , 0 , 0 , 20 , 1 , 1 , 30 , SC_LIQUID , R_TEMP - 2.0f + 273.15f , 29 , " Carbonated water. Conducts electricity. Freezes. Extinguishes fires. " , ST_LIQUID , TYPE_LIQUID | PROP_CONDUCTS | PROP_LIFE_DEC | PROP_NEUTPENETRATE , & update_CBNW , & graphics_CBNW } ,
{ " STOR " , PIXPACK ( 0x50DFDF ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 100 , SC_POWERED , R_TEMP + 0.0f + 273.15f , 251 , " Solid. Stores a single particle, releases when charged with PSCN, also passes to PIPE " , ST_NONE , TYPE_SOLID , & update_STOR , & graphics_STOR } ,
{ " PVOD " , PIXPACK ( 0x792020 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 100 , SC_POWERED , R_TEMP + 0.0f + 273.15f , 251 , " Solid. When activated, destroys entering particles " , ST_NONE , TYPE_SOLID , & update_PVOD , & graphics_PVOD } ,
{ " CONV " , PIXPACK ( 0x0AAB0A ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 100 , SC_SPECIAL , R_TEMP + 0.0f + 273.15f , 251 , " Solid. Converts whatever touches it into its ctype. " , ST_NONE , TYPE_SOLID , & update_CONV , NULL } ,
{ " CAUS " , PIXPACK ( 0x80FFA0 ) , 2.0f , 0.00f * CFDS , 0.99f , 0.30f , - 0.1f , 0.0f , 1.50f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , SC_GAS , R_TEMP + 0.0f + 273.15f , 70 , " Caustic Gas, acts like Acid " , ST_GAS , TYPE_GAS | PROP_DEADLY , & update_CAUS , NULL } ,
{ " LIGH " , PIXPACK ( 0xFFFFC0 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 0 , " More realistic lightning. Set pen size to set the size of the lightning. " , ST_SOLID , TYPE_SOLID , & update_LIGH , & graphics_LIGH } ,
{ " TESC " , PIXPACK ( 0x707040 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 251 , " Tesla coil! " , ST_SOLID , TYPE_SOLID | PROP_CONDUCTS | PROP_LIFE_DEC | PROP_HOT_GLOW , NULL , NULL } ,
{ " DEST " , PIXPACK ( 0xFF3311 ) , - 0.05f , 0.00f * CFDS , 0.95f , 0.95f , - 0.1f , 0.4f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 101 , SC_EXPLOSIVE , R_TEMP + 0.0f + 273.15f , 150 , " More destructive Bomb. " , ST_SOLID , TYPE_PART | PROP_LIFE_DEC | PROP_LIFE_KILL_DEC , & update_DEST , & graphics_DEST } ,
{ " SPNG " , PIXPACK ( 0xFFBE30 ) , 0.00f , 0.00f * CFDS , 0.00f , 1.00f , 0.00f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 20 , 0 , 1 , 30 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 251 , " A sponge, absorbs water. " , ST_SOLID , TYPE_SOLID , & update_SPNG , & graphics_SPNG } ,
{ " RIME " , PIXPACK ( 0xCCCCCC ) , 0.00f , 0.00f * CFDS , 0.00f , 1.00f , 0.00f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 30 , 1 , 1 , 100 , SC_CRACKER2 , 243.15f , 100 , " Not quite Ice " , ST_SOLID , TYPE_SOLID , & update_RIME , NULL } ,
{ " FOG " , PIXPACK ( 0xAAAAAA ) , 0.8f , 0.00f * CFDS , 0.4f , 0.70f , - 0.1f , 0.0f , 0.99f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 30 , 1 , 1 , 1 , SC_CRACKER2 , 243.15f , 100 , " Not quite Steam " , ST_GAS , TYPE_GAS | PROP_LIFE_DEC , & update_FOG , NULL } ,
{ " BCLN " , PIXPACK ( 0xFFD040 ) , 0.0f , 0.00f * CFDS , 0.97f , 0.50f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 12 , 1 , 1 , 100 , SC_SPECIAL , R_TEMP + 0.0f + 273.15f , 251 , " Breakable Clone. " , ST_NONE , TYPE_SOLID | PROP_LIFE_DEC | PROP_LIFE_KILL_DEC , & update_BCLN , NULL } ,
{ " LOVE " , PIXPACK ( 0xFF30FF ) , 0.0f , 0.00f * CFDS , 0.00f , 0.00f , 0.0f , 0.0f , 0.0f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 100 , SC_CRACKER2 , 373.0f , 40 , " Love... " , ST_GAS , TYPE_SOLID , & update_MISC , NULL } ,
{ " DEUT " , PIXPACK ( 0x00153F ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 2 , 0 , 0 , 0 , 20 , 1 , 1 , 31 , SC_NUCLEAR , R_TEMP - 2.0f + 273.15f , 251 , " Deuterium oxide. Volume changes with temp, radioactive with neutrons. " , ST_LIQUID , TYPE_LIQUID | PROP_NEUTPENETRATE , & update_DEUT , & graphics_DEUT } ,
{ " WARP " , PIXPACK ( 0x000000 ) , 0.8f , 0.00f * CFDS , 0.9f , 0.70f , - 0.1f , 0.0f , 3.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 30 , 1 , 1 , 1 , SC_NUCLEAR , R_TEMP + 273.15f , 100 , " Displaces other elements. " , ST_GAS , TYPE_GAS | PROP_LIFE_DEC | PROP_LIFE_KILL , & update_WARP , NULL } ,
{ " PUMP " , PIXPACK ( 0x0A0A3B ) , 0.0f , 0.00f * CFDS , 0.95f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 10 , 1 , 1 , 100 , SC_POWERED , 273.15f , 0 , " Changes pressure to its temp when activated. (use HEAT/COOL). " , ST_SOLID , TYPE_SOLID , & update_PUMP , & graphics_PUMP } ,
{ " FWRK " , PIXPACK ( 0x666666 ) , 0.4f , 0.01f * CFDS , 0.99f , 0.95f , 0.0f , 0.4f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 97 , SC_EXPLOSIVE , R_TEMP + 0.0f + 273.15f , 100 , " First fireworks made, activated by heat/neutrons. " , ST_SOLID , TYPE_PART | PROP_LIFE_DEC , & update_FWRK , NULL } ,
{ " PIPE " , PIXPACK ( 0x444444 ) , 0.0f , 0.00f * CFDS , 0.95f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 100 , SC_SOLIDS , 273.15f , 0 , " Moves elements around, read FAQ on website for help. " , ST_SOLID , TYPE_SOLID | PROP_LIFE_DEC , & update_PIPE , & graphics_PIPE } ,
{ " FRZZ " , PIXPACK ( 0xC0E0FF ) , 0.7f , 0.01f * CFDS , 0.96f , 0.90f , - 0.1f , 0.05f , 0.01f , - 0.00005f * CFDS , 1 , 0 , 0 , 0 , 20 , 1 , 1 , 50 , SC_POWDERS , 90.0f , 46 , " FREEZE " , ST_SOLID , TYPE_PART , & update_FRZZ , NULL } ,
{ " FRZW " , PIXPACK ( 0x1020C0 ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 2 , 0 , 0 , 0 , 20 , 1 , 1 , 30 , SC_CRACKER2 , 120.0f , 29 , " FREEZE WATER " , ST_LIQUID , TYPE_LIQUID | | PROP_LIFE_DEC , & update_FRZW , NULL } ,
{ " GRAV " , PIXPACK ( 0xFFE0A0 ) , 0.7f , 0.00f * CFDS , 1.00f , 1.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 1 , 10 , 0 , 0 , 30 , 1 , 1 , 85 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 70 , " Very light dust. Changes colour based on velocity. " , ST_SOLID , TYPE_PART , & update_MISC , & graphics_GRAV } ,
{ " BIZR " , PIXPACK ( 0x00FF77 ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 2 , 0 , 0 , 0 , 20 , 1 , 1 , 30 , SC_LIQUID , R_TEMP + 0.0f + 273.15f , 29 , " Bizarre... contradicts the normal state changes. " , ST_LIQUID , TYPE_LIQUID , & update_BIZR , & graphics_BIZR } ,
{ " BIZG " , PIXPACK ( 0x00FFBB ) , 1.0f , 0.01f * CFDS , 0.99f , 0.30f , - 0.1f , 0.0f , 2.75f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , SC_CRACKER2 , R_TEMP - 200.0f + 273.15f , 42 , " Bizarre gas " , ST_GAS , TYPE_GAS , & update_BIZR , & graphics_BIZR } ,
{ " BIZS " , PIXPACK ( 0x00E455 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_CRACKER2 , R_TEMP + 300.0f + 273.15f , 251 , " Bizarre solid " , ST_SOLID , TYPE_SOLID , & update_BIZR , & graphics_BIZR } ,
{ " INST " , PIXPACK ( 0x404039 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 251 , " Instantly conducts, PSCN to charge, NSCN to take. " , ST_SOLID , TYPE_SOLID | PROP_LIFE_DEC , NULL , NULL } ,
{ " ISOZ " , PIXPACK ( 0xAA30D0 ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 2 , 0 , 0 , 0 , 0 , 1 , 1 , 24 , SC_NUCLEAR , R_TEMP - 2.0f + 273.15f , 29 , " Radioactive liquid " , ST_LIQUID , TYPE_LIQUID | PROP_NEUTPENETRATE , & update_ISZ , NULL } ,
{ " ISZS " , PIXPACK ( 0x662089 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , - 0.0007f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_NUCLEAR , 140.00f , 251 , " Solid form of ISOZ, slowly decays. " , ST_SOLID , TYPE_SOLID , & update_ISZ , NULL } ,
{ " PRTI " , PIXPACK ( 0xEB5917 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , - 0.005f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 100 , SC_SPECIAL , R_TEMP + 0.0f + 273.15f , 0 , " Portal IN. Things go in here, now with channels (same as WIFI) " , ST_SOLID , TYPE_SOLID , & update_PRTI , & graphics_PRTI } ,
{ " PRTO " , PIXPACK ( 0x0020EB ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.005f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 100 , SC_SPECIAL , R_TEMP + 0.0f + 273.15f , 0 , " Portal OUT. Things come out here, now with channels (same as WIFI) " , ST_SOLID , TYPE_SOLID , & update_PRTO , & graphics_PRTO } ,
{ " PSTE " , PIXPACK ( 0xAA99AA ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 2 , 0 , 0 , 0 , 20 , 1 , 1 , 31 , SC_LIQUID , R_TEMP - 2.0f + 273.15f , 29 , " Colloid, Hardens under pressure " , ST_LIQUID , TYPE_LIQUID , NULL , NULL } ,
{ " PSTS " , PIXPACK ( 0x776677 ) , 0.0f , 0.00f * CFDS , 0.00f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 20 , 0 , 1 , 100 , SC_CRACKER , R_TEMP - 2.0f + 273.15f , 29 , " Solid form of PSTE, temporary " , ST_SOLID , TYPE_SOLID , NULL , NULL } ,
{ " ANAR " , PIXPACK ( 0xFFFFEE ) , - 0.7f , - 0.02f * CFDS , 0.96f , 0.80f , 0.1f , - 0.1f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 0 , 30 , 1 , 1 , 85 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 70 , " Very light dust. Behaves opposite gravity " , ST_SOLID , TYPE_PART , & update_ANAR , NULL } ,
{ " VINE " , PIXPACK ( 0x079A00 ) , 0.0f , 0.00f * CFDS , 0.95f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 20 , 0 , 0 , 10 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 65 , " Vine, grows " , ST_SOLID , TYPE_SOLID , & update_VINE , NULL } ,
{ " INVS " , PIXPACK ( 0x00CCCC ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 15 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 164 , " Invisible to everything while under pressure. " , ST_SOLID , TYPE_SOLID | PROP_NEUTPASS , NULL , & graphics_INVS } ,
{ " EQVE " , PIXPACK ( 0xFFE0A0 ) , 0.7f , 0.02f * CFDS , 0.96f , 0.80f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 0 , 30 , 0 , 1 , 85 , SC_CRACKER2 , R_TEMP + 0.0f + 273.15f , 70 , " Shared velocity test " , ST_SOLID , TYPE_PART , NULL , NULL } ,
{ " SPWN2 " , PIXPACK ( 0xAAAAAA ) , 0.0f , 0.00f * CFDS , 1.00f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 0 , " STK2 spawn point " , ST_SOLID , TYPE_SOLID , & update_SPAWN2 , NULL } ,
{ " SPWN " , PIXPACK ( 0xAAAAAA ) , 0.0f , 0.00f * CFDS , 1.00f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 0 , " STKM spawn point " , ST_SOLID , TYPE_SOLID , & update_SPAWN , NULL } ,
{ " SHLD " , PIXPACK ( 0xAAAAAA ) , 0.0f , 0.00f * CFDS , 1.00f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 0 , " Shield, spark it to grow " , ST_SOLID , TYPE_SOLID | PROP_LIFE_DEC , & update_SHLD1 , NULL } ,
{ " SHD2 " , PIXPACK ( 0x777777 ) , 0.0f , 0.00f * CFDS , 1.00f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 100 , SC_CRACKER2 , R_TEMP + 0.0f + 273.15f , 0 , " Shield lvl 2 " , ST_SOLID , TYPE_SOLID | PROP_LIFE_DEC , & update_SHLD2 , NULL } ,
{ " SHD3 " , PIXPACK ( 0x444444 ) , 0.0f , 0.00f * CFDS , 1.00f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 100 , SC_CRACKER2 , R_TEMP + 0.0f + 273.15f , 0 , " Shield lvl 3 " , ST_SOLID , TYPE_SOLID | PROP_LIFE_DEC , & update_SHLD3 , NULL } ,
{ " SHD4 " , PIXPACK ( 0x212121 ) , 0.0f , 0.00f * CFDS , 1.00f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 100 , SC_CRACKER2 , R_TEMP + 0.0f + 273.15f , 0 , " Shield lvl 4 " , ST_SOLID , TYPE_SOLID | PROP_LIFE_DEC , & update_SHLD4 , NULL } ,
{ " LOLZ " , PIXPACK ( 0x569212 ) , 0.0f , 0.00f * CFDS , 0.00f , 0.00f , 0.0f , 0.0f , 0.0f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 100 , SC_CRACKER2 , 373.0f , 40 , " Lolz " , ST_GAS , TYPE_SOLID , & update_MISC , NULL } ,
{ " WIFI " , PIXPACK ( 0x40A060 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 2 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 0 , " Wireless transmitter, color coded. " , ST_SOLID , TYPE_SOLID , & update_WIFI , & graphics_WIFI } ,
{ " FILT " , PIXPACK ( 0x000056 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 251 , " Filter for photons, changes the color. " , ST_SOLID , TYPE_SOLID , NULL , & graphics_FILT } ,
{ " ARAY " , PIXPACK ( 0xFFBB00 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 0 , " Ray Emitter. Rays create points when they collide " , ST_SOLID , TYPE_SOLID | PROP_LIFE_DEC , & update_ARAY , NULL } ,
{ " BRAY " , PIXPACK ( 0xFFFFFF ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 0 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 251 , " Ray Point. Rays create points when they collide " , ST_SOLID , TYPE_SOLID | PROP_LIFE_DEC | PROP_LIFE_KILL , NULL , & graphics_BRAY } ,
{ " STK2 " , PIXPACK ( 0x000000 ) , 0.5f , 0.00f * CFDS , 0.2f , 1.0f , 0.0f , 0.0f , 0.0f , 0.00f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 50 , SC_SPECIAL , R_TEMP + 14.6f + 273.15f , 0 , " Stickman. Don't kill him! " , ST_NONE , 0 , & update_STKM2 , & graphics_STKM2 } ,
{ " BOMB " , PIXPACK ( 0xFFF288 ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 0 , 20 , 1 , 1 , 30 , SC_EXPLOSIVE , R_TEMP - 2.0f + 273.15f , 29 , " Bomb. " , ST_NONE , TYPE_PART | PROP_LIFE_DEC | PROP_LIFE_KILL_DEC | PROP_SPARKSETTLE , & update_BOMB , & graphics_BOMB } ,
{ " C-5 " , PIXPACK ( 0x2050E0 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 100 , SC_EXPLOSIVE , R_TEMP + 0.0f + 273.15f , 88 , " Cold explosive " , ST_SOLID , TYPE_SOLID | PROP_NEUTPENETRATE , & update_C5 , NULL } ,
{ " SING " , PIXPACK ( 0x242424 ) , 0.7f , 0.36f * CFDS , 0.96f , 0.80f , 0.1f , 0.12f , 0.00f , - 0.001f * CFDS , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 86 , SC_NUCLEAR , R_TEMP + 0.0f + 273.15f , 70 , " Singularity " , ST_SOLID , TYPE_PART | PROP_LIFE_DEC , & update_SING , NULL } ,
{ " QRTZ " , PIXPACK ( 0xAADDDD ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 100 , SC_SOLIDS , R_TEMP + 0.0f + 273.15f , 3 , " Quartz, breakable mineral. Conducts but becomes brittle at lower temperatures. " , ST_SOLID , TYPE_SOLID | PROP_HOT_GLOW | PROP_LIFE_DEC , & update_QRTZ , & graphics_QRTZ } ,
{ " PQRT " , PIXPACK ( 0x88BBBB ) , 0.4f , 0.04f * CFDS , 0.94f , 0.95f , - 0.1f , 0.27f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 90 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 3 , " Broken quartz. " , ST_SOLID , TYPE_PART | PROP_HOT_GLOW , & update_QRTZ , & graphics_QRTZ } ,
{ " EMP " , PIXPACK ( 0x66AAFF ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.0f , 0.0f * CFDS , 0 , 0 , 0 , 0 , 3 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 121 , " Breaks activated electronics. " , ST_SOLID , TYPE_SOLID | PROP_LIFE_DEC , & update_EMP , & graphics_EMP } ,
{ " BREL " , PIXPACK ( 0x707060 ) , 0.4f , 0.04f * CFDS , 0.94f , 0.95f , - 0.1f , 0.18f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 2 , 2 , 1 , 1 , 90 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 211 , " Broken electronics " , ST_SOLID , TYPE_PART | PROP_CONDUCTS | PROP_LIFE_DEC | PROP_HOT_GLOW , NULL , NULL } ,
{ " ELEC " , PIXPACK ( 0xDFEFFF ) , 0.0f , 0.00f * CFDS , 1.00f , 1.00f , - 0.99f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , - 1 , SC_NUCLEAR , R_TEMP + 200.0f + 273.15f , 251 , " Electrons " , ST_GAS , TYPE_ENERGY | PROP_LIFE_DEC | PROP_LIFE_KILL_DEC , & update_ELEC , & graphics_ELEC } ,
{ " ACEL " , PIXPACK ( 0x0099CC ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 100 , SC_POWERED , R_TEMP + 0.0f + 273.15f , 251 , " Accelerator " , ST_NONE , TYPE_SOLID , & update_ACEL , & graphics_ACEL } ,
{ " DCEL " , PIXPACK ( 0x99CC00 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 100 , SC_POWERED , R_TEMP + 0.0f + 273.15f , 251 , " Decelerator " , ST_NONE , TYPE_SOLID , & update_DCEL , & graphics_DCEL } ,
{ " TNT " , PIXPACK ( 0xC05050 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 100 , SC_EXPLOSIVE , R_TEMP + 0.0f + 273.15f , 88 , " Explosive. " , ST_SOLID , TYPE_SOLID | PROP_NEUTPENETRATE , & update_BANG , NULL } ,
{ " IGNC " , PIXPACK ( 0xC0B050 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 100 , SC_EXPLOSIVE , R_TEMP + 0.0f + 273.15f , 88 , " Ignition cord. " , ST_SOLID , TYPE_SOLID | PROP_NEUTPENETRATE | PROP_SPARKSETTLE | PROP_LIFE_KILL , & update_IGNT , NULL } ,
{ " BOYL " , PIXPACK ( 0x0A3200 ) , 1.0f , 0.01f * CFDS , 0.99f , 0.30f , - 0.1f , 0.0f , 0.18f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , SC_GAS , R_TEMP + 2.0f + 273.15f , 42 , " Boyle, variable pressure gas. Expands when heated. " , ST_GAS , TYPE_GAS , & update_BOYL , NULL } ,
/*FREE*/ { " LOTE " , PIXPACK ( 0xFF0000 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 100 , SC_LIFE , 9000.0f , 40 , " Behaves kinda like Living on the Edge S3458/B37/4 " , ST_NONE , TYPE_SOLID | PROP_LIFE , NULL , NULL } ,
/*FREE*/ { " FRG2 " , PIXPACK ( 0x00FF00 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 100 , SC_LIFE , 9000.0f , 40 , " Like Frogs rule S124/B3/3 " , ST_NONE , TYPE_SOLID | PROP_LIFE , NULL , NULL } ,
/*FREE*/ { " STAR " , PIXPACK ( 0x0000FF ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 100 , SC_LIFE , 9000.0f , 40 , " Like Star Wars rule S3456/B278/6 " , ST_NONE , TYPE_SOLID | PROP_LIFE , NULL , NULL } ,
/*FREE*/ { " FROG " , PIXPACK ( 0x00AA00 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 100 , SC_LIFE , 9000.0f , 40 , " Frogs S12/B34/3 " , ST_NONE , TYPE_SOLID | PROP_LIFE , NULL , NULL } ,
/*FREE*/ { " BRAN " , PIXPACK ( 0xCCCC00 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 100 , SC_LIFE , 9000.0f , 40 , " Brian 6 S6/B246/3 " , ST_NONE , TYPE_SOLID | PROP_LIFE , NULL , NULL } ,
/*FREE*/ { " WIND " , PIXPACK ( 0x101010 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 100 , SC_SPECIAL , 0.0f , 40 , " " , ST_NONE , ST_NONE , NULL , NULL } ,
{ " HYGN " , PIXPACK ( 0x5070FF ) , 2.0f , 0.00f * CFDS , 0.99f , 0.30f , - 0.10f , 0.00f , 3.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , SC_GAS , R_TEMP + 0.0f + 273.15f , 251 , " Combines with O2 to make WATR " , ST_GAS , TYPE_GAS , & update_H2 , NULL } ,
{ " SOAP " , PIXPACK ( 0xF5F5DC ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 2 , 0 , 0 , 0 , 20 , 1 , 1 , 35 , SC_LIQUID , R_TEMP - 2.0f + 273.15f , 29 , " Soap. Creates bubbles. " , ST_LIQUID , TYPE_LIQUID | PROP_NEUTPENETRATE | PROP_LIFE_DEC , & update_SOAP , NULL } ,
{ " BHOL " , PIXPACK ( 0x202020 ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 100 , SC_SPECIAL , R_TEMP + 0.0f + 273.15f , 186 , " Black hole (Requires newtonian gravity) " , ST_SOLID , TYPE_SOLID , & update_NBHL , NULL } ,
{ " WHOL " , PIXPACK ( 0xFFFFFF ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 100 , SC_SPECIAL , R_TEMP + 0.0f + 273.15f , 186 , " White hole (Requires newtonian gravity) " , ST_SOLID , TYPE_SOLID , & update_NWHL , NULL } ,
{ " MERC " , PIXPACK ( 0x736B6D ) , 0.4f , 0.04f * CFDS , 0.94f , 0.80f , 0.0f , 0.3f , 0.00f , 0.000f * CFDS , 2 , 0 , 0 , 0 , 20 , 1 , 1 , 91 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 251 , " Mercury. Volume changes with temperature, Conductive. " , ST_LIQUID , TYPE_LIQUID | PROP_CONDUCTS | PROP_NEUTABSORB | PROP_LIFE_DEC , & update_MERC , NULL } ,
{ " PBCN " , PIXPACK ( 0x3B1D0A ) , 0.0f , 0.00f * CFDS , 0.97f , 0.50f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 12 , 1 , 1 , 100 , SC_POWERED , R_TEMP + 0.0f + 273.15f , 251 , " Powered breakable clone " , ST_NONE , TYPE_SOLID , & update_PBCN , & graphics_PBCN } ,
{ " GPMP " , PIXPACK ( 0x0A3B3B ) , 0.0f , 0.00f * CFDS , 0.90f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 100 , SC_POWERED , 0.0f + 273.15f , 0 , " Changes gravity to its temp when activated. (use HEAT/COOL). " , ST_NONE , TYPE_SOLID , & update_GPMP , & graphics_GPMP } ,
{ " CLST " , PIXPACK ( 0xE4A4A4 ) , 0.7f , 0.02f * CFDS , 0.94f , 0.95f , 0.0f , 0.2f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 2 , 2 , 1 , 1 , 55 , SC_POWDERS , R_TEMP + 0.0f + 273.15f , 70 , " Clay dust. Produces paste when mixed with water. " , ST_SOLID , TYPE_PART , & update_CLST , & graphics_CLST } ,
{ " WIRE " , PIXPACK ( 0xFFCC00 ) , 0.0f , 0.00f * CFDS , 0.00f , 0.00f , 0.0f , 0.0f , 0.00f , 0.000f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 100 , SC_ELEC , R_TEMP + 0.0f + 273.15f , 250 , " WireWorld wires. " , ST_SOLID , TYPE_SOLID , & update_WIRE , & graphics_WIRE } ,
{ " GBMB " , PIXPACK ( 0x1144BB ) , 0.6f , 0.01f * CFDS , 0.98f , 0.95f , 0.0f , 0.1f , 0.00f , 0.000f * CFDS , 1 , 0 , 0 , 0 , 20 , 1 , 1 , 30 , SC_EXPLOSIVE , R_TEMP - 2.0f + 273.15f , 29 , " Sticks to first object it touches then produces strong gravity push. " , ST_NONE , TYPE_PART | PROP_LIFE_DEC | PROP_LIFE_KILL_DEC , & update_GBMB , & graphics_GBMB } ,
{ " FIGH " , PIXPACK ( 0x000000 ) , 0.5f , 0.00f * CFDS , 0.2f , 1.0f , 0.0f , 0.0f , 0.0f , 0.00f * CFDS , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 50 , SC_SPECIAL , R_TEMP + 14.6f + 273.15f , 0 , " Fighter. Tries to kill stickmen. " , ST_NONE , 0 , & update_FIGH , & graphics_FIGH } ,
//Name Colour Advec Airdrag Airloss Loss Collid Grav Diffus Hotair Fal Burn Exp Mel Hrd M Use Weight Section H Ins Description
} ;
memcpy ( ptypes , ptypest , sizeof ( part_type ) * PT_NUM ) ;
# define IPL -257.0f
# define IPH 257.0f
# define ITL MIN_TEMP-1
# define ITH MAX_TEMP+1
// no transition (PT_NONE means kill part)
# define NT -1
// special transition - lava ctypes etc need extra code, which is only found and run if ST is given
# define ST PT_NUM
part_transition ptransitionst [ PT_NUM ] =
{ // if low pressure if high pressure if low temperature if high temperature
// Name plv plt phv pht tlv tlt thv tht
/* NONE */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* DUST */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* WATR */ { IPL , NT , IPH , NT , 273.15f , PT_ICEI , 373.0f , PT_WTRV } ,
/* OIL */ { IPL , NT , IPH , NT , ITL , NT , 333.0f , PT_GAS } ,
/* FIRE */ { IPL , NT , IPH , NT , ITL , NT , 2773.0f , PT_PLSM } ,
/* STNE */ { IPL , NT , IPH , NT , ITL , NT , 983.0f , PT_LAVA } ,
/* LAVA */ { IPL , NT , IPH , NT , 2573.15f , ST , ITH , NT } , // 2573.15f is highest melt pt of possible ctypes
/* GUN */ { IPL , NT , IPH , NT , ITL , NT , 673.0f , PT_FIRE } ,
/* NITR */ { IPL , NT , IPH , NT , ITL , NT , 673.0f , PT_FIRE } ,
/* CLNE */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* GAS */ { IPL , NT , 6.0f , PT_OIL , ITL , NT , 573.0f , PT_FIRE } ,
/* C-4 */ { IPL , NT , IPH , NT , ITL , NT , 673.0f , PT_FIRE } ,
/* GOO */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* ICE */ { IPL , NT , 0.8f , PT_SNOW , ITL , NT , 233.0f , ST } ,
/* METL */ { IPL , NT , IPH , NT , ITL , NT , 1273.0f , PT_LAVA } ,
/* SPRK */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* SNOW */ { IPL , NT , IPH , NT , ITL , NT , 273.0f , PT_WATR } ,
/* WOOD */ { IPL , NT , IPH , NT , ITL , NT , 873.0f , PT_FIRE } ,
/* NEUT */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* PLUT */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* PLNT */ { IPL , NT , IPH , NT , ITL , NT , 573.0f , PT_FIRE } ,
/* ACID */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* VOID */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* WTRV */ { IPL , NT , IPH , NT , 371.0f , ST , ITH , NT } ,
/* CNCT */ { IPL , NT , IPH , NT , ITL , NT , 1123.0f , PT_LAVA } ,
/* DSTW */ { IPL , NT , IPH , NT , 273.15f , PT_ICEI , 373.0f , PT_WTRV } ,
/* SALT */ { IPL , NT , IPH , NT , ITL , NT , 1173.0f , PT_LAVA } ,
/* SLTW */ { IPL , NT , IPH , NT , 233.0f , PT_ICEI , 483.0f , ST } ,
/* DMND */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* BMTL */ { IPL , NT , 1.0f , ST , ITL , NT , 1273.0f , PT_LAVA } ,
/* BRMT */ { IPL , NT , IPH , NT , ITL , NT , 1273.0f , PT_LAVA } ,
/* PHOT */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* URAN */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* WAX */ { IPL , NT , IPH , NT , ITL , NT , 319.0f , PT_MWAX } ,
/* MWAX */ { IPL , NT , IPH , NT , 318.0f , PT_WAX , 673.0f , PT_FIRE } ,
/* PSCN */ { IPL , NT , IPH , NT , ITL , NT , 1687.0f , PT_LAVA } ,
/* NSCN */ { IPL , NT , IPH , NT , ITL , NT , 1687.0f , PT_LAVA } ,
/* LN2 */ { IPL , NT , IPH , NT , 63.0f , PT_NICE , 77.0f , PT_NONE } ,
/* INSL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* VACU */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* VENT */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* RBDM */ { IPL , NT , IPH , NT , ITL , NT , 312.0f , PT_LRBD } ,
/* LRBD */ { IPL , NT , IPH , NT , 311.0f , PT_RBDM , 961.0f , PT_FIRE } ,
/* NTCT */ { IPL , NT , IPH , NT , ITL , NT , 1687.0f , PT_LAVA } ,
/* SAND */ { IPL , NT , IPH , NT , ITL , NT , 1973.0f , PT_LAVA } ,
/* GLAS */ { IPL , NT , IPH , NT , ITL , NT , 1973.0f , PT_LAVA } ,
/* PTCT */ { IPL , NT , IPH , NT , ITL , NT , 1414.0f , PT_LAVA } ,
/* BGLA */ { IPL , NT , IPH , NT , ITL , NT , 1973.0f , PT_LAVA } ,
/* THDR */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* PLSM */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* ETRD */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* NICE */ { IPL , NT , IPH , NT , ITL , NT , 63.1f , PT_LNTG } ,
/* NBLE */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* BTRY */ { IPL , NT , IPH , NT , ITL , NT , 2273.0f , PT_PLSM } ,
/* LCRY */ { IPL , NT , IPH , NT , ITL , NT , 1273.0f , PT_BGLA } ,
/* STKM */ { IPL , NT , IPH , NT , ITL , NT , 620.0f , PT_FIRE } ,
/* SWCH */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* SMKE */ { IPL , NT , IPH , NT , ITL , NT , 625.0f , PT_FIRE } ,
/* DESL */ { IPL , NT , 5.0f , PT_FIRE , ITL , NT , 335.0f , PT_FIRE } ,
/* COAL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* LO2 */ { IPL , NT , IPH , NT , ITL , NT , 90.1f , PT_O2 } ,
/* O2 */ { IPL , NT , IPH , NT , 90.0f , PT_LO2 , ITH , NT } ,
/* INWR */ { IPL , NT , IPH , NT , ITL , NT , 1687.0f , PT_LAVA } ,
/* YEST */ { IPL , NT , IPH , NT , ITL , NT , 373.0f , PT_DYST } ,
/* DYST */ { IPL , NT , IPH , NT , ITL , NT , 473.0f , PT_DUST } ,
/* THRM */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* GLOW */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* BRCK */ { IPL , NT , 8.8f , PT_STNE , ITL , NT , 1223.0f , PT_LAVA } ,
/* CFLM */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* FIRW */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* FUSE */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* FSEP */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* AMTR */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* BCOL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* PCLN */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* HSWC */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* IRON */ { IPL , NT , IPH , NT , ITL , NT , 1687.0f , PT_LAVA } ,
/* MORT */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* LIFE */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* DLAY */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* CO2 */ { IPL , NT , IPH , NT , 194.65f , PT_DRIC , ITH , NT } ,
/* DRIC */ { IPL , NT , IPH , NT , ITL , NT , 195.65f , PT_CO2 } ,
/* CBNW */ { IPL , NT , IPH , NT , 273.15f , PT_ICEI , 373.0f , PT_WTRV } ,
/* STOR */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* STOR */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/*FREE*/ /* GOL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/*FREE*/ /* GOL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/*FREE*/ /* GOL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/*FREE*/ /* GOL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/*FREE*/ /* GOL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* SPNG */ { IPL , NT , IPH , NT , ITL , NT , 2730.0f , PT_FIRE } ,
/* RIME */ { IPL , NT , IPH , NT , ITL , NT , 273.15f , PT_WATR } ,
/* FOG */ { IPL , NT , IPH , NT , ITL , NT , 373.15f , PT_WTRV } ,
/* BCLN */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* LOVE */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* DEUT */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* WARP */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* PUMP */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* FWRK */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* PIPE */ { IPL , NT , 10.0f , PT_BRMT , ITL , NT , ITH , NT } ,
/* FRZZ */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* FRZW */ { IPL , NT , IPH , NT , ITL , NT , 53.0f , PT_ICEI } ,
/* GRAV */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* BIZR */ { IPL , NT , IPH , NT , 100.0f , PT_BIZRG , 400.0f , PT_BIZRS } ,
/* BIZRG*/ { IPL , NT , IPH , NT , ITL , NT , 100.0f , PT_BIZR } , //, 400.0f, PT_BIZRS},
/* BIZRS*/ { IPL , NT , IPH , NT , 400.0f , PT_BIZR , ITH , NT } , // 100.0f, PT_BIZRG},
/* INST */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* ISOZ */ { IPL , NT , IPH , NT , 160.0f , PT_ISZS , ITH , NT } ,
/* ISZS */ { IPL , NT , IPH , NT , ITL , NT , 300.0f , PT_ISOZ } ,
/* PRTI */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* PRTO */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* PSTE */ { IPL , NT , 0.5f , PT_PSTS , ITL , NT , 747.0f , PT_BRCK } ,
/* PSTS */ { 0.5f , PT_PSTE , IPH , NT , ITL , NT , ITH , NT } ,
/* ANAR */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* VINE */ { IPL , NT , IPH , NT , ITL , NT , 573.0f , PT_FIRE } ,
/* INVS */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* EQVE */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* SPWN2*/ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* SPAWN*/ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* SHLD1*/ { IPL , NT , 7.0f , PT_NONE , ITL , NT , ITH , NT } ,
/* SHLD2*/ { IPL , NT , 15.0f , PT_NONE , ITL , NT , ITH , NT } ,
/* SHLD3*/ { IPL , NT , 25.0f , PT_NONE , ITL , NT , ITH , NT } ,
/* SHLD4*/ { IPL , NT , 40.0f , PT_NONE , ITL , NT , ITH , NT } ,
/* LOlZ */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* WIFI */ { IPL , NT , 15.0f , PT_BRMT , ITL , NT , ITH , NT } ,
/* FILT */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* ARAY */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* BRAY */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* STKM2*/ { IPL , NT , IPH , NT , ITL , NT , 620.0f , PT_FIRE } ,
/* BOMB */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* C-5 */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* SING */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* QRTZ */ { IPL , NT , IPH , NT , ITL , NT , 2573.15f , PT_LAVA } ,
/* PQRT */ { IPL , NT , IPH , NT , ITL , NT , 2573.15f , PT_LAVA } ,
/* EMP */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* BREL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* ELEC */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* ACEL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* DCEL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* TNT */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* IGNP */ { IPL , NT , IPH , NT , ITL , NT , 673.0f , PT_FIRE } ,
/* BOYL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/*FREE*/ /* GOL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/*FREE*/ /* GOL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/*FREE*/ /* GOL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/*FREE*/ /* GOL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/*FREE*/ /* GOL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* WIND */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* H2 */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* SOAP */ { IPL , NT , IPH , NT , ITL , NT , ITL , NT } ,
/* NBHL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* NWHL */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* MERC */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* PBCN */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* GPMP */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* CLST */ { IPL , NT , IPH , NT , ITL , NT , 1256.0f , PT_LAVA } ,
/* WIRE */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* GBMB */ { IPL , NT , IPH , NT , ITL , NT , ITH , NT } ,
/* FIGH */ { IPL , NT , IPH , NT , ITL , NT , 620.0f , PT_FIRE } ,
} ;
# undef IPL
# undef IPH
# undef ITL
# undef ITH
# undef NT
# undef ST* /
memcpy ( ptransitions , ptransitionst , sizeof ( part_transition ) * PT_NUM ) ;
init_can_move ( ) ;
clear_sim ( ) ;
}