985 lines
16 KiB
C++
985 lines
16 KiB
C++
#include "game.h"
|
|
#include "pap.h"
|
|
#include "walkable.h"
|
|
#include "memory.h"
|
|
#include "mav.h"
|
|
|
|
extern void highlight_rface(SLONG rface);
|
|
//
|
|
// code to do with walkable faces
|
|
//
|
|
|
|
//
|
|
// this whole module has been changed to treat walkable faces as 10% (more in terms of area) bigger for collision.
|
|
//
|
|
|
|
|
|
SLONG clock(const SLONG dx,const SLONG dz,const SLONG dx1,const SLONG dz1)
|
|
{
|
|
if((dx*dz1-dz*dx1)<=0)
|
|
return(0);
|
|
else
|
|
return(1);
|
|
}
|
|
|
|
SLONG point_in_quad(SLONG px,SLONG pz,SLONG x,SLONG y,SLONG z,SWORD face)
|
|
{
|
|
SLONG c0;
|
|
SWORD vx[4],vz[4];
|
|
SLONG mx=0,mz=0;
|
|
|
|
ASSERT(face>=0);
|
|
|
|
|
|
for(c0=0;c0<4;c0++)
|
|
{
|
|
vx[c0]=x+prim_points[prim_faces4[face].Points[c0]].X;
|
|
vz[c0]=z+prim_points[prim_faces4[face].Points[c0]].Z;
|
|
|
|
mx+=vx[c0];
|
|
mz+=vz[c0];
|
|
}
|
|
|
|
|
|
// mx=0;
|
|
mx>>=2;
|
|
// mz/=mx;
|
|
mz>>=2;
|
|
for(c0=0;c0<4;c0++)
|
|
{
|
|
vx[c0]=( ( (vx[c0]-mx)*268)>>8 )+mx;
|
|
vz[c0]=( ( (vz[c0]-mz)*268)>>8 )+mz;
|
|
}
|
|
|
|
|
|
if(clock(vx[1]-vx[0],vz[1]-vz[0],px-vx[0],pz-vz[0]))//x2-x1,z2-z1,px-x1,pz-z1))
|
|
{
|
|
if(clock(vx[3]-vx[1],vz[3]-vz[1],px-vx[1],pz-vz[1]))
|
|
{
|
|
if(clock(vx[2]-vx[3],vz[2]-vz[3],px-vx[3],pz-vz[3]))
|
|
{
|
|
if(clock(vx[0]-vx[2],vz[0]-vz[2],px-vx[2],pz-vz[2]))
|
|
{
|
|
return(1);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
//
|
|
// returns true if on face
|
|
// *height always trys to have the height
|
|
|
|
SLONG gh_vx[4],gh_vy[4],gh_vz[4];//out of stack space (on PSX) so words
|
|
SLONG get_height_on_face_quad64_at(SLONG rx, SLONG rz, SWORD face,SLONG *height)
|
|
{
|
|
// SLONG ux,uy,uz,vx,vy,vz,wx,wy,wz;
|
|
struct PrimFace4 *this_face4;
|
|
SLONG ax,ay,az,bx,by,bz;
|
|
|
|
SLONG top, bot;
|
|
SLONG alpha, beta;
|
|
SLONG x,y,z;
|
|
|
|
SLONG mx=0,my=0,mz=0;
|
|
UWORD c0;
|
|
SLONG on_face=1;
|
|
ASSERT(face>=0);
|
|
|
|
this_face4=&prim_faces4[face];
|
|
|
|
for(c0=0;c0<4;c0++)
|
|
{
|
|
gh_vx[c0] = prim_points[this_face4->Points[c0]].X;
|
|
gh_vy[c0] = prim_points[this_face4->Points[c0]].Y;
|
|
gh_vz[c0] = prim_points[this_face4->Points[c0]].Z;
|
|
|
|
mx+=gh_vx[c0];
|
|
// my+=gh_vy[c0];
|
|
mz+=gh_vz[c0];
|
|
|
|
}
|
|
|
|
if(gh_vy[0]==gh_vy[1] && gh_vy[1]==gh_vy[2] && gh_vy[2]==gh_vy[3])
|
|
{
|
|
*height=gh_vy[0];
|
|
return(1);
|
|
}
|
|
|
|
mx>>=2;
|
|
// my>>=2;
|
|
mz>>=2;
|
|
|
|
for(c0=0;c0<4;c0++)
|
|
{
|
|
gh_vx[c0]=( ( (gh_vx[c0]-mx)*268)>>8 )+mx;
|
|
// gh_vy[c0]=( ( (gh_vy[c0]-my)*268)>>8 )+my;
|
|
gh_vz[c0]=( ( (gh_vz[c0]-mz)*268)>>8 )+mz;
|
|
}
|
|
|
|
|
|
/*
|
|
ux= obj_x+prim_points[this_face4->Points[0]].X;
|
|
uy= obj_y+prim_points[this_face4->Points[0]].Y;
|
|
uz= obj_z+prim_points[this_face4->Points[0]].Z;
|
|
|
|
vx= obj_x+prim_points[this_face4->Points[1]].X;
|
|
vy= obj_y+prim_points[this_face4->Points[1]].Y;
|
|
vz= obj_z+prim_points[this_face4->Points[1]].Z;
|
|
|
|
wx= obj_x+prim_points[this_face4->Points[2]].X;
|
|
wy= obj_y+prim_points[this_face4->Points[2]].Y;
|
|
wz= obj_z+prim_points[this_face4->Points[2]].Z;
|
|
|
|
if(uy==vy && vy==wy)
|
|
return(uy);
|
|
*/
|
|
|
|
|
|
ax = (gh_vx[1] - gh_vx[0]) << 8;
|
|
ay = (gh_vy[1] - gh_vy[0]) << 8;
|
|
az = (gh_vz[1] - gh_vz[0]) << 8;
|
|
|
|
bx = (gh_vx[2] - gh_vx[0]) << 8;
|
|
by = (gh_vy[2] - gh_vy[0]) << 8;
|
|
bz = (gh_vz[2] - gh_vz[0]) << 8;
|
|
|
|
x = (rx<<8) - (gh_vx[0] << 8);
|
|
z = (rz<<8) - (gh_vz[0] << 8);
|
|
|
|
//printf("face =%d a=(%d,%d,%d) b =(%d,%d,%d) xz=(%d,%d)\n",face,ax,ay,az,bx,by,bz,x,z);
|
|
|
|
// Work out alpha and beta such that x = alpha*ax + beta*bx and y = alhpa*ay + beta*by
|
|
|
|
// First alpha...
|
|
|
|
top = MUL64(x, bz) - MUL64(z, bx);
|
|
bot = MUL64(bz, ax) - MUL64(bx, az);
|
|
|
|
if (bot == 0) {bot = 0x8000;}
|
|
|
|
alpha = DIV64(top, bot);
|
|
|
|
// Now beta...
|
|
|
|
top = MUL64(z, ax) - MUL64(x, az);
|
|
if(bot<3)
|
|
{
|
|
*height=gh_vy[0];
|
|
|
|
return(1);
|
|
}
|
|
beta = DIV64(top, bot);
|
|
|
|
|
|
if(alpha<0)
|
|
{
|
|
alpha=0;
|
|
on_face=0;
|
|
}
|
|
if(beta<0)
|
|
{
|
|
beta=0;
|
|
on_face=0;
|
|
}
|
|
if(alpha>0x10000)
|
|
{
|
|
alpha=0x10000;
|
|
on_face=0;
|
|
}
|
|
if(beta>0x10000)
|
|
{
|
|
beta=0x10000;
|
|
on_face=0;
|
|
}
|
|
|
|
/*
|
|
if (alpha < 0 || alpha > 0x10000 || beta < 0 || beta > 0x10000)
|
|
{
|
|
LogText(" get height on QUAD NOT %d alpha %x beta %x \n",face,alpha,beta);
|
|
return 1000000;
|
|
}
|
|
*/
|
|
// else
|
|
if (alpha+beta>0x10000)
|
|
{
|
|
// 0 1 3 2
|
|
//
|
|
// 2 1 0
|
|
// 3
|
|
//
|
|
// other triangular half of quad
|
|
//
|
|
|
|
ax = (gh_vx[2] - gh_vx[3]) << 8;
|
|
ay = (gh_vy[2] - gh_vy[3]) << 8;
|
|
az = (gh_vz[2] - gh_vz[3]) << 8;
|
|
|
|
bx = (gh_vx[1] - gh_vx[3]) << 8;
|
|
by = (gh_vy[1] - gh_vy[3]) << 8;
|
|
bz = (gh_vz[1] - gh_vz[3]) << 8;
|
|
|
|
x = (rx<<8) - (gh_vx[3] << 8);
|
|
z = (rz<<8) - (gh_vz[3] << 8);
|
|
|
|
//printf("face =%d a=(%d,%d,%d) b =(%d,%d,%d) xz=(%d,%d)\n",face,ax,ay,az,bx,by,bz,x,z);
|
|
|
|
// Work out alpha and beta such that x = alpha*ax + beta*bx and y = alhpa*ay + beta*by
|
|
|
|
// First alpha...
|
|
|
|
top = MUL64(x, bz) - MUL64(z, bx);
|
|
bot = MUL64(bz, ax) - MUL64(bx, az);
|
|
|
|
if (bot == 0) {bot = 0x8000;}
|
|
|
|
alpha = DIV64(top, bot);
|
|
|
|
// Now beta...
|
|
|
|
top = MUL64(z, ax) - MUL64(x, az);
|
|
if(bot<3)
|
|
{
|
|
*height=gh_vy[3];
|
|
return(on_face);
|
|
}
|
|
beta = DIV64(top, bot);
|
|
/*
|
|
if (alpha < 0 || alpha > 0x10000 || beta < 0 || beta > 0x10000)
|
|
{
|
|
|
|
}
|
|
else
|
|
*/
|
|
if(alpha<0)
|
|
{
|
|
alpha=0;
|
|
on_face=0;
|
|
}
|
|
if(beta<0)
|
|
{
|
|
beta=0;
|
|
on_face=0;
|
|
}
|
|
if(alpha>0x10000)
|
|
{
|
|
alpha=0x10000;
|
|
on_face=0;
|
|
}
|
|
if(beta>0x10000)
|
|
{
|
|
beta=0x10000;
|
|
on_face=0;
|
|
}
|
|
if (alpha+beta>0x10000)
|
|
{
|
|
// This is benign - happens very very occasionally - don't worry about it.
|
|
ASSERT(0);
|
|
*height=gh_vy[1];
|
|
return(0);
|
|
}
|
|
else
|
|
{
|
|
y = gh_vy[3] << 8;
|
|
y += MUL64(alpha, ay);
|
|
y += MUL64(beta, by);
|
|
*height= y >> 8;
|
|
return(on_face);
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
// LogText(" get height on face=%d alpha %x beta %x uy %d vy %d wy %d\n",y>>8,face,alpha,beta),uy,vy,wy;
|
|
y = gh_vy[0] << 8;
|
|
y += MUL64(alpha, ay);
|
|
y += MUL64(beta, by);
|
|
*height= y >> 8;
|
|
return(on_face);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// returns 0 or 1 (on face false/true) new_y is alt on face
|
|
//
|
|
/*
|
|
SLONG calc_height_on_face(SLONG x,SLONG z,SLONG face,SLONG *new_y)
|
|
{
|
|
|
|
if (face > 0)
|
|
{
|
|
return(get_height_on_face_quad64_at(x,z,face,new_y));
|
|
}
|
|
ASSERT(0);
|
|
// return(1000000);
|
|
// return(-100);
|
|
}
|
|
*/
|
|
|
|
|
|
SLONG is_thing_on_this_quad(SLONG x,SLONG z,SLONG face)
|
|
{
|
|
if(face<0)
|
|
{
|
|
struct RoofFace4 *rf;
|
|
// highlight_rface(-face);
|
|
|
|
if(IS_ROOF_HIDDEN_FACE(face))
|
|
{
|
|
if((x>>8)==ROOF_HIDDEN_X(face) && (z>>8)==ROOF_HIDDEN_Z(face))
|
|
return(1);
|
|
else
|
|
return(0);
|
|
|
|
}
|
|
rf=&roof_faces4[-face];
|
|
x>>=8;
|
|
z>>=8;
|
|
if(x==(rf->RX&127) && z==(rf->RZ&127))
|
|
return(1);
|
|
else
|
|
return(0);
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
if(point_in_quad(x,z,0,0,0,face))
|
|
{
|
|
return(1);
|
|
}
|
|
else
|
|
{
|
|
return(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
SLONG calc_height_on_rface(SLONG x, SLONG z,SWORD face,SLONG *ret_y)
|
|
{
|
|
SLONG h0;
|
|
SLONG h1;
|
|
SLONG h2;
|
|
SLONG h3;
|
|
|
|
SLONG xfrac;
|
|
SLONG zfrac;
|
|
|
|
SLONG answer;
|
|
|
|
struct RoofFace4 *rf;
|
|
|
|
ASSERT(face>0);
|
|
|
|
if(IS_ROOF_HIDDEN_FACE(-face))
|
|
{
|
|
if(ROOF_HIDDEN_X(-face)!=(x>>8) || ROOF_HIDDEN_Z(-face)!=(z>>8))
|
|
return(0);
|
|
|
|
if(PAP_hi[x>>8][z>>8].Flags&PAP_FLAG_ROOF_EXISTS)
|
|
{
|
|
*ret_y = MAVHEIGHT(x>>8,z>>8)<<6;
|
|
|
|
return(ROOF_HIDDEN_GET_FACE(x>>8,z>>8));
|
|
}
|
|
else
|
|
return(0);
|
|
|
|
}
|
|
|
|
// highlight_rface(face);
|
|
|
|
rf=&roof_faces4[face];
|
|
|
|
if(x>>8!=(rf->RX&127) ||z>>8!=(rf->RZ&127))
|
|
return(0);
|
|
|
|
|
|
h0 = rf->Y;
|
|
if(!(rf->RZ&128))
|
|
{
|
|
*ret_y=h0;
|
|
return(face);
|
|
}
|
|
|
|
h1 = h0+(rf->DY[2]<<ROOF_SHIFT);
|
|
h2 = h0+(rf->DY[0]<<ROOF_SHIFT);
|
|
h3 = h0+(rf->DY[1]<<ROOF_SHIFT);
|
|
|
|
{
|
|
if(rf->RX&1<<7)
|
|
{
|
|
xfrac = x & 0xff;
|
|
zfrac = z & 0xff;
|
|
|
|
if (xfrac + (256-zfrac) < 0x100)
|
|
{
|
|
answer = h1;
|
|
answer += (h3 - h1) * xfrac >> 8;
|
|
answer += (h0 - h1) * (256-zfrac) >> 8;
|
|
}
|
|
else
|
|
{
|
|
answer = h2;
|
|
answer += (h0 - h2) * (0x100 - xfrac) >> 8;
|
|
answer += (h3 - h2) * (zfrac) >> 8;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xfrac = x & 0xff;
|
|
zfrac = z & 0xff;
|
|
|
|
if (xfrac + zfrac < 0x100)
|
|
{
|
|
answer = h0;
|
|
answer += (h2 - h0) * xfrac >> 8;
|
|
answer += (h1 - h0) * zfrac >> 8;
|
|
}
|
|
else
|
|
{
|
|
answer = h3;
|
|
answer += (h1 - h3) * (0x100 - xfrac) >> 8;
|
|
answer += (h2 - h3) * (0x100 - zfrac) >> 8;
|
|
}
|
|
}
|
|
}
|
|
|
|
*ret_y=answer;
|
|
return(face);
|
|
}
|
|
|
|
|
|
//
|
|
// Finds a face to be stood on (checks height is not out of range)
|
|
//
|
|
|
|
SLONG find_face_for_this_pos(
|
|
SLONG x,
|
|
SLONG y,
|
|
SLONG z,
|
|
SLONG *ret_y,
|
|
SLONG ignore_building,
|
|
UBYTE ignore_height_flag)
|
|
{
|
|
UBYTE mx;
|
|
UBYTE mz;
|
|
SWORD dy;
|
|
SLONG facey;
|
|
SWORD index;
|
|
SWORD groundy;
|
|
SWORD best_face = NULL;
|
|
SWORD best_dy = 0x7fff;
|
|
SWORD best_facey = 0;
|
|
|
|
SWORD mx1 = x - 0x200 >> PAP_SHIFT_LO;
|
|
SWORD mz1 = z - 0x200 >> PAP_SHIFT_LO;
|
|
|
|
SWORD mx2 = x + 0x200 >> PAP_SHIFT_LO;
|
|
SWORD mz2 = z + 0x200 >> PAP_SHIFT_LO;
|
|
|
|
SATURATE(mx1, 0, PAP_SIZE_LO - 1);
|
|
SATURATE(mz1, 0, PAP_SIZE_LO - 1);
|
|
|
|
SATURATE(mx2, 0, PAP_SIZE_LO - 1);
|
|
SATURATE(mz2, 0, PAP_SIZE_LO - 1);
|
|
|
|
if(PAP_hi[x>>8][z>>8].Flags&PAP_FLAG_ROOF_EXISTS)
|
|
{
|
|
best_face=ROOF_HIDDEN_GET_FACE(x>>8,z>>8);
|
|
|
|
if(ignore_height_flag==FIND_ANYFACE)
|
|
{
|
|
*ret_y = MAVHEIGHT(x>>8,z>>8)<<6;
|
|
return(best_face);
|
|
}
|
|
best_facey=MAVHEIGHT(x>>8,z>>8)<<6;
|
|
best_dy = best_facey - y;
|
|
if(best_dy<30 && ignore_height_flag==FIND_FACE_NEAR_BELOW)
|
|
{
|
|
*ret_y = best_facey;
|
|
|
|
return best_face;
|
|
}
|
|
if (best_dy < 0xa0)
|
|
{
|
|
best_face = best_face;
|
|
best_dy = abs(best_dy);
|
|
}
|
|
}
|
|
|
|
for (mx = mx1; mx <= mx2; mx++)
|
|
for (mz = mz1; mz <= mz2; mz++)
|
|
{
|
|
index = PAP_2LO(mx,mz).Walkable;
|
|
|
|
while(index)
|
|
{
|
|
// ASSERT(index >= 0);
|
|
// ASSERT(WITHIN(index, 1, next_prim_face4 - 1));
|
|
|
|
if (is_thing_on_this_quad(x,z, index))
|
|
{
|
|
//
|
|
// We've found a face to stand on. But at what height?
|
|
// we are on this face so use clipped alpha and beta in calc height on face
|
|
//
|
|
|
|
if(index<0)
|
|
{
|
|
calc_height_on_rface(x,z, -index,&facey);
|
|
|
|
}
|
|
else
|
|
{
|
|
calc_height_on_face(x,z, index,&facey);
|
|
}
|
|
|
|
dy = facey - y;
|
|
|
|
if(ignore_height_flag==FIND_ANYFACE)
|
|
{
|
|
*ret_y = facey;
|
|
|
|
return index;
|
|
}
|
|
|
|
if(dy<30 && ignore_height_flag==FIND_FACE_NEAR_BELOW)
|
|
{
|
|
*ret_y = facey;
|
|
|
|
return index;
|
|
}
|
|
|
|
if (dy <= 0xa0)
|
|
{
|
|
//
|
|
// This is a candidate face.
|
|
//
|
|
|
|
if (abs(dy) < best_dy)
|
|
{
|
|
best_dy = abs(dy);
|
|
best_face = index;
|
|
best_facey = facey;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Too much difference in y. Ignore this face.
|
|
//
|
|
}
|
|
}
|
|
|
|
if(index<0)
|
|
{
|
|
index = roof_faces4[-index].Next;
|
|
}
|
|
else
|
|
{
|
|
index = prim_faces4[index].WALKABLE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (best_face == NULL)
|
|
{
|
|
//
|
|
// Could not find a face to stand on. How about the ground?
|
|
//
|
|
|
|
if(PAP_2HI(x>>PAP_SHIFT_HI,z>>PAP_SHIFT_HI).Flags & PAP_FLAG_HIDDEN)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
groundy = PAP_calc_height_at(x,z); //+5
|
|
*ret_y = groundy;
|
|
|
|
dy = y - groundy;
|
|
|
|
if (abs(dy) < 0x50)
|
|
{
|
|
return GRAB_FLOOR; // step onto floor
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*ret_y = best_facey;
|
|
|
|
return best_face;
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
SLONG find_height_for_this_pos( SLONG x,SLONG z, SLONG *ret_face)
|
|
{
|
|
UBYTE mx;
|
|
UBYTE mz;
|
|
SLONG dy;
|
|
SLONG facey;
|
|
SWORD index;
|
|
SLONG groundy;
|
|
|
|
SWORD mx1 = x - 0x200 >> PAP_SHIFT_LO;
|
|
SWORD mz1 = z - 0x200 >> PAP_SHIFT_LO;
|
|
|
|
SWORD mx2 = x + 0x200 >> PAP_SHIFT_LO;
|
|
SWORD mz2 = z + 0x200 >> PAP_SHIFT_LO;
|
|
|
|
SATURATE(mx1, 0, PAP_SIZE_LO - 1);
|
|
SATURATE(mz1, 0, PAP_SIZE_LO - 1);
|
|
|
|
SATURATE(mx2, 0, PAP_SIZE_LO - 1);
|
|
SATURATE(mz2, 0, PAP_SIZE_LO - 1);
|
|
|
|
if(PAP_hi[x>>8][z>>8].Flags&PAP_FLAG_ROOF_EXISTS)
|
|
{
|
|
*ret_face=ROOF_HIDDEN_GET_FACE(x>>8,z>>8);
|
|
return(MAVHEIGHT(x>>8,z>>8)<<6);
|
|
}
|
|
|
|
for (mx = mx1; mx <= mx2; mx++)
|
|
for (mz = mz1; mz <= mz2; mz++)
|
|
{
|
|
index = PAP_2LO(mx,mz).Walkable;
|
|
|
|
while(index)
|
|
{
|
|
// ASSERT(index >= 0);
|
|
// ASSERT(WITHIN(index, 1, next_prim_face4 - 1));
|
|
|
|
if (is_thing_on_this_quad(x,z, index))
|
|
{
|
|
//
|
|
// We've found a face to stand on. But at what height?
|
|
//
|
|
|
|
//
|
|
// use result no matter what as we are on the face
|
|
//
|
|
if(index<0)
|
|
{
|
|
calc_height_on_rface(x,z, -index,&facey);
|
|
|
|
}
|
|
else
|
|
{
|
|
calc_height_on_face(x,z, index,&facey);
|
|
}
|
|
{
|
|
|
|
*ret_face = index;
|
|
|
|
return facey;
|
|
}
|
|
}
|
|
|
|
if(index<0)
|
|
{
|
|
index = roof_faces4[-index].Next;
|
|
}
|
|
else
|
|
{
|
|
index = prim_faces4[index].WALKABLE;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// How about the ground?
|
|
//
|
|
|
|
if(PAP_2HI(x>>PAP_SHIFT_HI,z>>PAP_SHIFT_HI).Flags & PAP_FLAG_HIDDEN)
|
|
return(0);
|
|
|
|
groundy = PAP_calc_height_at(x,z); //+5
|
|
|
|
*ret_face = 0;
|
|
return groundy; // step onto floor
|
|
|
|
}
|
|
|
|
SLONG RFACE_on_slope(SLONG face,SLONG x,SLONG z,SLONG *angle)
|
|
{
|
|
SLONG h0;
|
|
SLONG h1;
|
|
SLONG h2;
|
|
SLONG h3;
|
|
|
|
SLONG xfrac;
|
|
SLONG zfrac;
|
|
|
|
|
|
struct RoofFace4 *rf;
|
|
|
|
ASSERT(face>0);
|
|
|
|
|
|
if(IS_ROOF_HIDDEN_FACE(-face))
|
|
return(0);
|
|
|
|
rf=&roof_faces4[face];
|
|
if(!(rf->RZ&128))
|
|
{
|
|
*angle=0;
|
|
return(0);
|
|
}
|
|
|
|
if(x>>8!=(rf->RX&127) ||z>>8!=(rf->RZ&127))
|
|
return(0);
|
|
|
|
|
|
|
|
h0 = rf->Y;
|
|
h1 = h0+(rf->DY[2]<<ROOF_SHIFT);
|
|
h2 = h0+(rf->DY[0]<<ROOF_SHIFT);
|
|
h3 = h0+(rf->DY[1]<<ROOF_SHIFT);
|
|
|
|
|
|
if (h0 == h1 && h1 == h2 && h2 == h3)
|
|
{
|
|
//
|
|
// No need to do any interpolation.
|
|
//
|
|
return(0);
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
// h0 h2
|
|
//
|
|
// h1 h3
|
|
|
|
|
|
h0 <<= PAP_ALT_SHIFT;
|
|
h1 <<= PAP_ALT_SHIFT;
|
|
h2 <<= PAP_ALT_SHIFT;
|
|
h3 <<= PAP_ALT_SHIFT;
|
|
|
|
xfrac = x & 0xff;
|
|
zfrac = z & 0xff;
|
|
|
|
if(rf->RX&(1<<7))
|
|
{
|
|
if (xfrac + (256-zfrac) < 0x100)
|
|
{
|
|
SLONG vx,vy,vz;
|
|
SLONG wx,wy,wz;
|
|
SLONG rx,ry,rz;
|
|
SLONG len;
|
|
|
|
vx=256;
|
|
vy=h3-h1;
|
|
vz=0;
|
|
|
|
wx=0;
|
|
wy=h0-h1;
|
|
wz=256;
|
|
|
|
rx=(vy*wz); //-vz*wy;
|
|
ry=65536; //vz*wx-vx*wz; dont care about this
|
|
rz=(vx*wy); //-vy*wx;
|
|
|
|
if(rx==0 && rz==0)
|
|
return(0);
|
|
|
|
*angle = (Arctan(rx,rz))&2047;
|
|
|
|
rx=abs(rx);
|
|
rz=abs(rz);
|
|
len=QDIST3(rx,ry,rz);
|
|
|
|
ry=(ry<<8)/(len);
|
|
|
|
return(abs(256-(len>>8)));
|
|
|
|
}
|
|
else
|
|
{
|
|
SLONG vx,vy,vz;
|
|
SLONG wx,wy,wz;
|
|
SLONG rx,ry,rz;
|
|
SLONG len;
|
|
|
|
vx=-256;
|
|
vy=h0-h2;
|
|
vz=0;
|
|
|
|
wx=0;
|
|
wy=h3-h2;
|
|
wz=256;
|
|
|
|
rx=(vy*wz); //-vz*wy;
|
|
ry=65536; //vz*wx-vx*wz; dont care about this
|
|
rz=(vx*wy); //-vy*wx;
|
|
|
|
if(rx==0 && rz==0)
|
|
return(0);
|
|
|
|
*angle = (Arctan(-rx,rz))&2047 ;
|
|
|
|
rx=abs(rx);
|
|
rz=abs(rz);
|
|
len=QDIST3(rx,ry,rz);
|
|
|
|
ry=(ry<<8)/(len);
|
|
|
|
return(abs(256-(len>>8)));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
if (xfrac + zfrac < 0x100)
|
|
{
|
|
SLONG vx,vy,vz;
|
|
SLONG wx,wy,wz;
|
|
SLONG rx,ry,rz;
|
|
SLONG len;
|
|
|
|
vx=256;
|
|
vy=h2-h0;
|
|
vz=0;
|
|
|
|
wx=0;
|
|
wy=h1-h0;
|
|
wz=-256;
|
|
|
|
rx=(vy*wz); //-vz*wy;
|
|
ry=65536; //vz*wx-vx*wz; dont care about this
|
|
rz=(vx*wy); //-vy*wx;
|
|
|
|
if(rx==0 && rz==0)
|
|
return(0);
|
|
|
|
*angle = (Arctan(-rx,-rz))&2047;
|
|
|
|
rx=abs(rx);
|
|
rz=abs(rz);
|
|
len=QDIST3(rx,ry,rz);
|
|
|
|
ry=(ry<<8)/(len);
|
|
|
|
return(abs(256-(len>>8)));
|
|
|
|
}
|
|
else
|
|
{
|
|
SLONG vx,vy,vz;
|
|
SLONG wx,wy,wz;
|
|
SLONG rx,ry,rz;
|
|
SLONG len;
|
|
|
|
vx=-256;
|
|
vy=h1-h3;
|
|
vz=0;
|
|
|
|
wx=0;
|
|
wy=h2-h3;
|
|
wz=-256;
|
|
|
|
rx=(vy*wz); //-vz*wy;
|
|
ry=65536; //vz*wx-vx*wz; dont care about this
|
|
rz=(vx*wy); //-vy*wx;
|
|
|
|
if(rx==0 && rz==0)
|
|
return(0);
|
|
|
|
*angle = (Arctan(rx,-rz))&2047 ;
|
|
|
|
rx=abs(rx);
|
|
rz=abs(rz);
|
|
len=QDIST3(rx,ry,rz);
|
|
|
|
ry=(ry<<8)/(len);
|
|
|
|
return(abs(256-(len>>8)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef PSX
|
|
void WALKABLE_remove_rface(UBYTE map_x, UBYTE map_z)
|
|
{
|
|
SWORD next;
|
|
SWORD *prev;
|
|
|
|
PAP_Lo *pl;
|
|
RoofFace4 *rf;
|
|
|
|
pl = &PAP_2LO(map_x >> 2, map_z >> 2);
|
|
|
|
if(PAP_hi[map_x][map_z].Flags&PAP_FLAG_ROOF_EXISTS)
|
|
{
|
|
PAP_hi[map_x][map_z].Flags&=~PAP_FLAG_ROOF_EXISTS;
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
prev = &pl->Walkable;
|
|
next = pl->Walkable;
|
|
|
|
while(next)
|
|
{
|
|
if (next < 0)
|
|
{
|
|
rf = &roof_faces4[-next];
|
|
|
|
if ((rf->RX&127) == map_x &&
|
|
(rf->RZ&127) == map_z)
|
|
{
|
|
//
|
|
// We have found the face to get rid of. Take it out of the linked list
|
|
// for this square.
|
|
//
|
|
|
|
*prev = rf->Next;
|
|
|
|
//
|
|
// Instead of deleting this face proper, we mark it as no-draw for now.
|
|
//
|
|
|
|
rf->DrawFlags |= RFACE_FLAG_NODRAW;
|
|
|
|
return;
|
|
}
|
|
|
|
prev = &rf->Next;
|
|
next = rf->Next;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// This is a normal walkable face.
|
|
//
|
|
|
|
prev = &prim_faces4[next].WALKABLE;
|
|
next = prim_faces4[next].WALKABLE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make this mapsquare be HIDDEN.
|
|
//
|
|
|
|
PAP_2HI(map_x,map_z).Flags |= PAP_FLAG_HIDDEN;
|
|
}
|
|
#endif
|
|
|