1597 lines
33 KiB
C++
1597 lines
33 KiB
C++
#include "game.h"
|
|
#include "pap.h"
|
|
#include "ns.h"
|
|
#include "supermap.h"
|
|
#include "fmatrix.h"
|
|
#include "memory.h"
|
|
#include "ware.h"
|
|
#include "mav.h"
|
|
|
|
//#include "c:\fallen\editor\headers\collide.hpp"
|
|
#include "c:\fallen\editor\headers\map.h"
|
|
#include "animate.h"
|
|
#include "FMatrix.h"
|
|
#ifndef PSX
|
|
#include "c:\fallen\editor\headers\prim_draw.h"
|
|
#else
|
|
extern void rotate_obj(SWORD xangle,SWORD yangle,SWORD zangle, Matrix33 *r3);
|
|
|
|
#endif
|
|
/*
|
|
|
|
actions that cause you to look for a grab face
|
|
|
|
jumping through the air in grab mode
|
|
Jumping vertically in grab mode
|
|
standing on a face and jumping vertically
|
|
|
|
|
|
so we should probably look for the edge of a walkable face within a certain radius
|
|
and a certain height range
|
|
|
|
|
|
|
|
|
|
*/
|
|
/*
|
|
struct KeyFrame *anim_array[300],
|
|
*cop_array[300],
|
|
*darci_array[300],
|
|
*roper_array[300],
|
|
*van_array[20],
|
|
*thug_array[300];
|
|
*/
|
|
struct GameKeyFrame *global_anim_array[4][450];
|
|
|
|
struct KeyFrameChunk *test_chunk;
|
|
#if !defined(PSX) && !defined(TARGET_DC)
|
|
struct KeyFrameChunk test_chunk2;
|
|
struct KeyFrameChunk test_chunk3;
|
|
struct KeyFrameChunk thug_chunk;
|
|
#endif
|
|
struct KeyFrameElement *the_elements;
|
|
struct GameKeyFrameChunk game_chunk[MAX_GAME_CHUNKS];
|
|
struct GameKeyFrameChunk anim_chunk[MAX_ANIM_CHUNKS];
|
|
|
|
SLONG next_game_chunk=0;
|
|
SLONG next_anim_chunk=0;
|
|
|
|
//
|
|
// The bounding boxes of the anim prims in the initial position of
|
|
// their first frame. They are calculated by calling find_anim_prim_bboxes()
|
|
//
|
|
#ifndef PSX
|
|
AnimPrimBbox anim_prim_bbox[MAX_ANIM_CHUNKS];
|
|
#endif
|
|
|
|
|
|
|
|
extern SLONG nearest_point_on_line_and_dist( SLONG x1, SLONG z1, SLONG x2, SLONG z2, SLONG a, SLONG b,SLONG *ret_x,SLONG *ret_z);
|
|
|
|
SLONG calc_angle(SLONG dx,SLONG dz)
|
|
{
|
|
SLONG angle=0;
|
|
|
|
angle=Arctan(-dx,dz)+1024;
|
|
|
|
/*
|
|
if(angle<0)
|
|
{
|
|
angle=2048+angle;
|
|
}
|
|
*/
|
|
|
|
angle=angle&2047;
|
|
|
|
return(angle);
|
|
|
|
}
|
|
|
|
SLONG angle_diff(SLONG angle1,SLONG angle2)
|
|
{
|
|
SLONG diff;
|
|
|
|
//0 .. 2047 - 0--2047
|
|
//0-2047 = -2047 ==-1
|
|
//1024-0 = 1024
|
|
//
|
|
/*
|
|
if(angle1>1024)
|
|
angle1=angle1-2048;
|
|
|
|
if(angle2>1024)
|
|
angle2=angle2-2048;
|
|
*/
|
|
diff = angle1 - angle2;
|
|
|
|
if (diff > +1024) {diff -= 2048;}
|
|
else if (diff < -1024) {diff += 2048;}
|
|
|
|
return diff;
|
|
}
|
|
|
|
SLONG valid_grab_angle(SLONG angle,SLONG dx,SLONG dz)
|
|
{
|
|
SLONG wall_angle,diff;
|
|
return(1);
|
|
|
|
wall_angle=calc_angle(dx,dz);
|
|
LogText(" wall angle %d player angle %d \n",wall_angle,angle);
|
|
wall_angle+=512; //or -512
|
|
|
|
diff=angle_diff(angle,wall_angle);
|
|
LogText(" wall angle %d player angle %d diff %d\n",wall_angle,angle,diff);
|
|
diff=abs(diff);
|
|
if(diff<256 || abs(diff-1024)<256 ) //second if is for -512
|
|
return(1);
|
|
else
|
|
{
|
|
return(0);
|
|
// MSG_add(" WRONG grab angle ");
|
|
}
|
|
}
|
|
|
|
|
|
extern void e_draw_3d_mapwho(SLONG x1,SLONG z1);
|
|
extern void highlight_face(SLONG face);
|
|
|
|
#define ON_MAP(x,z) (((x)>=0) && ((z)>=0) && ((x)<MAP_WIDTH) && ((z)<MAP_HEIGHT))
|
|
|
|
SLONG find_cable_y_along(struct DFacet *p_facet,SLONG along)
|
|
{
|
|
SLONG max_at,y;
|
|
SLONG angle_step1,angle_step2,count;
|
|
|
|
|
|
angle_step1=(SWORD)p_facet->StyleIndex;
|
|
angle_step2=(SWORD)p_facet->Building;
|
|
count=p_facet->Height;
|
|
|
|
//
|
|
// how many steps along facet to reach maximum dip
|
|
//
|
|
max_at=(512<<CABLE_ALONG_SHIFT)/angle_step1;
|
|
|
|
max_at/=count;
|
|
|
|
//
|
|
// max_at is now in same formal as along
|
|
//
|
|
|
|
if(along<max_at)
|
|
{
|
|
SLONG step,angle;
|
|
|
|
step=(along*count);
|
|
step=(step*angle_step1)>>CABLE_ALONG_SHIFT;
|
|
angle=(-512+step+2048)&2047;
|
|
|
|
y=-(COS(angle)*p_facet->FHeight)>>(16-6);
|
|
}
|
|
else
|
|
{
|
|
SLONG step,angle;
|
|
|
|
step=((CABLE_ALONG_MAX-along)*count);
|
|
step=-(step*angle_step2)>>CABLE_ALONG_SHIFT;
|
|
angle=(-512+step+2048)&2047;
|
|
|
|
y=-(COS(angle)*p_facet->FHeight)>>(16-6);
|
|
|
|
}
|
|
|
|
{
|
|
SLONG dy;
|
|
dy=p_facet->Y[1]-p_facet->Y[0];
|
|
dy=((dy*along)>>CABLE_ALONG_SHIFT)+p_facet->Y[0];
|
|
|
|
y+=dy;
|
|
|
|
}
|
|
return(y);
|
|
}
|
|
|
|
SLONG check_grab_cable_facet(SLONG facet,SLONG *grab_x,SLONG *grab_y,SLONG *grab_z,SLONG *grab_angle,SLONG radius,SLONG dy,SLONG x,SLONG y,SLONG z)
|
|
{
|
|
struct DFacet *p_facet;
|
|
SLONG near_x,near_z,along;
|
|
SLONG dist;
|
|
SLONG cable_y;
|
|
|
|
p_facet=&dfacets[facet];
|
|
|
|
extern SLONG nearest_point_on_line_and_dist_and_along( SLONG x1, SLONG z1, SLONG x2, SLONG z2, SLONG a, SLONG b,SLONG *ret_x,SLONG *ret_z,SLONG *ret_along);
|
|
|
|
dist = nearest_point_on_line_and_dist_and_along(
|
|
p_facet->x[0] << 8, p_facet->z[0] << 8,
|
|
p_facet->x[1] << 8, p_facet->z[1] << 8,
|
|
x, z,
|
|
&near_x,
|
|
&near_z,
|
|
&along);
|
|
|
|
if(dist>radius)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
if (!WITHIN(along, 4, 252))
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
cable_y=find_cable_y_along(p_facet,along<<(CABLE_ALONG_SHIFT - 8));
|
|
|
|
if(abs(cable_y-y)>dy)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
*grab_x=near_x;
|
|
*grab_z=near_z;
|
|
*grab_y=cable_y;
|
|
{
|
|
SLONG dx,dz,angle;
|
|
|
|
dx = p_facet->x[1] - p_facet->x[0] << 8;
|
|
dz = p_facet->z[1] - p_facet->z[0] << 8;
|
|
|
|
*grab_angle=calc_angle(dx,dz);
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
SLONG check_grab_ladder_facet(SLONG facet,SLONG *grab_x,SLONG *grab_y,SLONG *grab_z,SLONG *grab_angle,SLONG radius,SLONG dy,SLONG x,SLONG y,SLONG z)
|
|
{
|
|
struct DFacet *p_facet;
|
|
SLONG near_x,near_z,along;
|
|
SLONG dist;
|
|
SLONG cable_y;
|
|
SLONG top,bot;
|
|
|
|
p_facet=&dfacets[facet];
|
|
|
|
extern SLONG nearest_point_on_line_and_dist_and_along( SLONG x1, SLONG z1, SLONG x2, SLONG z2, SLONG a, SLONG b,SLONG *ret_x,SLONG *ret_z,SLONG *ret_along);
|
|
|
|
dist = nearest_point_on_line_and_dist_and_along(
|
|
p_facet->x[0] << 8, p_facet->z[0] << 8,
|
|
p_facet->x[1] << 8, p_facet->z[1] << 8,
|
|
x, z,
|
|
&near_x,
|
|
&near_z,
|
|
&along);
|
|
|
|
if(dist>(radius>>1) || along==0 ||along==255)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
|
|
bot = p_facet->Y[0];
|
|
top = bot + p_facet->Height * 64;
|
|
|
|
if(y>top || y<bot)
|
|
{
|
|
if(y>top&&y<top+64)
|
|
{
|
|
//
|
|
// If we keep falling we will grab the ladder soon
|
|
// so tell grab ledge to exit until we are low enough to grab ledge
|
|
return(-1);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
correct_pos_for_ladder(p_facet,&near_x,&near_z,grab_angle,256);
|
|
*grab_x=near_x;
|
|
*grab_z=near_z;
|
|
*grab_y=y;
|
|
return(1);
|
|
}
|
|
|
|
SLONG get_cable_along(SLONG facet,SLONG ax,SLONG az)
|
|
{
|
|
SLONG dx;
|
|
SLONG dz;
|
|
|
|
SLONG x1;
|
|
SLONG z1;
|
|
|
|
SLONG x2;
|
|
SLONG z2;
|
|
|
|
|
|
SLONG along;
|
|
|
|
struct DFacet *p_facet;
|
|
|
|
p_facet=&dfacets[facet];
|
|
|
|
x1=p_facet->x[0] << 8;
|
|
x2=p_facet->x[1] << 8;
|
|
|
|
z1=p_facet->z[0] << 8;
|
|
z2=p_facet->z[1] << 8;
|
|
|
|
dx = x2 - x1;
|
|
dz = z2 - z1;
|
|
|
|
ax -= x1;
|
|
az -= z1;
|
|
|
|
|
|
if (abs(dx) > abs(dz))
|
|
{
|
|
along = (ax << CABLE_ALONG_SHIFT) / dx;
|
|
}
|
|
else
|
|
{
|
|
if (dz==0)
|
|
{
|
|
dz=1;
|
|
}
|
|
|
|
along = (az << CABLE_ALONG_SHIFT) / dz;
|
|
}
|
|
|
|
return along;
|
|
}
|
|
|
|
extern SLONG nearest_point_on_line_and_dist_calc_y( SLONG x1, SLONG y1,SLONG z1, SLONG x2, SLONG y2,SLONG z2, SLONG a, SLONG b,SLONG *ret_x,SLONG *ret_y,SLONG *ret_z);
|
|
|
|
|
|
SLONG grab_px[4],grab_py[4],grab_pz[4];
|
|
SLONG best_dist;
|
|
SLONG best_x;
|
|
SLONG best_y;
|
|
SLONG best_z;
|
|
SLONG best_angle;
|
|
|
|
|
|
SLONG find_grab_face(
|
|
SLONG x,
|
|
SLONG y,
|
|
SLONG z,
|
|
SLONG radius,
|
|
SLONG dy,
|
|
SLONG angle,
|
|
SLONG *grab_x,
|
|
SLONG *grab_y,
|
|
SLONG *grab_z,
|
|
SLONG *grab_angle,
|
|
SLONG ignore_building,
|
|
SLONG trench,
|
|
SLONG *type,
|
|
Thing *p_person)
|
|
{
|
|
SLONG i;
|
|
|
|
SLONG dx;
|
|
SLONG dz;
|
|
|
|
SLONG x1, z1;
|
|
SLONG x2, z2;
|
|
|
|
SLONG mx,mz;
|
|
|
|
SLONG index;
|
|
SLONG face;
|
|
SLONG near_x,near_y,near_z;
|
|
SLONG dist;
|
|
SLONG mid_x,mid_z;
|
|
SLONG angle_to_face;
|
|
SLONG count=0,count2=0;
|
|
SLONG cable=0;
|
|
|
|
SLONG thing;
|
|
Thing *p_thing;
|
|
SLONG pass=0;
|
|
|
|
best_dist = radius;
|
|
*type=0;
|
|
|
|
//
|
|
// Where we search for a face to grab.
|
|
//
|
|
|
|
x1 = x - radius - 0x100 >> PAP_SHIFT_LO;
|
|
z1 = z - radius - 0x100 >> PAP_SHIFT_LO;
|
|
|
|
x2 = x + radius + 0x100 >> PAP_SHIFT_LO;
|
|
z2 = z + radius + 0x100 >> PAP_SHIFT_LO;
|
|
|
|
//
|
|
// Don't go off the map.
|
|
//
|
|
|
|
SATURATE(x1, 0, PAP_SIZE_LO - 1);
|
|
SATURATE(x2, 0, PAP_SIZE_LO - 1);
|
|
|
|
SATURATE(z1, 0, PAP_SIZE_LO - 1);
|
|
SATURATE(z2, 0, PAP_SIZE_LO - 1);
|
|
|
|
for (mx = x1; mx <= x2; mx++)
|
|
for (mz = z1; mz <= z2; mz++)
|
|
{
|
|
SLONG facet,exit;
|
|
|
|
index = PAP_2LO(mx,mz).ColVectHead;
|
|
|
|
|
|
for(exit=0;exit==0;index++)
|
|
{
|
|
facet=facet_links[index];
|
|
if(facet<0)
|
|
{
|
|
exit=1;
|
|
facet=-facet;
|
|
}
|
|
if(dfacets[facet].FacetType==STOREY_TYPE_CABLE)
|
|
{
|
|
SLONG grab;
|
|
grab=check_grab_cable_facet(facet,grab_x,grab_y,grab_z,grab_angle,radius+30,dy,x,y,z);
|
|
if(grab)
|
|
{
|
|
*type=1;
|
|
return(facet);
|
|
}
|
|
|
|
}
|
|
else
|
|
if(dfacets[facet].FacetType==STOREY_TYPE_LADDER)
|
|
{
|
|
SLONG grab;
|
|
grab=check_grab_ladder_facet(facet,grab_x,grab_y,grab_z,grab_angle,radius,dy,x,y,z);
|
|
if(grab)
|
|
{
|
|
if(grab==-1)
|
|
{
|
|
return(0);
|
|
}
|
|
else
|
|
{
|
|
*type=2;
|
|
return(facet);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
round_again:;
|
|
|
|
if(pass==0)
|
|
{
|
|
x1 = x - radius - 0x100 >> PAP_SHIFT_HI;
|
|
z1 = z - radius - 0x100 >> PAP_SHIFT_HI;
|
|
|
|
x2 = x + radius + 0x100 >> PAP_SHIFT_HI;
|
|
z2 = z + radius + 0x100 >> PAP_SHIFT_HI;
|
|
SATURATE(x1, 0, PAP_SIZE_HI - 1);
|
|
SATURATE(x2, 0, PAP_SIZE_HI - 1);
|
|
|
|
SATURATE(z1, 0, PAP_SIZE_HI - 1);
|
|
SATURATE(z2, 0, PAP_SIZE_HI - 1);
|
|
}
|
|
else
|
|
{
|
|
x1 = x - radius - 0x100 >> PAP_SHIFT_LO;
|
|
z1 = z - radius - 0x100 >> PAP_SHIFT_LO;
|
|
|
|
x2 = x + radius + 0x100 >> PAP_SHIFT_LO;
|
|
z2 = z + radius + 0x100 >> PAP_SHIFT_LO;
|
|
|
|
SATURATE(x1, 0, PAP_SIZE_LO - 1);
|
|
SATURATE(x2, 0, PAP_SIZE_LO - 1);
|
|
|
|
SATURATE(z1, 0, PAP_SIZE_LO - 1);
|
|
SATURATE(z2, 0, PAP_SIZE_LO - 1);
|
|
}
|
|
|
|
|
|
for (mx = x1; mx <= x2; mx++)
|
|
for (mz = z1; mz <= z2; mz++)
|
|
{
|
|
if(pass==0)
|
|
{
|
|
if(PAP_hi[mx][mz].Flags&PAP_FLAG_ROOF_EXISTS)
|
|
{
|
|
index=ROOF_HIDDEN_GET_FACE(mx,mz);
|
|
}
|
|
else
|
|
index=0;
|
|
}
|
|
else
|
|
index = PAP_2LO(mx,mz).Walkable;
|
|
|
|
while(index&&count++<100)
|
|
{
|
|
face = index;
|
|
|
|
// if (face > 0)
|
|
{
|
|
SLONG p;
|
|
SLONG c0;
|
|
SLONG p0,p1,p2,p3;
|
|
SLONG face_angle;
|
|
SLONG dangle;
|
|
|
|
PrimFace4 *p_f4;
|
|
struct RoofFace4 *rf;
|
|
|
|
|
|
// highlight_face(face);
|
|
|
|
if (face>0 && prim_faces4[face].ThingIndex == ignore_building)
|
|
{
|
|
//
|
|
// Don't collide with faces from this building
|
|
//
|
|
|
|
}
|
|
else
|
|
{
|
|
{
|
|
cable=0;
|
|
}
|
|
|
|
if(face>0)
|
|
{
|
|
p_f4 = &prim_faces4[face];
|
|
for (c0 = 0; c0 < 4; c0++)
|
|
{
|
|
p = p_f4->Points[c0];
|
|
|
|
grab_px[c0] = 0 + prim_points[p].X;
|
|
grab_py[c0] = 0 + prim_points[p].Y;
|
|
grab_pz[c0] = 0 + prim_points[p].Z;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
if(IS_ROOF_HIDDEN_FACE(face))
|
|
{
|
|
rf=0;
|
|
grab_px[0]=(mx)<<8;
|
|
grab_pz[0]=(mz)<<8;
|
|
|
|
grab_py[0]=grab_py[1]=grab_py[2]=grab_py[3]=MAVHEIGHT(mx,mz)<<6;
|
|
|
|
|
|
}
|
|
else
|
|
|
|
{
|
|
rf = &roof_faces4[-face];
|
|
|
|
grab_px[0]=(rf->RX&127)<<8;
|
|
grab_pz[0]=(rf->RZ&127)<<8;
|
|
grab_py[0]=rf->Y;
|
|
grab_py[1]=rf->Y+(rf->DY[0]<<ROOF_SHIFT);
|
|
grab_py[2]=rf->Y+(rf->DY[2]<<ROOF_SHIFT);
|
|
grab_py[3]=rf->Y+(rf->DY[1]<<ROOF_SHIFT);
|
|
}
|
|
|
|
grab_px[1]=grab_px[0]+256;
|
|
grab_pz[1]=grab_pz[0];//+256;
|
|
|
|
grab_px[2]=grab_px[0];
|
|
grab_pz[2]=grab_pz[0]+256;//+256;
|
|
|
|
grab_px[3]=grab_px[0]+256;
|
|
grab_pz[3]=grab_pz[0]+256;//+256;
|
|
|
|
}
|
|
|
|
//
|
|
// assume that non flat faces never deviate by more than 256
|
|
//
|
|
if (abs(grab_py[0] - y) < 256+dy)//+256)
|
|
{
|
|
MSG_add("***** grab face in in in in range abs(%d - %d) !< %d\n",grab_py[0],y,dy);
|
|
|
|
//
|
|
// The face is in y-range.
|
|
//
|
|
|
|
UBYTE point_order[4] = {0, 1, 3, 2};
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
//
|
|
// Check the four sides of this face.
|
|
//
|
|
|
|
|
|
|
|
//
|
|
//i==0 is north edge, i==1 is east edge i==2 south edge i==3 is west edge
|
|
//
|
|
ULONG faceflag;
|
|
ULONG edgeflag;
|
|
|
|
if(pass==0)
|
|
{
|
|
switch(i)
|
|
{
|
|
case 0:
|
|
if(abs((MAVHEIGHT(mx,mz-1)<<6)-grab_py[0])<0xa0)
|
|
continue;
|
|
break;
|
|
case 1:
|
|
if(abs((MAVHEIGHT(mx+1,mz)<<6)-grab_py[0])<0xa0)
|
|
continue;
|
|
break;
|
|
case 2:
|
|
if(abs((MAVHEIGHT(mx,mz+1)<<6)-grab_py[0])<0xa0)
|
|
continue;
|
|
break;
|
|
case 3:
|
|
if(abs((MAVHEIGHT(mx-1,mz)<<6)-grab_py[0])<0xa0)
|
|
continue;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(face<0)
|
|
{
|
|
if(rf)
|
|
{
|
|
faceflag = rf->DrawFlags;
|
|
}
|
|
edgeflag = RFACE_FLAG_SLIDE_EDGE;
|
|
edgeflag <<= i;
|
|
}
|
|
else
|
|
{
|
|
faceflag = p_f4->FaceFlags;
|
|
edgeflag = FACE_FLAG_SLIDE_EDGE;
|
|
edgeflag <<= i;
|
|
}
|
|
|
|
MSG_add(" faceflag %x edgeflag %x \n",faceflag,edgeflag);
|
|
|
|
if ((faceflag & edgeflag) ||IS_ROOF_HIDDEN_FACE(face))
|
|
{
|
|
MSG_add(" useful edge %d \n",i);
|
|
|
|
p0 = point_order[(i)];
|
|
p1 = point_order[(i + 1) & 3];
|
|
|
|
if (cable)
|
|
{
|
|
face_angle = angle + 512;
|
|
face_angle &= 2047;
|
|
}
|
|
else
|
|
{
|
|
dx = grab_px[p1] - grab_px[p0];
|
|
dz = grab_pz[p1] - grab_pz[p0];
|
|
|
|
face_angle = calc_angle(dx,dz);
|
|
}
|
|
|
|
//
|
|
// Are we facing this face enough?
|
|
//
|
|
|
|
face_angle += 512;
|
|
face_angle &= 2047;
|
|
|
|
dangle = face_angle - angle;
|
|
|
|
if (dangle < 1024) {dangle += 2048;}
|
|
if (dangle > 1024) {dangle -= 2048;}
|
|
|
|
MSG_add(" dangle %d <200? \n",dangle);
|
|
|
|
if (abs(dangle) < 200||cable)
|
|
{
|
|
//
|
|
// Angle okay.
|
|
//
|
|
|
|
if(pass==0)
|
|
{
|
|
|
|
// AENG_world_line(grab_px[p0],grab_py[p0],grab_pz[p0],6,0xff0000,
|
|
// grab_px[p1],grab_py[p1],grab_pz[p1],1,0xff0000,1);
|
|
}
|
|
dist = nearest_point_on_line_and_dist_calc_y(
|
|
grab_px[p0],grab_py[p0],grab_pz[p0],
|
|
grab_px[p1],grab_py[p1],grab_pz[p1],
|
|
x,z,
|
|
&near_x,
|
|
&near_y,
|
|
&near_z);
|
|
|
|
if (dist < radius && abs(near_y - y) < dy)
|
|
{
|
|
if (face > 0)
|
|
{
|
|
//
|
|
// Make sure this isn't too near to the ground?
|
|
//
|
|
|
|
if (PAP_calc_map_height_at(near_x, near_z) > grab_py[0] - 0x80)
|
|
{
|
|
//
|
|
// This walkable face is too near the ground to grab.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Found somewhere to grab- but does it lie along a fence?
|
|
//
|
|
|
|
{
|
|
SLONG fx1;
|
|
SLONG fz1;
|
|
SLONG fx2;
|
|
SLONG fz2;
|
|
|
|
fx1 = near_x;
|
|
fz1 = near_z;
|
|
fx2 = near_x;
|
|
fz2 = near_z;
|
|
|
|
if (abs(SIN(face_angle)) < abs(COS(face_angle)))
|
|
{
|
|
fx1 += 256;
|
|
fz1 += 128;
|
|
fz2 += 128;
|
|
}
|
|
else
|
|
{
|
|
fz2 += 256;
|
|
fx1 += 128;
|
|
fx2 += 128;
|
|
}
|
|
|
|
fx1 &= ~0xff;
|
|
fz1 &= ~0xff;
|
|
fx2 &= ~0xff;
|
|
fz2 &= ~0xff;
|
|
|
|
if (!does_fence_lie_along_line(
|
|
fx1, fz1,
|
|
fx2, fz2))
|
|
{
|
|
*grab_x = near_x;
|
|
*grab_y = near_y;//grab_py[p0];
|
|
*grab_z = near_z;
|
|
*grab_angle = face_angle;
|
|
|
|
return face;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Distance okay. Is this place too near a wall?
|
|
//
|
|
|
|
|
|
SLONG cx1 = near_x;
|
|
SLONG cy1 = grab_py[p0];
|
|
SLONG cz1 = near_z;
|
|
|
|
SLONG cx2 = near_x;
|
|
SLONG cy2 = grab_py[p0];
|
|
SLONG cz2 = near_z;
|
|
|
|
SLONG cx3 = near_x;
|
|
SLONG cy3 = grab_py[p0];
|
|
SLONG cz3 = near_z;
|
|
|
|
SLONG cx4 = near_x;
|
|
SLONG cy4 = grab_py[p0];
|
|
SLONG cz4 = near_z;
|
|
|
|
|
|
#define CHECK_WIDTH 32
|
|
#define CHECK_FORWARD 16
|
|
|
|
//
|
|
// We divide by 8 so that edges which are just of 90 degrees
|
|
// snap to being 90 degrees.
|
|
//
|
|
|
|
SLONG dx = SIGN((grab_px[p1] - grab_px[p0]) / 8);
|
|
SLONG dz = SIGN((grab_pz[p1] - grab_pz[p0]) / 8);
|
|
|
|
// ASSERT(pass);
|
|
|
|
|
|
|
|
cx1 += (+dx) * CHECK_WIDTH + (-dz) * CHECK_FORWARD;
|
|
cz1 += (+dz) * CHECK_WIDTH + (+dx) * CHECK_FORWARD;
|
|
|
|
cx2 += (-dx) * CHECK_WIDTH + (-dz) * CHECK_FORWARD;
|
|
cz2 += (-dz) * CHECK_WIDTH + (+dx) * CHECK_FORWARD;
|
|
|
|
cx3 += (+dx) * CHECK_WIDTH - (-dz) * CHECK_FORWARD;
|
|
cz3 += (+dz) * CHECK_WIDTH - (+dx) * CHECK_FORWARD;
|
|
|
|
cx4 += (-dx) * CHECK_WIDTH - (-dz) * CHECK_FORWARD;
|
|
cz4 += (-dz) * CHECK_WIDTH - (+dx) * CHECK_FORWARD;
|
|
|
|
SLONG height1;
|
|
SLONG height2;
|
|
SLONG height3;
|
|
SLONG height4;
|
|
|
|
SLONG face1;
|
|
SLONG face2;
|
|
|
|
if (p_person->Genus.Person->Ware)
|
|
{
|
|
height1 = WARE_calc_height_at(p_person->Genus.Person->Ware, cx1,cz1);
|
|
height2 = WARE_calc_height_at(p_person->Genus.Person->Ware, cx2,cz2);
|
|
height3 = WARE_calc_height_at(p_person->Genus.Person->Ware, cx3,cz3);
|
|
height4 = WARE_calc_height_at(p_person->Genus.Person->Ware, cx4,cz4);
|
|
}
|
|
else
|
|
{
|
|
height1 = PAP_calc_map_height_at(cx1,cz1);
|
|
height2 = PAP_calc_map_height_at(cx2,cz2);
|
|
height3 = PAP_calc_map_height_at(cx3,cz3);
|
|
height4 = PAP_calc_map_height_at(cx4,cz4);
|
|
|
|
// AENG_world_line(cx1,height1,cz1,10,0xffffff,cx1,height1+256,cz1,1,0xffffff,1);
|
|
// AENG_world_line(cx2,height2,cz2,10,0xffffff,cx2,height2,cz2,1,0xffffff,1);
|
|
}
|
|
|
|
/*
|
|
|
|
face1 = find_face_for_this_pos(cx1, cy1, cz1, &height1, NULL,0);
|
|
|
|
if (face1)
|
|
{
|
|
face2 = find_face_for_this_pos(cx2, cy2, cz2, &height2, NULL,0);
|
|
}
|
|
|
|
if (face1 && face2)
|
|
|
|
*/
|
|
|
|
if(radius<30|| radius>90 || abs(cy1-PAP_calc_map_height_at(x,z))>0xa0) //radius <30 is to allow sideling
|
|
if (abs(height1 - cy1) < 64 &&
|
|
abs(height2 - cy2) < 64 &&
|
|
height3 <= height1 &&
|
|
height4 <= height2)
|
|
{
|
|
SLONG dy = height2 - height1;
|
|
|
|
if (abs(dy) < 64)
|
|
{
|
|
//
|
|
// Found somewhere to grab. But does it lie along a fence?
|
|
//
|
|
|
|
{
|
|
SLONG fx1;
|
|
SLONG fz1;
|
|
SLONG fx2;
|
|
SLONG fz2;
|
|
|
|
fx1 = near_x;
|
|
fz1 = near_z;
|
|
fx2 = near_x;
|
|
fz2 = near_z;
|
|
|
|
if (abs(SIN(face_angle)) < abs(COS(face_angle)))
|
|
{
|
|
fx1 += 256;
|
|
fz1 += 128;
|
|
fz2 += 128;
|
|
}
|
|
else
|
|
{
|
|
fz2 += 256;
|
|
fx1 += 128;
|
|
fx2 += 128;
|
|
}
|
|
|
|
fx1 &= ~0xff;
|
|
fz1 &= ~0xff;
|
|
fx2 &= ~0xff;
|
|
fz2 &= ~0xff;
|
|
|
|
if (!does_fence_lie_along_line(
|
|
fx1, fz1,
|
|
fx2, fz2))
|
|
{
|
|
*grab_x = near_x;
|
|
*grab_y = grab_py[p0];
|
|
*grab_z = near_z;
|
|
*grab_angle = face_angle;
|
|
|
|
MSG_add(" YES YES YES grab Face dist %d radius %d y %d\n",dist,radius,grab_py[p0]);
|
|
|
|
return face;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MSG_add("TOO NEAR A WALL (%d) !!!!!!", dy);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MSG_add("Couldn't find faces.");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
MSG_add(" dist %d to far %d \n",dist,radius);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
MSG_add(" grab face out range abs(%d - %d) !< %d\n",grab_py[0],y,dy);
|
|
|
|
}
|
|
}
|
|
|
|
if(pass==0)
|
|
{
|
|
index=0;
|
|
}
|
|
else
|
|
if(index<0)
|
|
{
|
|
index = roof_faces4[-index].Next; //acts as next field for walkable faces
|
|
}
|
|
else
|
|
{
|
|
index = prim_faces4[index].WALKABLE; //acts as next field for walkable faces
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
pass++;
|
|
if(pass==1)
|
|
goto round_again;
|
|
|
|
#if 0
|
|
|
|
if(trench)
|
|
{
|
|
SWORD mx;
|
|
SWORD mz;
|
|
SWORD dx,dz;
|
|
SLONG floor_height;
|
|
|
|
//
|
|
// Person is over trench square so try grab edge of trench
|
|
//
|
|
|
|
for(dx=-1;dx<=1;dx++)
|
|
for(dz=-1;dz<=1;dz++)
|
|
{
|
|
if((dx|dz) && !(dx && dz))
|
|
{
|
|
mx = (x >> PAP_SHIFT_HI) + dx;
|
|
mz = (z >> PAP_SHIFT_HI) + dz;
|
|
|
|
if (PAP_on_map_hi(mx,mz))
|
|
{
|
|
if (!(PAP_2HI(mx,mz).Flags & (PAP_FLAG_HIDDEN)))
|
|
{
|
|
floor_height = PAP_2HI(
|
|
(x >> PAP_SHIFT_HI) + MIN(dx, 0),
|
|
(z >> PAP_SHIFT_HI) + MIN(dz, 0)).Alt << FLOOR_HEIGHT_SHIFT;
|
|
|
|
if(abs(floor_height-y)<dy)
|
|
{
|
|
if(dx==-1)
|
|
dist=x&0xff;
|
|
else
|
|
if(dx==1)
|
|
dist=255-(x&0xff);
|
|
else
|
|
if(dz==-1)
|
|
dist=z&0xff;
|
|
else
|
|
if(dz==1)
|
|
dist=255-(z&0xff);
|
|
|
|
if(dist<best_dist)
|
|
{
|
|
// LogText(" best %d \n",dist);
|
|
best_dist = dist;
|
|
best_y = floor_height;
|
|
|
|
if(dx==-1)
|
|
{
|
|
best_x = x & 0xffffff00;
|
|
best_z = z;
|
|
best_angle = 512; // 90 degrees
|
|
}
|
|
else
|
|
if(dx==1)
|
|
{
|
|
best_x = (x + 256) & 0xffffff00;
|
|
best_z = z;
|
|
best_angle = 1536; // 270 degrees
|
|
}
|
|
else
|
|
if(dz==-1)
|
|
{
|
|
best_z = z & 0xffffff00;
|
|
best_x = x;
|
|
best_angle = 0;
|
|
}
|
|
else
|
|
if(dz==1)
|
|
{
|
|
best_z = (z + 256) & 0xffffff00;
|
|
best_x = x;
|
|
best_angle = 1024;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
if(best_dist<radius)
|
|
{
|
|
*grab_x = best_x;
|
|
*grab_y = best_y;
|
|
*grab_z = best_z;
|
|
*grab_angle = best_angle;
|
|
|
|
MSG_add(" grab radius best_y %d \n",best_y);
|
|
|
|
return(GRAB_FLOOR);
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return(0);
|
|
}
|
|
|
|
#if !defined(PSX) && !defined(TARGET_DC)
|
|
SLONG find_grab_face_in_sewers(
|
|
SLONG x,
|
|
SLONG y,
|
|
SLONG z,
|
|
SLONG radius,
|
|
SLONG dy,
|
|
SLONG angle,
|
|
SLONG *grab_x,
|
|
SLONG *grab_y,
|
|
SLONG *grab_z,
|
|
SLONG *grab_angle)
|
|
{
|
|
SLONG i;
|
|
|
|
SLONG mx;
|
|
SLONG mz;
|
|
SLONG dx;
|
|
SLONG dz;
|
|
SLONG floor_height;
|
|
|
|
SLONG best_dist = radius;
|
|
SLONG best_x;
|
|
SLONG best_y;
|
|
SLONG best_z;
|
|
SLONG best_angle;
|
|
|
|
SLONG dist;
|
|
SLONG dangle;
|
|
|
|
NS_Hi *nh;
|
|
|
|
const struct {SBYTE dx; SBYTE dz;} order[4] =
|
|
{
|
|
{+1, 0},
|
|
{-1, 0},
|
|
{0, +1},
|
|
{0, -1}
|
|
};
|
|
|
|
//
|
|
// Person is over trench square so try grab edge of trench
|
|
//
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
dx = order[i].dx;
|
|
dz = order[i].dz;
|
|
|
|
mx = (x >> PAP_SHIFT_HI) + dx;
|
|
mz = (z >> PAP_SHIFT_HI) + dz;
|
|
|
|
if (PAP_on_map_hi(mx,mz))
|
|
{
|
|
nh = &NS_hi[mx][mz];
|
|
|
|
if (NS_HI_TYPE(nh) != NS_HI_TYPE_ROCK &&
|
|
NS_HI_TYPE(nh) != NS_HI_TYPE_CURVE &&
|
|
NS_HI_TYPE(nh) != NS_HI_TYPE_NOTHING)
|
|
{
|
|
floor_height = (nh->bot << 5) + (-0x100 * 32);
|
|
|
|
if (abs(floor_height - y) < dy)
|
|
{
|
|
switch(i)
|
|
{
|
|
case 0: dist = 255 - (x & 0xff); break;
|
|
case 1: dist = (x & 0xff); break;
|
|
case 2: dist = 255 - (z & 0xff); break;
|
|
case 3: dist = (z & 0xff); break;
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
if(dist<best_dist)
|
|
{
|
|
switch(i)
|
|
{
|
|
case 0:
|
|
best_x = (x + 256) & 0xffffff00;
|
|
best_z = z;
|
|
best_angle = 1536; // 270 degrees
|
|
break;
|
|
|
|
case 1:
|
|
best_x = x & 0xffffff00;
|
|
best_z = z;
|
|
best_angle = 512; // 90 degrees
|
|
break;
|
|
|
|
case 2:
|
|
best_z = (z + 256) & 0xffffff00;
|
|
best_x = x;
|
|
best_angle = 1024;
|
|
break;
|
|
|
|
case 3:
|
|
best_z = z & 0xffffff00;
|
|
best_x = x;
|
|
best_angle = 0;
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
dangle = best_angle - angle;
|
|
|
|
if (dangle > 1024) {dangle -= 2048;}
|
|
if (dangle < -1024) {dangle += 2048;}
|
|
|
|
if (abs(dangle) < 200)
|
|
{
|
|
//
|
|
// Change in angle okay.
|
|
//
|
|
|
|
best_dist = dist;
|
|
best_y = floor_height;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (best_dist < radius)
|
|
{
|
|
*grab_x = best_x;
|
|
*grab_y = best_y;
|
|
*grab_z = best_z;
|
|
*grab_angle = best_angle;
|
|
|
|
return GRAB_SEWERS;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
struct Matrix33 r_matrix;
|
|
struct Matrix31 offset;
|
|
SLONG matrix[9];
|
|
|
|
void calc_sub_objects_position(Thing *p_mthing,SLONG tween,UWORD object,SLONG *x,SLONG *y,SLONG *z)
|
|
{
|
|
struct SVector temp; //max points per object?
|
|
struct GameKeyFrameElement *anim_info;
|
|
struct GameKeyFrameElement *anim_info_next;
|
|
struct Matrix33 *rot_mat;
|
|
SLONG wx,wy,wz;
|
|
DrawTween *dt = p_mthing->Draw.Tweened;
|
|
|
|
#ifdef PSX
|
|
{
|
|
SLONG index1,index2;
|
|
//
|
|
// stuff added for more compression of anims
|
|
//
|
|
extern struct PrimPoint *anim_mids; //[256];
|
|
|
|
index1=dt->CurrentFrame->XYZIndex;
|
|
index2=dt->NextFrame->XYZIndex;
|
|
|
|
if(index1!=index2)
|
|
{
|
|
wx=anim_mids[index1].X+(((anim_mids[index2].X-anim_mids[index1].X)*dt->AnimTween)>>8);
|
|
wy=anim_mids[index1].Y+(((anim_mids[index2].Y-anim_mids[index1].Y)*dt->AnimTween)>>8);
|
|
wz=anim_mids[index1].Z+(((anim_mids[index2].Z-anim_mids[index1].Z)*dt->AnimTween)>>8);
|
|
|
|
}
|
|
else
|
|
{
|
|
wx=anim_mids[index1].X;
|
|
wy=anim_mids[index1].Y;
|
|
wz=anim_mids[index1].Z;
|
|
}
|
|
|
|
}
|
|
#else
|
|
wx=0;
|
|
wy=0;
|
|
wz=0;
|
|
#endif
|
|
|
|
|
|
if (object==SUB_OBJECT_PREFERRED_HAND)
|
|
{
|
|
// object=(p_mthing->Genus.Person->Flags&FLAG_PERSON_OTHERHAND) ? SUB_OBJECT_RIGHT_HAND : SUB_OBJECT_LEFT_HAND;
|
|
object=SUB_OBJECT_LEFT_HAND;
|
|
}
|
|
|
|
|
|
if(p_mthing->Draw.Tweened->CurrentFrame && p_mthing->Draw.Tweened->NextFrame)
|
|
{
|
|
anim_info=&p_mthing->Draw.Tweened->CurrentFrame->FirstElement[object];
|
|
anim_info_next=&p_mthing->Draw.Tweened->NextFrame->FirstElement[object];
|
|
// anim_info_next=&p_mthing->NextAnimElements[object];
|
|
|
|
|
|
|
|
offset.M[0] = ((anim_info->OffsetX+(((anim_info_next->OffsetX-anim_info->OffsetX)*tween)>>8))>>TWEEN_OFFSET_SHIFT)+wx;
|
|
offset.M[1] = ((anim_info->OffsetY+(((anim_info_next->OffsetY-anim_info->OffsetY)*tween)>>8))>>TWEEN_OFFSET_SHIFT)+wy;
|
|
offset.M[2] = ((anim_info->OffsetZ+(((anim_info_next->OffsetZ-anim_info->OffsetZ)*tween)>>8))>>TWEEN_OFFSET_SHIFT)+wz;
|
|
|
|
{
|
|
//
|
|
// Takes roll into account properly.
|
|
//
|
|
|
|
|
|
FMATRIX_calc(
|
|
matrix,
|
|
p_mthing->Draw.Tweened->Angle,
|
|
p_mthing->Draw.Tweened->Tilt,
|
|
p_mthing->Draw.Tweened->Roll);
|
|
|
|
if (p_mthing->Class == CLASS_PERSON)
|
|
{
|
|
SLONG character_scale = person_get_scale(p_mthing);
|
|
|
|
if(character_scale!=256)
|
|
{
|
|
// offset.M[0]=(offset.M[0]*character_scale)>>8;
|
|
// offset.M[1]=(offset.M[1]*character_scale)>>8;
|
|
// offset.M[2]=(offset.M[2]*character_scale)>>8;
|
|
matrix[0] = (matrix[0] * character_scale) >>8;
|
|
matrix[1] = (matrix[1] * character_scale) >>8;
|
|
matrix[2] = (matrix[2] * character_scale) >>8;
|
|
matrix[3] = (matrix[3] * character_scale) >>8;
|
|
matrix[4] = (matrix[4] * character_scale) >>8;
|
|
matrix[5] = (matrix[5] * character_scale) >>8;
|
|
matrix[6] = (matrix[6] * character_scale) >>8;
|
|
matrix[7] = (matrix[7] * character_scale) >>8;
|
|
matrix[8] = (matrix[8] * character_scale) >>8;
|
|
}
|
|
}
|
|
|
|
|
|
FMATRIX_MUL_BY_TRANSPOSE(
|
|
matrix,
|
|
offset.M[0],
|
|
offset.M[1],
|
|
offset.M[2]);
|
|
|
|
*x = offset.M[0];//+wx;
|
|
*y = offset.M[1];//+wy;
|
|
*z = offset.M[2];//+wz;
|
|
|
|
if(object==SUB_OBJECT_LEFT_FOOT)
|
|
{
|
|
MSG_add(" tween %d y %d y-foot_height %d \n",tween,*y,*y-FOOT_HEIGHT);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
rotate_obj (
|
|
p_mthing->Draw.Tweened->Tilt,
|
|
p_mthing->Draw.Tweened->Angle,
|
|
p_mthing->Draw.Tweened->Roll,
|
|
&r_matrix
|
|
);
|
|
|
|
matrix_transformZMY((struct Matrix31*)&temp,&r_matrix, &offset);
|
|
*x=temp.X;
|
|
*y=temp.Y;
|
|
*z=temp.Z;
|
|
|
|
*/
|
|
|
|
}
|
|
else
|
|
{
|
|
*x=0;
|
|
*y=0;
|
|
*z=0;
|
|
|
|
}
|
|
if(object==SUB_OBJECT_LEFT_FOOT || object==SUB_OBJECT_RIGHT_FOOT)
|
|
*y-=10; //9;//16; //FOOT_HEIGHT;
|
|
if(object==SUB_OBJECT_LEFT_HAND || object==SUB_OBJECT_RIGHT_HAND)
|
|
*y+=HAND_HEIGHT;
|
|
}
|
|
void calc_sub_objects_position_fix8(Thing *p_mthing,SLONG tween,UWORD object,SLONG *x,SLONG *y,SLONG *z)
|
|
{
|
|
struct SVector temp; //max points per object?
|
|
struct Matrix33 r_matrix;
|
|
struct Matrix31 offset;
|
|
struct GameKeyFrameElement *anim_info;
|
|
struct GameKeyFrameElement *anim_info_next;
|
|
struct Matrix33 *rot_mat;
|
|
SLONG wx,wy,wz;
|
|
|
|
DrawTween *dt = p_mthing->Draw.Tweened;
|
|
|
|
#ifdef PSX
|
|
{
|
|
SLONG index1,index2;
|
|
//
|
|
// stuff added for more compression of anims
|
|
//
|
|
extern struct PrimPoint *anim_mids; //[256];
|
|
|
|
index1=dt->CurrentFrame->XYZIndex;
|
|
index2=dt->NextFrame->XYZIndex;
|
|
|
|
if(index1!=index2)
|
|
{
|
|
wx=anim_mids[index1].X+(((anim_mids[index2].X-anim_mids[index1].X)*dt->AnimTween)>>8);
|
|
wy=anim_mids[index1].Y+(((anim_mids[index2].Y-anim_mids[index1].Y)*dt->AnimTween)>>8);
|
|
wz=anim_mids[index1].Z+(((anim_mids[index2].Z-anim_mids[index1].Z)*dt->AnimTween)>>8);
|
|
|
|
}
|
|
else
|
|
{
|
|
wx=anim_mids[index1].X;
|
|
wy=anim_mids[index1].Y;
|
|
wz=anim_mids[index1].Z;
|
|
}
|
|
|
|
}
|
|
#else
|
|
wx=0;
|
|
wy=0;
|
|
wz=0;
|
|
#endif
|
|
|
|
if(p_mthing->Draw.Tweened->CurrentFrame && p_mthing->Draw.Tweened->NextFrame)
|
|
{
|
|
anim_info=&p_mthing->Draw.Tweened->CurrentFrame->FirstElement[object];
|
|
anim_info_next=&p_mthing->Draw.Tweened->NextFrame->FirstElement[object];
|
|
// anim_info_next=&p_mthing->NextAnimElements[object];
|
|
|
|
|
|
|
|
offset.M[0] = ((anim_info->OffsetX<<8)+(((anim_info_next->OffsetX-anim_info->OffsetX)*tween)>>0))>>(TWEEN_OFFSET_SHIFT+3)+wx;
|
|
offset.M[1] = ((anim_info->OffsetY<<8)+(((anim_info_next->OffsetY-anim_info->OffsetY)*tween)>>0))>>(TWEEN_OFFSET_SHIFT+3)+wy;
|
|
offset.M[2] = ((anim_info->OffsetZ<<8)+(((anim_info_next->OffsetZ-anim_info->OffsetZ)*tween)>>0))>>(TWEEN_OFFSET_SHIFT+3)+wz;
|
|
|
|
rotate_obj (
|
|
p_mthing->Draw.Tweened->Tilt,
|
|
p_mthing->Draw.Tweened->Angle,
|
|
p_mthing->Draw.Tweened->Roll,
|
|
&r_matrix
|
|
);
|
|
|
|
matrix_transformZMY((struct Matrix31*)&temp,&r_matrix, &offset);
|
|
*x=(temp.X<<3);
|
|
*y=(temp.Y<<3);
|
|
*z=(temp.Z<<3);
|
|
}
|
|
else
|
|
{
|
|
*x=0;
|
|
*y=0;
|
|
*z=0;
|
|
|
|
}
|
|
if(object==SUB_OBJECT_LEFT_FOOT || object==SUB_OBJECT_RIGHT_FOOT)
|
|
*y-=FOOT_HEIGHT<<8;
|
|
if(object==SUB_OBJECT_LEFT_HAND || object==SUB_OBJECT_RIGHT_HAND)
|
|
*y+=HAND_HEIGHT;
|
|
|
|
}
|
|
#ifndef PSX
|
|
void calc_sub_objects_position_keys(Thing *p_mthing,SLONG tween,UWORD object,SLONG *x,SLONG *y,SLONG *z,struct GameKeyFrame *frame1,struct GameKeyFrame *frame2)
|
|
{
|
|
struct SVector temp; //max points per object?
|
|
struct Matrix33 r_matrix;
|
|
struct Matrix31 offset;
|
|
struct GameKeyFrameElement *anim_info;
|
|
struct GameKeyFrameElement *anim_info_next;
|
|
struct Matrix33 *rot_mat;
|
|
SLONG wx,wy,wz;
|
|
|
|
DrawTween *dt = p_mthing->Draw.Tweened;
|
|
|
|
#ifdef PSX
|
|
{
|
|
SLONG index1,index2;
|
|
//
|
|
// stuff added for more compression of anims
|
|
//
|
|
extern struct PrimPoint *anim_mids; //[256];
|
|
|
|
index1=dt->CurrentFrame->XYZIndex;
|
|
index2=dt->NextFrame->XYZIndex;
|
|
|
|
if(index1!=index2)
|
|
{
|
|
wx=anim_mids[index1].X+(((anim_mids[index2].X-anim_mids[index1].X)*dt->AnimTween)>>8);
|
|
wy=anim_mids[index1].Y+(((anim_mids[index2].Y-anim_mids[index1].Y)*dt->AnimTween)>>8);
|
|
wz=anim_mids[index1].Z+(((anim_mids[index2].Z-anim_mids[index1].Z)*dt->AnimTween)>>8);
|
|
|
|
}
|
|
else
|
|
{
|
|
wx=anim_mids[index1].X;
|
|
wy=anim_mids[index1].Y;
|
|
wz=anim_mids[index1].Z;
|
|
}
|
|
|
|
}
|
|
#else
|
|
wx=0;
|
|
wy=0;
|
|
wz=0;
|
|
#endif
|
|
|
|
if(p_mthing->Draw.Tweened->CurrentFrame && p_mthing->Draw.Tweened->NextFrame)
|
|
{
|
|
anim_info=&frame1->FirstElement[object];
|
|
anim_info_next=&frame2->FirstElement[object];
|
|
// anim_info_next=&p_mthing->NextAnimElements[object];
|
|
|
|
|
|
|
|
offset.M[0] = ((anim_info->OffsetX+(((anim_info_next->OffsetX-anim_info->OffsetX)*tween)>>8))>>TWEEN_OFFSET_SHIFT)+wx;
|
|
offset.M[1] = ((anim_info->OffsetY+(((anim_info_next->OffsetY-anim_info->OffsetY)*tween)>>8))>>TWEEN_OFFSET_SHIFT)+wy;
|
|
offset.M[2] = ((anim_info->OffsetZ+(((anim_info_next->OffsetZ-anim_info->OffsetZ)*tween)>>8))>>TWEEN_OFFSET_SHIFT)+wz;
|
|
|
|
rotate_obj (
|
|
p_mthing->Draw.Tweened->Tilt,
|
|
p_mthing->Draw.Tweened->Angle,
|
|
p_mthing->Draw.Tweened->Roll,
|
|
&r_matrix
|
|
);
|
|
|
|
matrix_transformZMY((struct Matrix31*)&temp,&r_matrix, &offset);
|
|
*x=temp.X;//+wx;
|
|
*y=temp.Y;//+wy;
|
|
*z=temp.Z;//+wz;
|
|
}
|
|
else
|
|
{
|
|
*x=0;
|
|
*y=0;
|
|
*z=0;
|
|
|
|
}
|
|
if(object==SUB_OBJECT_LEFT_FOOT || object==SUB_OBJECT_RIGHT_FOOT)
|
|
*y-=FOOT_HEIGHT;
|
|
if(object==SUB_OBJECT_LEFT_HAND || object==SUB_OBJECT_RIGHT_HAND)
|
|
*y+=HAND_HEIGHT;
|
|
|
|
}
|
|
#endif
|
|
void calc_sub_objects_position_global(GameKeyFrame *cur_frame,GameKeyFrame *next_frame,SLONG tween,UWORD object,SLONG *x,SLONG *y,SLONG *z)
|
|
{
|
|
struct Matrix31 offset;
|
|
struct GameKeyFrameElement *anim_info;
|
|
struct GameKeyFrameElement *anim_info_next;
|
|
SLONG wx,wy,wz;
|
|
|
|
#ifdef PSX
|
|
{
|
|
SLONG index1,index2;
|
|
//
|
|
// stuff added for more compression of anims
|
|
//
|
|
extern struct PrimPoint *anim_mids; //[256];
|
|
|
|
index1=cur_frame->XYZIndex;
|
|
index2=next_frame->XYZIndex;
|
|
|
|
if(index1!=index2)
|
|
{
|
|
wx=anim_mids[index1].X+(((anim_mids[index2].X-anim_mids[index1].X)*tween)>>8);
|
|
wy=anim_mids[index1].Y+(((anim_mids[index2].Y-anim_mids[index1].Y)*tween)>>8);
|
|
wz=anim_mids[index1].Z+(((anim_mids[index2].Z-anim_mids[index1].Z)*tween)>>8);
|
|
|
|
}
|
|
else
|
|
{
|
|
wx=anim_mids[index1].X;
|
|
wy=anim_mids[index1].Y;
|
|
wz=anim_mids[index1].Z;
|
|
}
|
|
|
|
}
|
|
#else
|
|
wx=0;
|
|
wy=0;
|
|
wz=0;
|
|
#endif
|
|
|
|
if(cur_frame && next_frame)
|
|
{
|
|
anim_info=&cur_frame->FirstElement[object];
|
|
anim_info_next=&next_frame->FirstElement[object];
|
|
|
|
// anim_info_next=&p_mthing->NextAnimElements[object];
|
|
|
|
|
|
|
|
*x = (anim_info->OffsetX+(((anim_info_next->OffsetX-anim_info->OffsetX)*tween)>>8))>>TWEEN_OFFSET_SHIFT;
|
|
*y = (anim_info->OffsetY+(((anim_info_next->OffsetY-anim_info->OffsetY)*tween)>>8))>>TWEEN_OFFSET_SHIFT;
|
|
*z = (anim_info->OffsetZ+(((anim_info_next->OffsetZ-anim_info->OffsetZ)*tween)>>8))>>TWEEN_OFFSET_SHIFT;
|
|
|
|
*x+=wx;
|
|
*y+=wy;
|
|
*z+=wz;
|
|
|
|
}
|
|
else
|
|
{
|
|
*x=0;
|
|
*y=0;
|
|
*z=0;
|
|
|
|
}
|
|
if(object==SUB_OBJECT_LEFT_FOOT || object==SUB_OBJECT_RIGHT_FOOT)
|
|
*y-=FOOT_HEIGHT;
|
|
if(object==SUB_OBJECT_LEFT_HAND || object==SUB_OBJECT_RIGHT_HAND)
|
|
*y+=HAND_HEIGHT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|