2020-06-04 11:00:08 +02:00
# include "framework.h"
# include "tr5_rollingball.h"
# include "sphere.h"
# include "camera.h"
# include "control.h"
# include "lara.h"
# include "setup.h"
2020-08-24 18:01:12 -05:00
# include "sound.h"
2020-06-04 11:00:08 +02:00
void RollingBallCollision ( short itemNumber , ITEM_INFO * l , COLL_INFO * coll )
{
2020-07-21 09:56:47 +02:00
ITEM_INFO * item = & g_Level . Items [ itemNumber ] ;
2020-06-04 11:00:08 +02:00
if ( TestBoundsCollide ( item , l , coll - > radius ) )
{
if ( TestCollision ( item , l ) )
{
if ( TriggerActive ( item ) & & ( item - > itemFlags [ 0 ] | | item - > fallspeed ) )
{
2020-08-04 20:32:07 +10:00
LaraItem - > animNumber = LA_BOULDER_DEATH ;
2020-07-21 09:56:47 +02:00
LaraItem - > frameNumber = g_Level . Anims [ LaraItem - > animNumber ] . frameBase ;
2020-08-04 20:32:07 +10:00
LaraItem - > goalAnimState = LS_DEATH ;
LaraItem - > currentAnimState = LS_DEATH ;
2020-06-04 11:00:08 +02:00
LaraItem - > gravityStatus = false ;
}
else
{
ObjectCollision ( itemNumber , l , coll ) ;
}
}
}
}
void RollingBallControl ( short itemNumber )
{
2020-07-21 09:56:47 +02:00
ITEM_INFO * item = & g_Level . Items [ itemNumber ] ;
2020-06-04 11:00:08 +02:00
if ( ! TriggerActive ( item ) )
return ;
item - > fallspeed + = GRAVITY ;
2020-10-17 23:36:06 -05:00
item - > pos . xPos + = item - > itemFlags [ 0 ] / 32 ;
2020-06-04 11:00:08 +02:00
item - > pos . yPos + = item - > fallspeed ;
2020-10-17 23:36:06 -05:00
item - > pos . zPos + = item - > itemFlags [ 1 ] / 32 ;
2020-06-04 11:00:08 +02:00
short roomNumber = item - > roomNumber ;
FLOOR_INFO * floor = GetFloor ( item - > pos . xPos , item - > pos . yPos , item - > pos . zPos , & roomNumber ) ;
int height = GetFloorHeight ( floor , item - > pos . xPos , item - > pos . yPos , item - > pos . zPos ) ;
int dh = height - 512 ;
if ( item - > pos . yPos > height - 512 )
{
if ( abs ( item - > fallspeed ) > 16 )
{
int distance = sqrt (
SQUARE ( Camera . pos . x - item - > pos . xPos ) +
SQUARE ( Camera . pos . y - item - > pos . yPos ) +
SQUARE ( Camera . pos . z - item - > pos . zPos ) ) ;
if ( distance < 16384 )
2020-10-17 23:36:06 -05:00
Camera . bounce = - ( ( ( 16384 - distance ) * abs ( item - > fallspeed ) ) / 16384 ) ;
2020-06-04 11:00:08 +02:00
}
if ( item - > pos . yPos - dh < 512 )
item - > pos . yPos = dh ;
if ( item - > fallspeed < = 64 )
{
if ( abs ( item - > speed ) < = 512 | | GetRandomControl ( ) & 0x1F )
item - > fallspeed = 0 ;
else
2020-10-17 23:36:06 -05:00
item - > fallspeed = - ( short ) ( GetRandomControl ( ) % ( item - > speed / 8 ) ) ;
2020-06-04 11:00:08 +02:00
}
else
{
2020-10-17 23:36:06 -05:00
item - > fallspeed = - ( short ) ( item - > fallspeed / 4 ) ;
2020-06-04 11:00:08 +02:00
}
}
int x = item - > pos . xPos ;
int y = item - > pos . yPos ;
int z = item - > pos . zPos ;
floor = GetFloor ( x , y , z + 128 , & roomNumber ) ;
int y1a = GetFloorHeight ( floor , x , y , z + 128 ) - 512 ;
floor = GetFloor ( x , y , z - 128 , & roomNumber ) ;
int y2a = GetFloorHeight ( floor , x , y , z - 128 ) - 512 ;
floor = GetFloor ( x + 128 , y , z , & roomNumber ) ;
int y3a = GetFloorHeight ( floor , x + 128 , y , z ) - 512 ;
floor = GetFloor ( x - 128 , y , z , & roomNumber ) ;
int y4a = GetFloorHeight ( floor , x - 128 , y , z ) - 512 ;
floor = GetFloor ( x , y , z + 512 , & roomNumber ) ;
int y1b = GetFloorHeight ( floor , x , y , z + 512 ) - 512 ;
floor = GetFloor ( x , y , z - 512 , & roomNumber ) ;
int y2b = GetFloorHeight ( floor , x , y , z - 512 ) - 512 ;
floor = GetFloor ( x + 512 , y , z , & roomNumber ) ;
int y3b = GetFloorHeight ( floor , x + 512 , y , z ) - 512 ;
floor = GetFloor ( x - 512 , y , z , & roomNumber ) ;
int y4b = GetFloorHeight ( floor , x - 512 , y , z ) - 512 ;
if ( item - > pos . yPos - dh > - 256
| | item - > pos . yPos - y1b > = 512
| | item - > pos . yPos - y3b > = 512
| | item - > pos . yPos - y2b > = 512
| | item - > pos . yPos - y4b > = 512 )
{
int counterZ = 0 ;
if ( y1a - dh < = 256 )
{
if ( y1b - dh < - 1024 | | y1a - dh < - 256 )
{
if ( item - > itemFlags [ 1 ] < = 0 )
{
if ( ! item - > itemFlags [ 1 ] & & item - > itemFlags [ 0 ] )
{
item - > pos . zPos = ( item - > pos . zPos & - 512 ) + 512 ;
}
}
else
{
2020-10-17 23:36:06 -05:00
item - > itemFlags [ 1 ] = - item - > itemFlags [ 1 ] / 2 ;
2020-06-04 11:00:08 +02:00
item - > pos . zPos = ( item - > pos . zPos & - 512 ) + 512 ;
}
}
else if ( y1a = = dh )
{
counterZ = 1 ;
}
else
{
2020-10-17 23:36:06 -05:00
item - > itemFlags [ 1 ] + = ( y1a - dh ) / 2 ;
2020-06-04 11:00:08 +02:00
}
}
if ( y2a - dh < = 256 )
{
if ( y2b - dh < - 1024 | | y2a - dh < - 256 )
{
if ( item - > itemFlags [ 1 ] > = 0 )
{
if ( ! item - > itemFlags [ 1 ] & & item - > itemFlags [ 0 ] )
{
item - > pos . zPos = ( item - > pos . zPos & - 512 ) + 512 ;
}
}
else
{
2020-10-17 23:36:06 -05:00
item - > itemFlags [ 1 ] = - item - > itemFlags [ 1 ] / 2 ;
2020-06-04 11:00:08 +02:00
item - > pos . zPos = ( item - > pos . zPos & - 512 ) + 512 ;
}
}
else if ( y2a = = dh )
{
counterZ + + ;
}
else
{
2020-10-17 23:36:06 -05:00
item - > itemFlags [ 1 ] - = ( y2a - dh ) / 2 ;
2020-06-04 11:00:08 +02:00
}
}
if ( counterZ = = 2 )
{
if ( abs ( item - > itemFlags [ 1 ] ) < = 64 )
item - > itemFlags [ 1 ] = 0 ;
else
2020-10-17 23:36:06 -05:00
item - > itemFlags [ 1 ] = item - > itemFlags [ 1 ] - ( item - > itemFlags [ 1 ] / 64 ) ;
2020-06-04 11:00:08 +02:00
}
int counterX = 0 ;
if ( y4a - dh < = 256 )
{
if ( y4b - dh < - 1024 | | y4a - dh < - 256 )
{
if ( item - > itemFlags [ 0 ] > = 0 )
{
if ( ! item - > itemFlags [ 0 ] & & item - > itemFlags [ 1 ] )
{
item - > pos . xPos = ( item - > pos . xPos & - 512 ) + 512 ;
}
}
else
{
2020-10-17 23:36:06 -05:00
item - > itemFlags [ 0 ] = - item - > itemFlags [ 0 ] / 2 ;
2020-06-04 11:00:08 +02:00
item - > pos . xPos = ( item - > pos . xPos & - 512 ) + 512 ;
}
}
else if ( y4a = = dh )
{
counterX = 1 ;
}
else
{
2020-10-17 23:36:06 -05:00
item - > itemFlags [ 0 ] - = ( y4a - dh ) / 2 ;
2020-06-04 11:00:08 +02:00
}
}
if ( y3a - dh < = 256 )
{
if ( y3b - dh < - 1024 | | y3a - dh < - 256 )
{
if ( item - > itemFlags [ 0 ] < = 0 )
{
if ( ! item - > itemFlags [ 0 ] & & item - > itemFlags [ 1 ] )
{
item - > pos . xPos = ( item - > pos . xPos & - 512 ) + 512 ;
}
}
else
{
2020-10-17 23:36:06 -05:00
item - > itemFlags [ 0 ] = - item - > itemFlags [ 0 ] / 2 ;
2020-06-04 11:00:08 +02:00
item - > pos . xPos = ( item - > pos . xPos & - 512 ) + 512 ;
}
}
else if ( y3a = = dh )
{
counterX + + ;
}
else
{
2020-10-17 23:36:06 -05:00
item - > itemFlags [ 0 ] + = ( y3a - dh ) / 2 ;
2020-06-04 11:00:08 +02:00
}
}
if ( counterX = = 2 )
{
if ( abs ( item - > itemFlags [ 0 ] ) < = 64 )
item - > itemFlags [ 0 ] = 0 ;
else
2020-10-17 23:36:06 -05:00
item - > itemFlags [ 0 ] = item - > itemFlags [ 0 ] - ( item - > itemFlags [ 0 ] / 64 ) ;
2020-06-04 11:00:08 +02:00
}
}
GetFloor ( item - > pos . xPos , item - > pos . yPos , item - > pos . zPos , & roomNumber ) ;
if ( item - > roomNumber ! = roomNumber )
ItemNewRoom ( itemNumber , roomNumber ) ;
if ( item - > itemFlags [ 0 ] < = 3072 )
{
if ( item - > itemFlags [ 0 ] < - 3072 )
item - > itemFlags [ 0 ] = - 3072 ;
}
else
{
item - > itemFlags [ 0 ] = 3072 ;
}
if ( item - > itemFlags [ 1 ] < = 3072 )
{
if ( item - > itemFlags [ 1 ] < - 3072 )
item - > itemFlags [ 1 ] = - 3072 ;
}
else
{
item - > itemFlags [ 1 ] = 3072 ;
}
short angle = 0 ;
if ( item - > itemFlags [ 1 ] | | item - > itemFlags [ 0 ] )
angle = phd_atan ( item - > itemFlags [ 1 ] , item - > itemFlags [ 0 ] ) ;
else
angle = item - > pos . yRot ;
if ( item - > pos . yRot ! = angle )
{
if ( ( ( angle - item - > pos . yRot ) & 32767 ) > = 512 )
{
if ( angle < = item - > pos . yRot | | angle - item - > pos . yRot > = 0x8000 )
item - > pos . yRot - = 512 ;
else
item - > pos . yRot + = 512 ;
}
else
{
item - > pos . yRot = angle ;
}
}
2020-10-17 23:36:06 -05:00
item - > pos . xRot - = ( abs ( item - > itemFlags [ 0 ] ) + abs ( item - > itemFlags [ 1 ] ) ) / 2 ;
2020-06-04 11:00:08 +02:00
roomNumber = item - > roomNumber ;
floor = GetFloor ( item - > pos . xPos , item - > pos . yPos , item - > pos . zPos , & roomNumber ) ;
GetFloorHeight ( floor , item - > pos . xPos , item - > pos . yPos , item - > pos . zPos ) ;
TestTriggers ( TriggerIndex , TRUE , NULL ) ;
2020-08-24 13:23:21 -05:00
}
void ClassicRollingBallCollision ( short itemNum , ITEM_INFO * lara , COLL_INFO * coll )
{
int x , y , z ;
short d ;
ITEM_INFO * item ;
item = & g_Level . Items [ itemNum ] ;
if ( item - > status = = ITEM_ACTIVE )
{
2020-08-24 18:01:12 -05:00
if ( ! TestBoundsCollide ( item , lara , coll - > radius ) )
return ;
if ( ! TestCollision ( item , lara ) )
return ;
if ( lara - > gravityStatus )
{
if ( coll - > enableBaddiePush )
ItemPushLara ( item , lara , coll , coll - > enableSpaz , 1 ) ;
lara - > hitPoints - = 100 ;
x = lara - > pos . xPos - item - > pos . xPos ;
y = ( lara - > pos . yPos - 350 ) - ( item - > pos . yPos - 512 ) ;
z = lara - > pos . zPos - item - > pos . zPos ;
d = ( short ) sqrt ( SQUARE ( x ) + SQUARE ( y ) + SQUARE ( z ) ) ;
if ( d < 512 )
d = 512 ;
x = item - > pos . xPos + ( ( x * 512 ) / d ) ;
y = item - > pos . yPos - 512 + ( ( y * 512 ) / d ) ;
z = item - > pos . zPos + ( ( z * 512 ) / d ) ;
DoBloodSplat ( x , y , z , item - > speed , item - > pos . yRot , item - > roomNumber ) ;
}
else
2020-08-24 13:23:21 -05:00
{
2020-08-24 18:01:12 -05:00
lara - > hitStatus = 1 ;
if ( lara - > hitPoints > 0 )
2020-08-24 13:23:21 -05:00
{
2020-08-24 18:01:12 -05:00
lara - > hitPoints = - 1 ; //?
lara - > pos . yRot = item - > pos . yRot ;
lara - > pos . zPos = 0 ;
lara - > pos . zRot = 0 ;
lara - > animNumber = LA_BOULDER_DEATH ;
lara - > frameNumber = g_Level . Anims [ lara - > animNumber ] . frameBase ;
lara - > currentAnimState = LS_BOULDER_DEATH ;
lara - > goalAnimState = LS_BOULDER_DEATH ;
Camera . flags = CF_FOLLOW_CENTER ;
Camera . targetAngle = ANGLE ( 170 ) ;
Camera . targetElevation = - ANGLE ( 25 ) ;
for ( int i = 0 ; i < 15 ; i + + )
2020-08-24 13:23:21 -05:00
{
2020-08-24 18:01:12 -05:00
x = lara - > pos . xPos + ( GetRandomControl ( ) - ANGLE ( 180 ) / 256 ) ;
y = lara - > pos . yPos - ( GetRandomControl ( ) / 64 ) ;
z = lara - > pos . zPos + ( GetRandomControl ( ) - ANGLE ( 180 ) / 256 ) ;
d = ( ( GetRandomControl ( ) - ANGLE ( 180 ) / 8 ) + item - > pos . yRot ) ;
DoBloodSplat ( x , y , z , ( short ) ( item - > speed * 2 ) , d , item - > roomNumber ) ;
2020-08-24 13:23:21 -05:00
}
}
}
}
else if ( item - > status ! = ITEM_INVISIBLE )
ObjectCollision ( itemNum , lara , coll ) ;
}
void ClassicRollingBallControl ( short itemNum )
{
short x , z , dist , oldx , oldz , roomNum ;
2020-08-24 18:01:12 -05:00
short y1 , y2 , ydist ;
2020-08-24 13:23:21 -05:00
ITEM_INFO * item ;
FLOOR_INFO * floor ;
GAME_VECTOR * old ;
ROOM_INFO * r ;
item = & g_Level . Items [ itemNum ] ;
if ( item - > status = = ITEM_ACTIVE )
{
2020-08-24 18:19:58 -05:00
if ( item - > goalAnimState = = 2 )
2020-08-24 13:23:21 -05:00
{
AnimateItem ( item ) ;
return ;
}
if ( item - > pos . yPos < item - > floor )
{
2020-08-24 18:19:58 -05:00
if ( ! item - > gravityStatus )
2020-08-24 13:23:21 -05:00
{
item - > gravityStatus = 1 ;
item - > fallspeed = - 10 ;
}
}
else if ( item - > currentAnimState = = 0 )
item - > goalAnimState = 1 ;
oldx = item - > pos . xPos ;
oldz = item - > pos . zPos ;
AnimateItem ( item ) ;
roomNum = item - > roomNumber ;
floor = GetFloor ( item - > pos . xPos , item - > pos . yPos , item - > pos . zPos , & roomNum ) ;
if ( item - > roomNumber ! = roomNum )
ItemNewRoom ( itemNum , item - > roomNumber ) ;
item - > floor = GetFloorHeight ( floor , item - > pos . xPos , item - > pos . yPos , item - > pos . zPos ) ;
TestTriggers ( TriggerIndex , TRUE , NULL ) ;
if ( item - > pos . yPos > = ( int ) floor - 256 )
{
item - > gravityStatus = false ;
item - > fallspeed = 0 ;
item - > pos . yPos = item - > floor ;
2020-08-24 18:01:12 -05:00
SoundEffect ( SFX_TR3_ROLLING_BALL , & item - > pos , 0 ) ;
2020-08-24 13:23:21 -05:00
dist = sqrt ( ( SQUARE ( Camera . mikePos . x - item - > pos . xPos ) ) + ( SQUARE ( Camera . mikePos . z - item - > pos . zPos ) ) ) ;
if ( dist < 10240 )
Camera . bounce = - 40 * ( 10240 - dist ) / 10240 ;
}
2020-08-24 18:01:12 -05:00
// dist = (item->objectNumber == ID_CLASSIC_ROLLING_BALL) ? 384 : 1024;//huh?
if ( item - > objectNumber = = ID_CLASSIC_ROLLING_BALL )
{
dist = 320 ;
ydist = 832 ;
}
else if ( item - > objectNumber = = ID_BIG_ROLLING_BALL )
{
dist = 1088 ;
ydist = 2112 ;
}
else
{
dist = 1024 ;
ydist = 1024 ;
}
2020-10-05 22:24:57 -03:00
x = item - > pos . xPos + dist * phd_sin ( item - > pos . yRot ) ;
z = item - > pos . zPos + dist * phd_cos ( item - > pos . yRot ) ;
2020-08-24 18:01:12 -05:00
2020-08-24 13:23:21 -05:00
floor = GetFloor ( x , item - > pos . yPos , z , & roomNum ) ;
2020-08-24 18:01:12 -05:00
y1 = GetFloorHeight ( floor , x , item - > pos . yPos , z ) ;
roomNum = item - > roomNumber ;
floor = GetFloor ( x , item - > pos . yPos - ydist , z , & roomNum ) ;
y2 = GetCeiling ( floor , x , item - > pos . yPos - ydist , z ) ;
2020-08-24 18:39:50 -05:00
if ( y1 < item - > pos . yPos | | y2 > ( item - > pos . yPos - ydist ) ) //there's something wrong here, this if statement returns true, executing this block, deactivating the boulders.
2020-08-24 13:23:21 -05:00
{
/*stupid sound crap hardcoded to object # idk*/
item - > status = ITEM_DEACTIVATED ;
item - > pos . yPos = item - > floor ;
item - > pos . xPos = oldx ;
item - > pos . zPos = oldz ;
item - > speed = 0 ;
item - > fallspeed = 0 ;
item - > touchBits = 0 ;
}
}
else if ( item - > status = = ITEM_DEACTIVATED )
{
if ( ! TriggerActive ( item ) )
{
item - > status = ITEM_NOT_ACTIVE ;
old = ( GAME_VECTOR * ) item - > data ;
item - > pos . xPos = old - > x ;
item - > pos . yPos = old - > y ;
item - > pos . zPos = old - > z ;
if ( item - > roomNumber ! = old - > roomNumber )
{
RemoveDrawnItem ( itemNum ) ;
r = & g_Level . Rooms [ old - > roomNumber ] ;
item - > nextItem = r - > itemNumber ;
r - > itemNumber = itemNum ;
item - > roomNumber = old - > roomNumber ;
}
item - > currentAnimState = 0 ;
item - > goalAnimState = 0 ;
item - > animNumber = Objects [ item - > objectNumber ] . animIndex ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > currentAnimState = g_Level . Anims [ item - > animNumber ] . currentAnimState ;
item - > goalAnimState = g_Level . Anims [ item - > animNumber ] . currentAnimState ;
item - > requiredAnimState = 0 ;
RemoveActiveItem ( itemNum ) ;
}
}
}
void InitialiseClassicRollingBall ( short itemNum )
{
ITEM_INFO * item ;
GAME_VECTOR * old ;
item = & g_Level . Items [ itemNum ] ;
old = ( GAME_VECTOR * ) malloc ( sizeof ( GAME_VECTOR ) ) ;
item - > data = ( GAME_VECTOR * ) malloc ( sizeof ( GAME_VECTOR ) ) ;
old - > x = item - > pos . xPos ;
old - > y = item - > pos . yPos ;
old - > z = item - > pos . zPos ;
old - > roomNumber = item - > roomNumber ;
}