2021-09-15 17:20:42 +03:00
# include "framework.h"
# include "los.h"
2021-09-16 05:06:03 +03:00
# include "animation.h"
2021-09-15 17:20:42 +03:00
# include "Sound/sound.h"
# include "objects.h"
# include "switch.h"
# include "lara_fire.h"
# include "input.h"
# include "effects/tomb4fx.h"
# include "effects/debris.h"
# include "Lara/lara_one_gun.h"
2021-09-24 07:53:42 +02:00
# include "item.h"
2021-09-25 11:27:47 +02:00
2021-09-15 17:20:42 +03:00
int NumberLosRooms ;
short LosRooms [ 20 ] ;
int ClosestItem ;
int ClosestDist ;
PHD_VECTOR ClosestCoord ;
int ClipTarget ( GAME_VECTOR * start , GAME_VECTOR * target )
{
short room ;
int x , y , z , wx , wy , wz ;
room = target - > roomNumber ;
if ( target - > y > GetFloorHeight ( GetFloor ( target - > x , target - > y , target - > z , & room ) , target - > x , target - > y , target - > z ) )
{
x = ( 7 * ( target - > x - start - > x ) > > 3 ) + start - > x ;
y = ( 7 * ( target - > y - start - > y ) > > 3 ) + start - > y ;
z = ( 7 * ( target - > z - start - > z ) > > 3 ) + start - > z ;
for ( int i = 3 ; i > 0 ; - - i )
{
wx = ( ( target - > x - x ) * i > > 2 ) + x ;
wy = ( ( target - > y - y ) * i > > 2 ) + y ;
wz = ( ( target - > z - z ) * i > > 2 ) + z ;
if ( wy < GetFloorHeight ( GetFloor ( wx , wy , wz , & room ) , wx , wy , wz ) )
break ;
}
target - > x = wx ;
target - > y = wy ;
target - > z = wz ;
target - > roomNumber = room ;
return 0 ;
}
room = target - > roomNumber ;
if ( target - > y < GetCeiling ( GetFloor ( target - > x , target - > y , target - > z , & room ) , target - > x , target - > y , target - > z ) )
{
x = ( 7 * ( target - > x - start - > x ) > > 3 ) + start - > x ;
y = ( 7 * ( target - > y - start - > y ) > > 3 ) + start - > y ;
z = ( 7 * ( target - > z - start - > z ) > > 3 ) + start - > z ;
for ( int i = 3 ; i > 0 ; - - i )
{
wx = ( ( target - > x - x ) * i > > 2 ) + x ;
wy = ( ( target - > y - y ) * i > > 2 ) + y ;
wz = ( ( target - > z - z ) * i > > 2 ) + z ;
if ( wy > GetCeiling ( GetFloor ( wx , wy , wz , & room ) , wx , wy , wz ) )
break ;
}
target - > x = wx ;
target - > y = wy ;
target - > z = wz ;
target - > roomNumber = room ;
return 0 ;
}
return 1 ;
}
int GetTargetOnLOS ( GAME_VECTOR * src , GAME_VECTOR * dest , int DrawTarget , int firing )
{
GAME_VECTOR target ;
int result , hit , itemNumber , count ;
MESH_INFO * mesh ;
PHD_VECTOR vector ;
ITEM_INFO * item ;
short angle , triggerItems [ 8 ] ;
VECTOR dir ;
Vector3 direction = Vector3 ( dest - > x , dest - > y , dest - > z ) - Vector3 ( src - > x , src - > y , src - > z ) ;
direction . Normalize ( ) ;
target . x = dest - > x ;
target . y = dest - > y ;
target . z = dest - > z ;
result = LOS ( src , & target ) ;
GetFloor ( target . x , target . y , target . z , & target . roomNumber ) ;
if ( firing & & LaserSight )
{
Lara . hasFired = true ;
Lara . fired = true ;
if ( Lara . gunType = = WEAPON_REVOLVER )
{
SoundEffect ( SFX_TR4_DESSERT_EAGLE_FIRE , NULL , 0 ) ;
}
}
hit = 0 ;
itemNumber = ObjectOnLOS2 ( src , dest , & vector , & mesh ) ;
if ( itemNumber ! = NO_LOS_ITEM )
{
target . x = vector . x - ( vector . x - src - > x > > 5 ) ;
target . y = vector . y - ( vector . y - src - > y > > 5 ) ;
target . z = vector . z - ( vector . z - src - > z > > 5 ) ;
GetFloor ( target . x , target . y , target . z , & target . roomNumber ) ;
// TODO: for covering scientist
// if ((itemNumber >= 0) && (BaddieSlots[itemNumber].itemNum != NO_ITEM)) // BUGFIX: ensure target has AI. No more pistol desync and camera wobble when shooting non-AI movable objects.
// Lara.target = &g_Level.Items[itemNumber];
// this is crashing and it's not really doing anything..
if ( firing )
{
if ( Lara . gunType ! = WEAPON_CROSSBOW )
{
if ( itemNumber < 0 )
{
if ( StaticObjects [ mesh - > staticNumber ] . shatterType ! = SHT_NONE )
{
ShatterImpactData . impactDirection = direction ;
ShatterImpactData . impactLocation = Vector3 ( mesh - > pos . xPos , mesh - > pos . yPos , mesh - > pos . zPos ) ;
ShatterObject ( NULL , mesh , 128 , target . roomNumber , 0 ) ;
SmashedMeshRoom [ SmashedMeshCount ] = target . roomNumber ;
SmashedMesh [ SmashedMeshCount ] = mesh ;
+ + SmashedMeshCount ;
mesh - > flags & = ~ StaticMeshFlags : : SM_VISIBLE ;
SoundEffect ( GetShatterSound ( mesh - > staticNumber ) , ( PHD_3DPOS * ) mesh , 0 ) ;
}
TriggerRicochetSpark ( & target , LaraItem - > pos . yRot , 3 , 0 ) ;
TriggerRicochetSpark ( & target , LaraItem - > pos . yRot , 3 , 0 ) ;
}
else
{
item = & g_Level . Items [ itemNumber ] ;
if ( item - > objectNumber < ID_SHOOT_SWITCH1 | | item - > objectNumber > ID_SHOOT_SWITCH4 )
{
if ( ( Objects [ item - > objectNumber ] . explodableMeshbits & ShatterItem . bit )
& & LaserSight )
{
//if (!Objects[item->objectNumber].intelligent)
//{
item - > meshBits & = ~ ShatterItem . bit ;
ShatterImpactData . impactDirection = direction ;
ShatterImpactData . impactLocation = Vector3 ( ShatterItem . sphere . x , ShatterItem . sphere . y , ShatterItem . sphere . z ) ;
ShatterObject ( & ShatterItem , 0 , 128 , target . roomNumber , 0 ) ;
TriggerRicochetSpark ( & target , LaraItem - > pos . yRot , 3 , 0 ) ;
/*}
else
{
if ( item - > objectNumber ! = ID_GUARD_LASER )
{
item - > hitPoints - = 30 ;
if ( item - > hitPoints < 0 )
item - > hitPoints = 0 ;
HitTarget ( item , & target , Weapons [ Lara . gunType ] . damage , 0 ) ;
}
else
{
angle = phd_atan ( LaraItem - > pos . zPos - item - > pos . zPos , LaraItem - > pos . xPos - item - > pos . xPos ) - item - > pos . yRot ;
if ( angle > - ANGLE ( 90 ) & & angle < ANGLE ( 90 ) )
{
item - > hitPoints = 0 ;
HitTarget ( item , & target , Weapons [ Lara . gunType ] . damage , 0 ) ;
}
}
} */
}
else
{
if ( DrawTarget & & ( Lara . gunType = = WEAPON_REVOLVER | | Lara . gunType = = WEAPON_HK ) )
{
if ( Objects [ item - > objectNumber ] . intelligent )
{
HitTarget ( item , & target , Weapons [ Lara . gunType ] . damage , 0 ) ;
}
else
{
// TR5
if ( Objects [ item - > objectNumber ] . hitEffect = = HIT_RICOCHET )
TriggerRicochetSpark ( & target , LaraItem - > pos . yRot , 3 , 0 ) ;
}
}
else
{
if ( item - > objectNumber > = ID_SMASH_OBJECT1 & & item - > objectNumber < = ID_SMASH_OBJECT8 )
{
SmashObject ( itemNumber ) ;
}
else
{
if ( Objects [ item - > objectNumber ] . hitEffect = = HIT_BLOOD )
{
DoBloodSplat ( target . x , target . y , target . z , ( GetRandomControl ( ) & 3 ) + 3 , item - > pos . yRot , item - > roomNumber ) ;
}
else if ( Objects [ item - > objectNumber ] . hitEffect = = HIT_SMOKE )
{
TriggerRicochetSpark ( & target , LaraItem - > pos . yRot , 3 , - 5 ) ;
}
else if ( Objects [ item - > objectNumber ] . hitEffect = = HIT_RICOCHET )
{
TriggerRicochetSpark ( & target , LaraItem - > pos . yRot , 3 , 0 ) ;
}
item - > hitStatus = true ;
if ( ! Objects [ item - > objectNumber ] . undead )
{
item - > hitPoints - = Weapons [ Lara . gunType ] . damage ;
}
}
}
}
}
else
{
if ( ShatterItem . bit = = 1 < < Objects [ item - > objectNumber ] . nmeshes - 1 )
{
if ( ! ( item - > flags & 0x40 ) )
{
if ( item - > objectNumber = = ID_SHOOT_SWITCH1 )
ExplodeItemNode ( item , Objects [ item - > objectNumber ] . nmeshes - 1 , 0 , 64 ) ;
if ( item - > triggerFlags = = 444 & & item - > objectNumber = = ID_SHOOT_SWITCH2 )
{
// TR5 ID_SWITCH_TYPE_8/ID_SHOOT_SWITCH2
ProcessExplodingSwitchType8 ( item ) ;
}
else
{
/*if (item->objectNumber == ID_SHOOT_SWITCH3)
{
// TR4 ID_SWITCH_TYPE7
ExplodeItemNode ( item , Objects [ item - > objectNumber ] . nmeshes - 1 , 0 , 64 ) ;
} */
if ( item - > flags & IFLAG_ACTIVATION_MASK & & ( item - > flags & IFLAG_ACTIVATION_MASK ) ! = IFLAG_ACTIVATION_MASK )
{
TestTriggers ( item - > pos . xPos , item - > pos . yPos - 256 , item - > pos . zPos , item - > roomNumber , true , item - > flags & IFLAG_ACTIVATION_MASK ) ;
}
else
{
for ( count = GetSwitchTrigger ( item , triggerItems , 1 ) ; count > 0 ; - - count )
{
AddActiveItem ( triggerItems [ count - 1 ] ) ;
g_Level . Items [ triggerItems [ count - 1 ] ] . status = ITEM_ACTIVE ;
g_Level . Items [ triggerItems [ count - 1 ] ] . flags | = IFLAG_ACTIVATION_MASK ;
}
}
}
}
if ( item - > status ! = ITEM_DEACTIVATED )
{
AddActiveItem ( itemNumber ) ;
item - > status = ITEM_ACTIVE ;
item - > flags | = IFLAG_ACTIVATION_MASK | 0x40 ;
}
}
TriggerRicochetSpark ( & target , LaraItem - > pos . yRot , 3 , 0 ) ;
}
}
}
else
{
if ( LaserSight & & firing )
{
FireCrossBowFromLaserSight ( src , & target ) ;
}
}
}
hit = 1 ;
}
else
{
if ( Lara . gunType = = WEAPON_CROSSBOW )
{
if ( firing & & LaserSight )
FireCrossBowFromLaserSight ( src , & target ) ;
}
else
{
target . x - = target . x - src - > x > > 5 ;
target . y - = target . y - src - > y > > 5 ;
target . z - = target . z - src - > z > > 5 ;
if ( firing & & ! result )
TriggerRicochetSpark ( & target , LaraItem - > pos . yRot , 8 , 0 ) ;
}
}
if ( DrawTarget & & ( hit | | ! result ) )
{
TriggerDynamicLight ( target . x , target . y , target . z , 64 , 255 , 0 , 0 ) ;
LaserSightActive = 1 ;
LaserSightX = target . x ;
LaserSightY = target . y ;
LaserSightZ = target . z ;
}
return hit ;
}
int ObjectOnLOS2 ( GAME_VECTOR * start , GAME_VECTOR * end , PHD_VECTOR * vec , MESH_INFO * * mesh )
{
int r , m ;
ROOM_INFO * room ;
short linknum ;
ITEM_INFO * item ;
PHD_3DPOS pos ;
MESH_INFO * meshp ;
BOUNDING_BOX * box ;
ClosestItem = NO_LOS_ITEM ;
ClosestDist = SQUARE ( end - > x - start - > x ) + SQUARE ( end - > y - start - > y ) + SQUARE ( end - > z - start - > z ) ;
for ( r = 0 ; r < NumberLosRooms ; + + r )
{
room = & g_Level . Rooms [ LosRooms [ r ] ] ;
for ( m = 0 ; m < room - > mesh . size ( ) ; m + + )
{
meshp = & room - > mesh [ m ] ;
if ( meshp - > flags & StaticMeshFlags : : SM_VISIBLE )
{
pos . xPos = meshp - > pos . xPos ;
pos . yPos = meshp - > pos . yPos ;
pos . zPos = meshp - > pos . zPos ;
pos . yRot = meshp - > pos . yRot ;
if ( DoRayBox ( start , end , & StaticObjects [ meshp - > staticNumber ] . collisionBox , & pos , vec , - 1 - meshp - > staticNumber ) )
{
* mesh = meshp ;
end - > roomNumber = LosRooms [ r ] ;
}
}
}
for ( linknum = room - > itemNumber ; linknum ! = NO_ITEM ; linknum = g_Level . Items [ linknum ] . nextItem )
{
item = & g_Level . Items [ linknum ] ;
if ( item - > status ! = ITEM_DEACTIVATED & & item - > status ! = ITEM_INVISIBLE
& & ( item - > objectNumber ! = ID_LARA
& & Objects [ item - > objectNumber ] . collision ! = NULL
| | item - > objectNumber = = ID_LARA
& & GetLaraOnLOS ) )
{
box = GetBoundsAccurate ( item ) ;
pos . xPos = item - > pos . xPos ;
pos . yPos = item - > pos . yPos ;
pos . zPos = item - > pos . zPos ;
pos . yRot = item - > pos . yRot ;
if ( DoRayBox ( start , end , box , & pos , vec , linknum ) )
{
end - > roomNumber = LosRooms [ r ] ;
}
}
}
}
vec - > x = ClosestCoord . x ;
vec - > y = ClosestCoord . y ;
vec - > z = ClosestCoord . z ;
return ClosestItem ;
}
int DoRayBox ( GAME_VECTOR * start , GAME_VECTOR * end , BOUNDING_BOX * box , PHD_3DPOS * itemOrStaticPos , PHD_VECTOR * hitPos , short closesItemNumber )
{
// Ray
FXMVECTOR rayStart = { start - > x , start - > y , start - > z } ;
FXMVECTOR rayEnd = { end - > x , end - > y , end - > z } ;
FXMVECTOR rayDir = { end - > x - start - > x , end - > y - start - > y , end - > z - start - > z } ;
XMVECTOR rayDirNormalized = XMVector3Normalize ( rayDir ) ;
// Create the bounding box for raw collision detection
auto obox = TO_DX_BBOX ( * itemOrStaticPos , box ) ;
// Get the collision with the bounding box
float distance ;
bool collided = obox . Intersects ( rayStart , rayDirNormalized , distance ) ;
// If no collision happened, then don't test spheres
if ( ! collided )
return 0 ;
// Get the raw collision point
Vector3 collidedPoint = rayStart + distance * rayDirNormalized ;
hitPos - > x = collidedPoint . x - itemOrStaticPos - > xPos ;
hitPos - > y = collidedPoint . y - itemOrStaticPos - > yPos ;
hitPos - > z = collidedPoint . z - itemOrStaticPos - > zPos ;
// Now in the case of items we need to test single spheres
MESH * meshPtr = NULL ;
int bit = 0 ;
int sp = - 2 ;
float minDistance = std : : numeric_limits < float > : : max ( ) ;
int action = TrInput & IN_ACTION ;
if ( closesItemNumber < 0 )
{
// Static meshes don't require further tests
sp = - 1 ;
minDistance = distance ;
}
else
{
// For items instead we need to test spheres
ITEM_INFO * item = & g_Level . Items [ closesItemNumber ] ;
OBJECT_INFO * obj = & Objects [ item - > objectNumber ] ;
// Get the ransformed sphere of meshes
GetSpheres ( item , CreatureSpheres , SPHERES_SPACE_WORLD , Matrix : : Identity ) ;
SPHERE spheres [ 34 ] ;
memcpy ( spheres , CreatureSpheres , sizeof ( SPHERE ) * 34 ) ;
if ( obj - > nmeshes < = 0 )
return 0 ;
meshPtr = & g_Level . Meshes [ obj - > meshIndex ] ;
for ( int i = 0 ; i < obj - > nmeshes ; i + + )
{
// If mesh is visibile...
if ( item - > meshBits & ( 1 < < i ) )
{
SPHERE * sphere = & CreatureSpheres [ i ] ;
// TODO: this approach is the correct one but, again, Core's math is a mistery and this test was meant
// to fail delberately in some way. I've so added again Core's legacy test for allowing the current game logic
// but after more testing we should trash it in the future and restore the new way.
#if 0
// Create the bounding sphere and test it against the ray
BoundingSphere sph = BoundingSphere ( Vector3 ( sphere - > x , sphere - > y , sphere - > z ) , sphere - > r ) ;
float newDist ;
if ( sph . Intersects ( rayStart , rayDirNormalized , newDist ) )
{
// HACK: Core seems to take in account for distance not the real hit point but the centre of the sphere.
// This can work well for example for GUARDIAN because the head sphere is so big that would always be hit
// and eyes would not be destroyed.
newDist = sqrt ( SQUARE ( sphere - > x - start - > x ) + SQUARE ( sphere - > y - start - > y ) + SQUARE ( sphere - > z - start - > z ) ) ;
// Test for min distance
if ( newDist < minDistance )
{
minDistance = newDist ;
meshPtr = & g_Level . Meshes [ obj - > meshIndex + i ] ;
bit = 1 < < i ;
sp = i ;
}
}
# endif
PHD_VECTOR p [ 4 ] ;
p [ 1 ] . x = start - > x ;
p [ 1 ] . y = start - > y ;
p [ 1 ] . z = start - > z ;
p [ 2 ] . x = end - > x ;
p [ 2 ] . y = end - > y ;
p [ 2 ] . z = end - > z ;
p [ 3 ] . x = sphere - > x ;
p [ 3 ] . y = sphere - > y ;
p [ 3 ] . z = sphere - > z ;
int r0 = ( p [ 3 ] . x - p [ 1 ] . x ) * ( p [ 2 ] . x - p [ 1 ] . x ) +
( p [ 3 ] . y - p [ 1 ] . y ) * ( p [ 2 ] . y - p [ 1 ] . y ) +
( p [ 3 ] . z - p [ 1 ] . z ) * ( p [ 2 ] . z - p [ 1 ] . z ) ;
int r1 = SQUARE ( p [ 2 ] . x - p [ 1 ] . x ) +
SQUARE ( p [ 2 ] . y - p [ 1 ] . y ) +
SQUARE ( p [ 2 ] . z - p [ 1 ] . z ) ;
if ( ( ( r0 < 0 & & r1 < 0 )
| | ( r1 > 0 & & r0 > 0 ) )
& & ( abs ( r0 ) < = abs ( r1 ) ) )
{
r1 > > = 16 ;
if ( r1 )
r0 / = r1 ;
else
r0 = 0 ;
p [ 0 ] . x = p [ 1 ] . x + ( ( r0 * ( p [ 2 ] . x - p [ 1 ] . x ) ) > > 16 ) ;
p [ 0 ] . y = p [ 1 ] . y + ( ( r0 * ( p [ 2 ] . y - p [ 1 ] . y ) ) > > 16 ) ;
p [ 0 ] . z = p [ 1 ] . z + ( ( r0 * ( p [ 2 ] . z - p [ 1 ] . z ) ) > > 16 ) ;
int dx = p [ 0 ] . x - p [ 3 ] . x ;
int dy = p [ 0 ] . y - p [ 3 ] . y ;
int dz = p [ 0 ] . z - p [ 3 ] . z ;
int distance = dx + dy + dz ;
if ( distance < SQUARE ( sphere - > r ) )
{
dx = SQUARE ( sphere - > x - start - > x ) ;
dy = SQUARE ( sphere - > y - start - > y ) ;
dz = SQUARE ( sphere - > z - start - > z ) ;
distance = dx + dy + dz ;
if ( distance < minDistance )
{
minDistance = distance ;
meshPtr = & g_Level . Meshes [ obj - > meshIndex + i ] ;
bit = 1 < < i ;
sp = i ;
}
}
}
}
}
if ( sp < - 1 )
return 0 ;
}
if ( distance > = ClosestDist )
return 0 ;
// Setup test result
ClosestCoord . x = hitPos - > x + itemOrStaticPos - > xPos ;
ClosestCoord . y = hitPos - > y + itemOrStaticPos - > yPos ;
ClosestCoord . z = hitPos - > z + itemOrStaticPos - > zPos ;
ClosestDist = distance ;
ClosestItem = closesItemNumber ;
// If collided object is an item, then setup the shatter item data struct
if ( sp > = 0 )
{
ITEM_INFO * item = & g_Level . Items [ closesItemNumber ] ;
GetSpheres ( item , CreatureSpheres , SPHERES_SPACE_WORLD | SPHERES_SPACE_BONE_ORIGIN , Matrix : : Identity ) ;
ShatterItem . yRot = item - > pos . yRot ;
ShatterItem . meshp = meshPtr ;
ShatterItem . sphere . x = CreatureSpheres [ sp ] . x ;
ShatterItem . sphere . y = CreatureSpheres [ sp ] . y ;
ShatterItem . sphere . z = CreatureSpheres [ sp ] . z ;
ShatterItem . bit = bit ;
ShatterItem . flags = 0 ;
}
return 1 ;
}
int LOS ( GAME_VECTOR * start , GAME_VECTOR * end )
{
int result1 , result2 ;
end - > roomNumber = start - > roomNumber ;
if ( abs ( end - > z - start - > z ) > abs ( end - > x - start - > x ) )
{
result1 = xLOS ( start , end ) ;
result2 = zLOS ( start , end ) ;
}
else
{
result1 = zLOS ( start , end ) ;
result2 = xLOS ( start , end ) ;
}
if ( result2 )
{
GetFloor ( end - > x , end - > y , end - > z , & end - > roomNumber ) ;
if ( ClipTarget ( start , end ) & & result1 = = 1 & & result2 = = 1 )
{
return 1 ;
}
}
return 0 ;
}
int xLOS ( GAME_VECTOR * start , GAME_VECTOR * end )
{
int dx , dy , dz , x , y , z , flag ;
short room , room2 ;
FLOOR_INFO * floor ;
dx = end - > x - start - > x ;
if ( ! dx )
return 1 ;
dy = ( end - > y - start - > y < < 10 ) / dx ;
dz = ( end - > z - start - > z < < 10 ) / dx ;
NumberLosRooms = 1 ;
LosRooms [ 0 ] = start - > roomNumber ;
room = start - > roomNumber ;
room2 = start - > roomNumber ;
flag = 1 ;
if ( dx < 0 )
{
x = start - > x & 0xFFFFFC00 ;
y = ( ( x - start - > x ) * dy > > 10 ) + start - > y ;
z = ( ( x - start - > x ) * dz > > 10 ) + start - > z ;
while ( x > end - > x )
{
floor = GetFloor ( x , y , z , & room ) ;
if ( room ! = room2 )
{
room2 = room ;
LosRooms [ NumberLosRooms ] = room ;
+ + NumberLosRooms ;
}
if ( y > GetFloorHeight ( floor , x , y , z ) | | y < GetCeiling ( floor , x , y , z ) )
{
flag = - 1 ;
break ;
}
floor = GetFloor ( x - 1 , y , z , & room ) ;
if ( room ! = room2 )
{
room2 = room ;
LosRooms [ NumberLosRooms ] = room ;
+ + NumberLosRooms ;
}
if ( y > GetFloorHeight ( floor , x - 1 , y , z ) | | y < GetCeiling ( floor , x - 1 , y , z ) )
{
flag = 0 ;
break ;
}
x - = 1024 ;
y - = dy ;
z - = dz ;
}
if ( flag ! = 1 )
{
end - > x = x ;
end - > y = y ;
end - > z = z ;
}
end - > roomNumber = flag ? room : room2 ;
}
else
{
x = start - > x | 0x3FF ;
y = ( ( x - start - > x ) * dy > > 10 ) + start - > y ;
z = ( ( x - start - > x ) * dz > > 10 ) + start - > z ;
while ( x < end - > x )
{
floor = GetFloor ( x , y , z , & room ) ;
if ( room ! = room2 )
{
room2 = room ;
LosRooms [ NumberLosRooms ] = room ;
+ + NumberLosRooms ;
}
if ( y > GetFloorHeight ( floor , x , y , z ) | | y < GetCeiling ( floor , x , y , z ) )
{
flag = - 1 ;
break ;
}
floor = GetFloor ( x + 1 , y , z , & room ) ;
if ( room ! = room2 )
{
room2 = room ;
LosRooms [ NumberLosRooms ] = room ;
+ + NumberLosRooms ;
}
if ( y > GetFloorHeight ( floor , x + 1 , y , z ) | | y < GetCeiling ( floor , x + 1 , y , z ) )
{
flag = 0 ;
break ;
}
x + = 1024 ;
y + = dy ;
z + = dz ;
}
if ( flag ! = 1 )
{
end - > x = x ;
end - > y = y ;
end - > z = z ;
}
end - > roomNumber = flag ? room : room2 ;
}
return flag ;
}
int zLOS ( GAME_VECTOR * start , GAME_VECTOR * end )
{
int dx , dy , dz , x , y , z , flag ;
short room , room2 ;
FLOOR_INFO * floor ;
dz = end - > z - start - > z ;
if ( ! dz )
return 1 ;
dx = ( end - > x - start - > x < < 10 ) / dz ;
dy = ( end - > y - start - > y < < 10 ) / dz ;
NumberLosRooms = 1 ;
LosRooms [ 0 ] = start - > roomNumber ;
room = start - > roomNumber ;
room2 = start - > roomNumber ;
flag = 1 ;
if ( dz < 0 )
{
z = start - > z & 0xFFFFFC00 ;
x = ( ( z - start - > z ) * dx > > 10 ) + start - > x ;
y = ( ( z - start - > z ) * dy > > 10 ) + start - > y ;
while ( z > end - > z )
{
floor = GetFloor ( x , y , z , & room ) ;
if ( room ! = room2 )
{
room2 = room ;
LosRooms [ NumberLosRooms ] = room ;
+ + NumberLosRooms ;
}
if ( y > GetFloorHeight ( floor , x , y , z ) | | y < GetCeiling ( floor , x , y , z ) )
{
flag = - 1 ;
break ;
}
floor = GetFloor ( x , y , z - 1 , & room ) ;
if ( room ! = room2 )
{
room2 = room ;
LosRooms [ NumberLosRooms ] = room ;
+ + NumberLosRooms ;
}
if ( y > GetFloorHeight ( floor , x , y , z - 1 ) | | y < GetCeiling ( floor , x , y , z - 1 ) )
{
flag = 0 ;
break ;
}
z - = 1024 ;
x - = dx ;
y - = dy ;
}
if ( flag ! = 1 )
{
end - > x = x ;
end - > y = y ;
end - > z = z ;
}
end - > roomNumber = flag ? room : room2 ;
}
else
{
z = start - > z | 0x3FF ;
x = ( ( z - start - > z ) * dx > > 10 ) + start - > x ;
y = ( ( z - start - > z ) * dy > > 10 ) + start - > y ;
while ( z < end - > z )
{
floor = GetFloor ( x , y , z , & room ) ;
if ( room ! = room2 )
{
room2 = room ;
LosRooms [ NumberLosRooms ] = room ;
+ + NumberLosRooms ;
}
if ( y > GetFloorHeight ( floor , x , y , z ) | | y < GetCeiling ( floor , x , y , z ) )
{
flag = - 1 ;
break ;
}
floor = GetFloor ( x , y , z + 1 , & room ) ;
if ( room ! = room2 )
{
room2 = room ;
LosRooms [ NumberLosRooms ] = room ;
+ + NumberLosRooms ;
}
if ( y > GetFloorHeight ( floor , x , y , z + 1 ) | | y < GetCeiling ( floor , x , y , z + 1 ) )
{
flag = 0 ;
break ;
}
z + = 1024 ;
x + = dx ;
y + = dy ;
}
if ( flag ! = 1 )
{
end - > x = x ;
end - > y = y ;
end - > z = z ;
}
end - > roomNumber = flag ? room : room2 ;
}
return flag ;
}