2013-01-20 17:08:16 -06:00
# include "simulation/Elements.h"
//#TPT-Directive ElementClass Element_PSTN PT_PSTN 168
Element_PSTN : : Element_PSTN ( )
{
Identifier = " DEFAULT_PT_PSTN " ;
Name = " PSTN " ;
2013-01-26 12:04:24 -06:00
Colour = PIXPACK ( 0xAA9999 ) ;
2013-01-20 17:08:16 -06:00
MenuVisible = 1 ;
2013-01-26 12:04:24 -06:00
MenuSection = SC_FORCE ;
2013-01-20 17:08:16 -06:00
Enabled = 1 ;
Advection = 0.0f ;
AirDrag = 0.00f * CFDS ;
AirLoss = 0.90f ;
Loss = 0.00f ;
Collision = 0.0f ;
Gravity = 0.0f ;
Diffusion = 0.00f ;
HotAir = 0.000f * CFDS ;
Falldown = 0 ;
Flammable = 0 ;
Explosive = 0 ;
Meltable = 0 ;
2013-01-26 12:04:24 -06:00
Hardness = 0 ;
2013-01-20 17:08:16 -06:00
Weight = 100 ;
Temperature = R_TEMP + 0.0f + 273.15f ;
HeatConduct = 0 ;
Description = " Piston, extends and pushes particles " ;
State = ST_SOLID ;
2013-03-03 15:36:37 -06:00
Properties = TYPE_SOLID ;
2013-01-20 17:08:16 -06:00
LowPressure = IPL ;
LowPressureTransition = NT ;
HighPressure = IPH ;
HighPressureTransition = NT ;
LowTemperature = ITL ;
LowTemperatureTransition = NT ;
HighTemperature = ITH ;
HighTemperatureTransition = NT ;
Update = & Element_PSTN : : update ;
Graphics = & Element_PSTN : : graphics ;
}
//#TPT-Directive ElementHeader Element_PSTN static int tempParts[128];
int Element_PSTN : : tempParts [ 128 ] ;
2013-01-26 13:44:05 -06:00
# define PISTON_INACTIVE 0x00
# define PISTON_RETRACT 0x01
# define PISTON_EXTEND 0x02
# define MAX_FRAME 0x0F
# define DEFAULT_LIMIT 0x1F
# define DEFAULT_ARM_LIMIT 0xFF
2013-01-20 17:08:16 -06:00
//#TPT-Directive ElementHeader Element_PSTN static int update(UPDATE_FUNC_ARGS)
int Element_PSTN : : update ( UPDATE_FUNC_ARGS )
{
2013-03-03 15:36:37 -06:00
if ( parts [ i ] . life )
2013-01-23 06:06:06 -06:00
return 0 ;
2013-01-23 13:52:45 -06:00
int maxSize = parts [ i ] . tmp ? parts [ i ] . tmp : DEFAULT_LIMIT ;
2013-01-26 13:44:05 -06:00
int armLimit = parts [ i ] . tmp2 ? parts [ i ] . tmp2 : DEFAULT_ARM_LIMIT ;
int state = 0 ;
2013-01-22 16:42:52 -06:00
int r , nxx , nyy , nxi , nyi , rx , ry ;
2013-01-23 06:06:06 -06:00
int directionX = 0 , directionY = 0 ;
2013-03-03 15:36:37 -06:00
if ( state = = PISTON_INACTIVE ) {
2013-01-23 13:20:52 -06:00
for ( rx = - 2 ; rx < 3 ; rx + + )
for ( ry = - 2 ; ry < 3 ; ry + + )
if ( x + rx > = 0 & & y + ry > 0 & & x + rx < XRES & & y + ry < YRES & & ( rx | | ry ) & & ( ! rx | | ! ry ) )
2013-01-20 17:08:16 -06:00
{
r = pmap [ y + ry ] [ x + rx ] ;
if ( ! r )
continue ;
if ( ( r & 0xFF ) = = PT_SPRK & & parts [ r > > 8 ] . life = = 3 ) {
2013-01-23 06:06:06 -06:00
if ( parts [ r > > 8 ] . ctype = = PT_PSCN )
state = PISTON_EXTEND ;
else
state = PISTON_RETRACT ;
}
}
}
if ( state = = PISTON_EXTEND | | state = = PISTON_RETRACT ) {
for ( rx = - 1 ; rx < 2 ; rx + + )
for ( ry = - 1 ; ry < 2 ; ry + + )
if ( x + rx > = 0 & & y + ry > 0 & & x + rx < XRES & & y + ry < YRES & & ( rx | | ry ) & & ( ! rx | | ! ry ) )
{
r = pmap [ y + ry ] [ x + rx ] ;
if ( ! r )
continue ;
2013-02-27 23:40:36 -06:00
if ( ( r & 0xFF ) = = PT_PSTN )
{
2013-02-22 15:50:33 -06:00
bool movedPiston = false ;
2013-02-27 23:40:36 -06:00
bool foundEnd = false ;
int pistonEndX , pistonEndY ;
int pistonCount = 0 ;
int newSpace = 0 ;
int armCount = 0 ;
2013-01-23 06:06:06 -06:00
directionX = rx ;
directionY = ry ;
2013-02-27 23:40:36 -06:00
for ( nxx = 0 , nyy = 0 , nxi = directionX , nyi = directionY ; ; nyy + = nyi , nxx + = nxi ) {
if ( ! ( x + nxi + nxx < XRES & & y + nyi + nyy < YRES & & x + nxi + nxx > = 0 & & y + nyi + nyy > = 0 ) ) {
break ;
}
r = pmap [ y + nyi + nyy ] [ x + nxi + nxx ] ;
if ( ( r & 0xFF ) = = PT_PSTN ) {
2013-03-03 15:36:37 -06:00
if ( parts [ r > > 8 ] . life )
2013-02-27 23:40:36 -06:00
armCount + + ;
else if ( armCount )
{
2013-01-23 06:06:06 -06:00
pistonEndX = x + nxi + nxx ;
pistonEndY = y + nyi + nyy ;
foundEnd = true ;
break ;
}
2013-02-27 23:40:36 -06:00
else
pistonCount + + ;
} else {
pistonEndX = x + nxi + nxx ;
pistonEndY = y + nyi + nyy ;
foundEnd = true ;
break ;
2013-01-20 17:08:16 -06:00
}
2013-02-27 23:40:36 -06:00
}
if ( foundEnd ) {
if ( state = = PISTON_EXTEND ) {
if ( armCount + pistonCount > armLimit )
pistonCount = armLimit - armCount ;
if ( pistonCount > 0 ) {
2013-03-03 15:36:37 -06:00
newSpace = MoveStack ( sim , pistonEndX , pistonEndY , directionX , directionY , maxSize , pistonCount , false , parts [ i ] . ctype , true ) ;
2013-02-27 23:40:36 -06:00
if ( newSpace ) {
//Create new piston section
for ( int j = 0 ; j < newSpace ; j + + ) {
int nr = sim - > create_part ( - 3 , pistonEndX + ( nxi * j ) , pistonEndY + ( nyi * j ) , PT_PSTN ) ;
2013-03-03 15:36:37 -06:00
if ( nr > - 1 ) {
parts [ nr ] . life = 1 ;
2013-01-23 06:06:06 -06:00
}
}
2013-02-27 23:40:36 -06:00
movedPiston = true ;
2013-01-23 06:06:06 -06:00
}
2013-02-27 23:40:36 -06:00
}
} else if ( state = = PISTON_RETRACT ) {
if ( pistonCount > armCount )
pistonCount = armCount ;
if ( armCount ) {
2013-03-03 15:36:37 -06:00
MoveStack ( sim , pistonEndX , pistonEndY , directionX , directionY , maxSize , pistonCount , true , parts [ i ] . ctype , true ) ;
2013-02-27 23:40:36 -06:00
movedPiston = true ;
2013-01-20 17:08:16 -06:00
}
}
}
2013-02-22 15:50:33 -06:00
if ( movedPiston )
2013-03-01 22:06:02 -06:00
return 0 ;
2013-01-20 17:08:16 -06:00
}
}
2013-01-23 06:06:06 -06:00
2013-01-20 17:08:16 -06:00
}
return 0 ;
}
2013-03-03 15:36:37 -06:00
//#TPT-Directive ElementHeader Element_PSTN static int CanMoveStack(Simulation * sim, int stackX, int stackY, int directionX, int directionY, int maxSize, int amount, bool retract, int block)
int Element_PSTN : : CanMoveStack ( Simulation * sim , int stackX , int stackY , int directionX , int directionY , int maxSize , int amount , bool retract , int block )
2013-02-21 22:35:44 -06:00
{
int posX , posY , r , spaces = 0 , currentPos = 0 ;
if ( amount = = 0 )
return 0 ;
2013-03-03 15:36:37 -06:00
for ( posX = stackX , posY = stackY ; currentPos < maxSize + amount ; posX + = directionX , posY + = directionY ) {
2013-02-21 22:35:44 -06:00
if ( ! ( posX < XRES & & posY < YRES & & posX > = 0 & & posY > = 0 ) ) {
break ;
}
r = sim - > pmap [ posY ] [ posX ] ;
2013-03-03 15:36:37 -06:00
if ( sim - > IsWallBlocking ( posX , posY , 0 ) | | ( block & & ( r & 0xFF ) = = block ) )
2013-02-21 22:35:44 -06:00
break ;
if ( ! r ) {
spaces + + ;
tempParts [ currentPos + + ] = - 1 ;
if ( spaces > = amount )
break ;
} else {
2013-03-03 15:36:37 -06:00
if ( currentPos < maxSize & & ! retract )
2013-02-21 22:35:44 -06:00
tempParts [ currentPos + + ] = r > > 8 ;
else
return spaces ;
}
}
if ( spaces )
return currentPos ;
else
return 0 ;
}
2013-03-03 15:36:37 -06:00
//#TPT-Directive ElementHeader Element_PSTN static int MoveStack(Simulation * sim, int stackX, int stackY, int directionX, int directionY, int maxSize, int amount, bool retract, int block, bool sticky, int callDepth = 0)
int Element_PSTN : : MoveStack ( Simulation * sim , int stackX , int stackY , int directionX , int directionY , int maxSize , int amount , bool retract , int block , bool sticky , int callDepth )
2013-01-20 17:08:16 -06:00
{
2013-01-26 11:14:44 -06:00
bool foundParts = false ;
2013-01-20 17:08:16 -06:00
int posX , posY , r , spaces = 0 , currentPos = 0 ;
2013-01-23 06:36:31 -06:00
r = sim - > pmap [ stackY ] [ stackX ] ;
if ( ! callDepth & & ( r & 0xFF ) = = PT_FRME ) {
int newY = ! ! directionX , newX = ! ! directionY ;
2013-03-01 22:06:02 -06:00
int realDirectionX = retract ? - directionX : directionX ;
int realDirectionY = retract ? - directionY : directionY ;
int maxRight = MAX_FRAME , maxLeft = MAX_FRAME ;
//check if we can push all the FRME
for ( int c = retract ; c < MAX_FRAME ; c + + ) {
posY = stackY + ( c * newY ) ;
posX = stackX + ( c * newX ) ;
if ( posX < XRES & & posY < YRES & & posX > = 0 & & posY > = 0 & & ( sim - > pmap [ posY ] [ posX ] & 0xFF ) = = PT_FRME ) {
2013-03-03 15:36:37 -06:00
int val = CanMoveStack ( sim , posX + realDirectionX , posY + realDirectionY , realDirectionX , realDirectionY , maxSize , amount , retract , block ) ;
2013-03-01 22:06:02 -06:00
if ( val < amount )
amount = val ;
} else {
maxRight = c ;
break ;
2013-02-21 22:35:44 -06:00
}
2013-03-01 22:06:02 -06:00
}
for ( int c = 1 ; c < MAX_FRAME ; c + + ) {
posY = stackY - ( c * newY ) ;
posX = stackX - ( c * newX ) ;
if ( posX < XRES & & posY < YRES & & posX > = 0 & & posY > = 0 & & ( sim - > pmap [ posY ] [ posX ] & 0xFF ) = = PT_FRME ) {
2013-03-03 15:36:37 -06:00
int val = CanMoveStack ( sim , posX + realDirectionX , posY + realDirectionY , realDirectionX , realDirectionY , maxSize , amount , retract , block ) ;
2013-03-01 22:06:02 -06:00
if ( val < amount )
amount = val ;
} else {
maxLeft = c ;
break ;
2013-02-21 22:35:44 -06:00
}
}
2013-03-01 22:06:02 -06:00
2013-01-23 06:36:31 -06:00
//If the piston is pushing frame, iterate out from the centre to the edge and push everything resting on frame
2013-03-01 22:06:02 -06:00
for ( int c = 1 ; c < maxRight ; c + + ) {
2013-01-23 06:36:31 -06:00
posY = stackY + ( c * newY ) ;
posX = stackX + ( c * newX ) ;
2013-03-03 15:36:37 -06:00
MoveStack ( sim , posX , posY , directionX , directionY , maxSize , amount , retract , block , ! sim - > parts [ sim - > pmap [ posY ] [ posX ] > > 8 ] . tmp , 1 ) ;
2013-03-01 22:06:02 -06:00
}
for ( int c = 1 ; c < maxLeft ; c + + ) {
2013-01-23 06:36:31 -06:00
posY = stackY - ( c * newY ) ;
posX = stackX - ( c * newX ) ;
2013-03-03 15:36:37 -06:00
MoveStack ( sim , posX , posY , directionX , directionY , maxSize , amount , retract , block , ! sim - > parts [ sim - > pmap [ posY ] [ posX ] > > 8 ] . tmp , 1 ) ;
2013-01-23 06:36:31 -06:00
}
2013-03-01 22:06:02 -06:00
//Remove arm section if retracting with FRME
if ( retract )
for ( int j = 1 ; j < = amount ; j + + )
sim - > kill_part ( sim - > pmap [ stackY + ( directionY * - j ) ] [ stackX + ( directionX * - j ) ] > > 8 ) ;
2013-03-03 15:36:37 -06:00
return MoveStack ( sim , stackX , stackY , directionX , directionY , maxSize , amount , retract , block , ! sim - > parts [ sim - > pmap [ stackY ] [ stackX ] > > 8 ] . tmp , 1 ) ;
2013-01-23 06:36:31 -06:00
}
2013-01-23 06:06:06 -06:00
if ( retract ) {
2013-03-01 22:06:02 -06:00
//Remove arm section if retracting without FRME
if ( ! callDepth )
for ( int j = 1 ; j < = amount ; j + + )
sim - > kill_part ( sim - > pmap [ stackY + ( directionY * - j ) ] [ stackX + ( directionX * - j ) ] > > 8 ) ;
2013-01-26 11:14:44 -06:00
bool foundEnd = false ;
2013-03-03 15:36:37 -06:00
for ( posX = stackX , posY = stackY ; currentPos < maxSize ; posX + = directionX , posY + = directionY ) {
2013-01-23 06:06:06 -06:00
if ( ! ( posX < XRES & & posY < YRES & & posX > = 0 & & posY > = 0 ) ) {
break ;
}
r = sim - > pmap [ posY ] [ posX ] ;
2013-03-03 15:36:37 -06:00
if ( ! r | | ( r & 0xFF ) = = block | | ( ! sticky & & ( r & 0xFF ) ! = PT_FRME ) ) {
2013-01-23 13:52:45 -06:00
break ;
2013-01-23 06:06:06 -06:00
} else {
foundParts = true ;
tempParts [ currentPos + + ] = r > > 8 ;
}
2013-01-20 17:08:16 -06:00
}
2013-01-23 13:52:45 -06:00
if ( foundParts ) {
2013-01-23 06:06:06 -06:00
//Move particles
for ( int j = 0 ; j < currentPos ; j + + ) {
int jP = tempParts [ j ] ;
2013-01-23 13:52:45 -06:00
sim - > pmap [ ( int ) ( sim - > parts [ jP ] . y + 0.5f ) ] [ ( int ) ( sim - > parts [ jP ] . x + 0.5f ) ] = 0 ;
2013-01-23 06:06:06 -06:00
sim - > parts [ jP ] . x + = ( float ) ( ( - directionX ) * amount ) ;
sim - > parts [ jP ] . y + = ( float ) ( ( - directionY ) * amount ) ;
2013-01-23 13:52:45 -06:00
sim - > pmap [ ( int ) ( sim - > parts [ jP ] . y + 0.5f ) ] [ ( int ) ( sim - > parts [ jP ] . x + 0.5f ) ] = sim - > parts [ jP ] . type | ( jP < < 8 ) ;
2013-01-23 06:06:06 -06:00
}
return amount ;
}
if ( ! foundParts & & foundEnd )
2013-02-21 22:35:44 -06:00
return amount ;
2013-01-23 06:06:06 -06:00
} else {
2013-03-03 15:36:37 -06:00
currentPos = CanMoveStack ( sim , stackX , stackY , directionX , directionY , maxSize , amount , retract , block ) ;
2013-02-21 22:35:44 -06:00
if ( currentPos ) {
2013-01-23 06:06:06 -06:00
//Move particles
2013-01-26 11:14:44 -06:00
int possibleMovement = 0 ;
for ( int j = currentPos - 1 ; j > = 0 ; j - - ) {
2013-01-23 06:06:06 -06:00
int jP = tempParts [ j ] ;
2013-03-03 15:36:37 -06:00
if ( jP < 0 ) {
2013-01-26 11:14:44 -06:00
possibleMovement + + ;
continue ;
}
if ( ! possibleMovement )
continue ;
2013-01-23 13:52:45 -06:00
sim - > pmap [ ( int ) ( sim - > parts [ jP ] . y + 0.5f ) ] [ ( int ) ( sim - > parts [ jP ] . x + 0.5f ) ] = 0 ;
2013-01-26 11:14:44 -06:00
sim - > parts [ jP ] . x + = ( float ) ( directionX * possibleMovement ) ;
sim - > parts [ jP ] . y + = ( float ) ( directionY * possibleMovement ) ;
2013-01-23 13:52:45 -06:00
sim - > pmap [ ( int ) ( sim - > parts [ jP ] . y + 0.5f ) ] [ ( int ) ( sim - > parts [ jP ] . x + 0.5f ) ] = sim - > parts [ jP ] . type | ( jP < < 8 ) ;
2013-01-23 06:06:06 -06:00
}
2013-01-26 11:14:44 -06:00
return possibleMovement ;
2013-01-20 17:08:16 -06:00
}
2013-01-26 11:14:44 -06:00
if ( ! foundParts & & spaces )
return spaces ;
2013-01-20 17:08:16 -06:00
}
return 0 ;
}
//#TPT-Directive ElementHeader Element_PSTN static int graphics(GRAPHICS_FUNC_ARGS)
int Element_PSTN : : graphics ( GRAPHICS_FUNC_ARGS )
{
2013-03-03 15:36:37 -06:00
if ( cpart - > life )
2013-01-20 17:08:16 -06:00
{
* colr - = 60 ;
* colg - = 60 ;
}
return 0 ;
}
2013-02-27 23:40:36 -06:00
Element_PSTN : : ~ Element_PSTN ( ) { }