// *********************************************** // CALCS.C - mathematical calculations for everything // *********************************************** // **** includes #include "useful.h" #include "global.h" #include "calcs.h" #include "mapsetup.h" #include "render.h" #include "text.h" #include "init.h" // **** private structures typedef struct { u_char height[21][21]; } HEIGHTTYPE; typedef struct { u_char info[20][20]; } COLLISIONTYPE; // **** private function prototypes long CalculateHeightBetweenTwoPoints(u_long, u_long, u_long); // **** return height at any point of map long CalculateHeight(u_long tX, u_long tZ) { u_long tCornerHeight[4]; long tHeight1, tHeight2; u_long tCellX = tX>>9, tCellZ = 19-(tZ>>9); HEIGHTTYPE *start = (HEIGHTTYPE *) CurrentMap->heightAddr; // get heights at all fours corners tCornerHeight[0] = (start->height[20-tCellZ][tCellX]) << 4; tCornerHeight[1] = (start->height[20-tCellZ][tCellX+1]) << 4; tCornerHeight[2] = (start->height[19-tCellZ][tCellX]) << 4; tCornerHeight[3] = (start->height[19-tCellZ][tCellX+1]) << 4; tHeight1 = CalculateHeightBetweenTwoPoints(tCornerHeight[0], tCornerHeight[1], tX%512); tHeight2 = CalculateHeightBetweenTwoPoints(tCornerHeight[2], tCornerHeight[3], tX%512); return -CalculateHeightBetweenTwoPoints(tHeight2, tHeight1, tZ%512); } // **** return height between two points long CalculateHeightBetweenTwoPoints(u_long tHeight1, u_long tHeight2, u_long tOffset) { // value of 0 to 511 (incl) // when 0 return = tHeight1 // when 511 return = tHeight2 // when between its a linear sliding scale u_long tHeightMultiplier = (tHeight1 * (511-tOffset)) + (tHeight2 * tOffset); return (long) (tHeightMultiplier >>9); } // **** calculate camera position and point at player void CalculateCamera(u_long mode, GsRVIEW2* tView, u_char tCharNum) { static long oldLookat[3] = {(10*512)<<8, 0, (10*512)<<8}; static long oldLookfrom[3] = {(10*512)<<8, -(50000<<8), (10*512)<<8}; u_long counter; u_long tX = CHARINFO[tCharNum].charModel.Object_Coord.coord.t[0] >> 9; u_long tY = CHARINFO[tCharNum].charModel.Object_Coord.coord.t[2] >> 9; long offsetLookat[3], offsetLookfrom[3]; switch(mode) { // use a static panning camera case 0: { offsetLookat[0] = (CHARINFO[tCharNum].charModel.Object_Coord.coord.t[0]<<8) - oldLookat[0]; offsetLookat[1] = ((CHARINFO[tCharNum].charModel.Object_Coord.coord.t[1]-400)<<8) - oldLookat[1]; offsetLookat[2] = (CHARINFO[tCharNum].charModel.Object_Coord.coord.t[2]<<8) - oldLookat[2]; for (counter=0; countercameras.numCameras; counter++) { if (!((tX < CurrentMap->cameras.camera[counter].x0) || (tX > CurrentMap->cameras.camera[counter].x1) || (tY < CurrentMap->cameras.camera[counter].y0) || (tY > CurrentMap->cameras.camera[counter].y1))) { offsetLookfrom[0] = (CurrentMap->cameras.camera[counter].xPos<<8) - oldLookfrom[0]; offsetLookfrom[1] = (CurrentMap->cameras.camera[counter].yPos<<8) - oldLookfrom[1]; offsetLookfrom[2] = (CurrentMap->cameras.camera[counter].zPos<<8) - oldLookfrom[2]; // FntPrint("panning camera number = %d\n", counter); counter = 10; } } tView->vrx = (oldLookat[0] += (offsetLookat[0]>>3)) >> 8; tView->vry = (oldLookat[1] += (offsetLookat[1]>>3)) >> 8; tView->vrz = (oldLookat[2] += (offsetLookat[2]>>3)) >> 8; tView->vpx = (oldLookfrom[0] += (offsetLookfrom[0]>>5)) >> 8; tView->vpy = (oldLookfrom[1] += (offsetLookfrom[1]>>5)) >> 8; tView->vpz = (oldLookfrom[2] += (offsetLookfrom[2]>>5)) >> 8; break; } // use a tracker camera case 1: { long tOffset[3]; Calculate3dOffset(&CHARINFO[tCharNum].charVector, 0, -500, 500, &tOffset[0]); offsetLookat[0] = ((CHARINFO[tCharNum].charModel.Object_Coord.coord.t[0]+tOffset[0])<<8) - oldLookat[0]; offsetLookat[1] = ((CHARINFO[tCharNum].charModel.Object_Coord.coord.t[1]+tOffset[1])<<8) - oldLookat[1]; offsetLookat[2] = ((CHARINFO[tCharNum].charModel.Object_Coord.coord.t[2]+tOffset[2])<<8) - oldLookat[2]; Calculate3dOffset(&CHARINFO[tCharNum].charVector, 0, -3000, -300, &tOffset[0]); offsetLookfrom[0] = ((CHARINFO[tCharNum].charModel.Object_Coord.coord.t[0]+tOffset[0])<<8) - oldLookfrom[0]; offsetLookfrom[1] = ((CHARINFO[tCharNum].charModel.Object_Coord.coord.t[1]+tOffset[1])<<8) - oldLookfrom[1]; offsetLookfrom[2] = ((CHARINFO[tCharNum].charModel.Object_Coord.coord.t[2]+tOffset[2])<<8) - oldLookfrom[2]; tView->vrx = (oldLookat[0] += (offsetLookat[0]>>2)) >> 8; tView->vry = (oldLookat[1] += (offsetLookat[1]>>2)) >> 8; tView->vrz = (oldLookat[2] += (offsetLookat[2]>>2)) >> 8; tView->vpx = (oldLookfrom[0] += (offsetLookfrom[0]>>2)) >> 8; tView->vpy = (oldLookfrom[1] += (offsetLookfrom[1]>>2)) >> 8; tView->vpz = (oldLookfrom[2] += (offsetLookfrom[2]>>2)) >> 8; // FntPrint("tracker camera\n"); break; } // use an overhead camera to view whole scene case 2: { offsetLookat[0] = ((10*512)<<8) - oldLookat[0]; offsetLookat[1] = ((-2000)<<8) - oldLookat[1]; offsetLookat[2] = ((10*512)<<8) - oldLookat[2]; offsetLookfrom[0] = ((15*512)<<8) - oldLookfrom[0]; offsetLookfrom[1] = ((-13000)<<8) - oldLookfrom[1]; offsetLookfrom[2] = ((-12*512)<<8) - oldLookfrom[2]; tView->vrx = (oldLookat[0] += (offsetLookat[0]>>4)) >> 8; tView->vry = (oldLookat[1] += (offsetLookat[1]>>4)) >> 8; tView->vrz = (oldLookat[2] += (offsetLookat[2]>>4)) >> 8; tView->vpx = (oldLookfrom[0] += (offsetLookfrom[0]>>4)) >> 8; tView->vpy = (oldLookfrom[1] += (offsetLookfrom[1]>>4)) >> 8; tView->vpz = (oldLookfrom[2] += (offsetLookfrom[2]>>4)) >> 8; // FntPrint("overhead camera\n"); break; } } } // **** find a point based on objects orientation void Calculate3dOffset(SVECTOR *tOrientation, long tX, long tY, long tZ, long* tArray) { MATRIX tMatrix; SVECTOR tOffset, tDirectionResult; tOffset.vx = tX; tOffset.vy = tY; tOffset.vz = tZ; RotMatrix(tOrientation, &tMatrix); ApplyMatrixSV(&tMatrix, &tOffset, &tDirectionResult); tArray[0] = tDirectionResult.vx; tArray[1] = tDirectionResult.vy; tArray[2] = tDirectionResult.vz; } // **** read from the collision map u_long ReadCollide(u_long tX, u_long tZ) { u_long returnValue = 0; static u_char tByte; static u_char tPos; tByte = tX>>3; tPos = tX%8; if (BitCheck(&CurrentMap->collide[tByte][tZ], 1<> 4; long tCellZ = CHARINFO[tCharNum].scaleZ >> 4; long tDeliberateVector[3]; long tAccidentalVector[3]; long tSlope[4]; long tTempX, tTempZ; // printf("snake "); // FntPrint("x,y = %d,%d\n", tCellX/512, tCellZ/512); // deliberate vector is what the character WANTS to move Calculate3dOffset(&CHARINFO[tCharNum].charVector, tSide<<4, 0, tForward<<4, &tDeliberateVector[0]); // printf("snake "); // accidental vector is how the character moves according to outside influences, ie sloping ground // calculate height of ground in four points around character tSlope[0] = CalculateHeight(tCellX, tCellZ + 50); tSlope[1] = CalculateHeight(tCellX + 50, tCellZ); tSlope[2] = CalculateHeight(tCellX, tCellZ - 50); tSlope[3] = CalculateHeight(tCellX - 50, tCellZ); // tSlope[0] = tSlope[1] = tSlope[2] = tSlope[3] = -256; // printf("snake "); tAccidentalVector[0] = (tSlope[1] - tSlope[3]); tAccidentalVector[2] = (tSlope[0] - tSlope[2]); if (abs(tAccidentalVector[0]) < 32) tAccidentalVector[0] = 0; if (abs(tAccidentalVector[2]) < 32) tAccidentalVector[2] = 0; // printf("snake "); // check what will happen if the player moves according to vector // check against solid objects from the tHeight list CHARINFO[tCharNum].momentumX += tAccidentalVector[0]; CHARINFO[tCharNum].momentumZ += tAccidentalVector[2]; tTempX = CHARINFO[tCharNum].scaleX + CHARINFO[tCharNum].momentumX + tDeliberateVector[0]*2; tTempZ = CHARINFO[tCharNum].scaleZ + CHARINFO[tCharNum].momentumZ + tDeliberateVector[2]*2; // printf("snake "); if (ReadCollide( (tTempX >> (4+9-1)), ((CHARINFO[tCharNum].scaleZ) >> (4+9-1)))) CHARINFO[tCharNum].momentumX = tDeliberateVector[0] = 0; if (ReadCollide( ((CHARINFO[tCharNum].scaleX) >> (4+9-1)), (tTempZ >> (4+9-1)))) CHARINFO[tCharNum].momentumZ = tDeliberateVector[2] = 0; for (counter=0; counter<21; counter++) { if (!((counter == tCharNum) || (CHARINFO[counter].state == 0))) { if ((abs(-tTempX + CHARINFO[counter].scaleX) < (150<<4)) && (abs(-tTempZ + CHARINFO[counter].scaleZ) < (150<<4))) { CHARINFO[tCharNum].momentumX = tDeliberateVector[0] = 0; CHARINFO[tCharNum].momentumZ = tDeliberateVector[2] = 0; if ((tCharNum != 0) && (counter!=0)) RotateModel(&CHARINFO[tCharNum].charModel, &CHARINFO[tCharNum].charVector, 0, rand()%2*800-400, 0); if ((CHARINFO[tCharNum].type == 26) && (counter == 0)) PLAYERHEALTH--; counter = 22; } } } // printf("snake "); CHARINFO[tCharNum].scaleX += CHARINFO[tCharNum].momentumX + tDeliberateVector[0]; CHARINFO[tCharNum].scaleZ += CHARINFO[tCharNum].momentumZ + tDeliberateVector[2]; // printf("snake "); CHARINFO[tCharNum].momentumX -= (CHARINFO[tCharNum].momentumX >> 3); CHARINFO[tCharNum].momentumZ -= (CHARINFO[tCharNum].momentumZ >> 3); if ((abs(CHARINFO[tCharNum].momentumX) < 32) && (abs(CHARINFO[tCharNum].momentumZ) < 32)) CHARINFO[tCharNum].momentumX = CHARINFO[tCharNum].momentumZ = 0; if (tCharNum == 0) { for (counter=0; counterexits.numExits; counter++) { if ( (((CHARINFO[0].scaleX>>(4+9)) >= CurrentMap->exits.exit[counter].x0) && ((CHARINFO[0].scaleZ>>(4+9)) >= CurrentMap->exits.exit[counter].y0) && ((CHARINFO[0].scaleX>>(4+9)) <= CurrentMap->exits.exit[counter].x1) && ((CHARINFO[0].scaleZ>>(4+9)) <= CurrentMap->exits.exit[counter].y1))) { long counter2; u_char tEntrance = CurrentMap->exits.exit[counter].entranceTo; // this bit recreates the renderworld function, but fades screen to white + moves camera for (counter2=15; counter2<256; counter2+=20) { CalculateCamera(2, &ViewPoint, tCharNum); GsSetRefView2(&ViewPoint); RenderProgram(counter2); } DrawSync(0); GsSwapDispBuff(); VSync(0); InitCurrentMap(CurrentMap->exits.exit[counter].mapTo, GROUND_MEM); if (MusicPlaying != CurrentMap->music) { stop_sound(SONG[MusicPlaying-1]); MusicPlaying = CurrentMap->music; play_sound(SONG[MusicPlaying-1]); } CHARINFO[0].scaleX = (CurrentMap->entrances[tEntrance].xPos * 512 + 256) << 4; CHARINFO[0].scaleZ = (CurrentMap->entrances[tEntrance].zPos * 512 + 256) << 4; CHARINFO[0].charVector.vy = (CurrentMap->entrances[tEntrance].direction)*1024; CHARINFO[0].momentumX = CHARINFO[0].momentumZ = 0; tCellX = CHARINFO[0].charModel.Object_Coord.coord.t[0] = CHARINFO[0].scaleX>>4; tCellZ = CHARINFO[0].charModel.Object_Coord.coord.t[2] = CHARINFO[0].scaleZ>>4; CHARINFO[0].charModel.Object_Coord.coord.t[1] = CalculateHeight(CHARINFO[0].scaleX>>4, CHARINFO[0].scaleZ>>4); RotateModel(&CHARINFO[0].charModel, &CHARINFO[tCharNum].charVector, 0, 0, 0); for (counter2=255; counter2>-1; counter2-=20) { CalculateCamera(0, &ViewPoint, tCharNum); GsSetRefView2(&ViewPoint); RenderProgram(counter2); } CameraMode = 0; counter = 100; } } } // update characters position correctly CHARINFO[tCharNum].charModel.Object_Coord.coord.t[0] = CHARINFO[tCharNum].scaleX>>4; CHARINFO[tCharNum].charModel.Object_Coord.coord.t[1] = CalculateHeight(tCellX, tCellZ); // FntPrint("y = %d\n", CalculateHeight(tCellX, tCellZ)); CHARINFO[tCharNum].charModel.Object_Coord.coord.t[2] = CHARINFO[tCharNum].scaleZ>>4; CHARINFO[tCharNum].charModel.Object_Coord.flg = 0; // FntPrint("x,y (%d,%d)\n",CHARINFO[tCharNum].scaleX, CHARINFO[tCharNum].scaleZ); return 0; } u_long CheckEnemyRotation(u_long tChar1, u_long tChar2) { u_long tReturnValue = 0; long tReturnPos[3]; long tDistance[3]; long tTemp1 = CHARINFO[tChar1].charModel.Object_Coord.coord.t[0] - CHARINFO[tChar2].charModel.Object_Coord.coord.t[0]; long tTemp2 = CHARINFO[tChar1].charModel.Object_Coord.coord.t[2] - CHARINFO[tChar2].charModel.Object_Coord.coord.t[2]; long tTemp3, tTemp4; Calculate3dOffset(&CHARINFO[tChar1].charVector, 0, 0, 57, &tReturnPos[0]); tTemp3 = (tTemp1 + tReturnPos[0]); tTemp4 = (tTemp2 + tReturnPos[2]); tDistance[0] = tTemp3 * tTemp3 + tTemp4 * tTemp4; Calculate3dOffset(&CHARINFO[tChar1].charVector, -32, 0, 48, &tReturnPos[0]); tTemp3 = (tTemp1 + tReturnPos[0]); tTemp4 = (tTemp2 + tReturnPos[2]); tDistance[1] = tTemp3 * tTemp3 + tTemp4 * tTemp4; Calculate3dOffset(&CHARINFO[tChar1].charVector, 32, 0, 48, &tReturnPos[0]); tTemp3 = (tTemp1 + tReturnPos[0]); tTemp4 = (tTemp2 + tReturnPos[2]); tDistance[2] = tTemp3 * tTemp3 + tTemp4 * tTemp4; if (!((tDistance[0] < tDistance[1]) && (tDistance[0] < tDistance[2]))) { if (tDistance[1] < tDistance[2]) tReturnValue = 1; else tReturnValue = 2; } return tReturnValue; }