/* This file is part of Warzone 2100. Copyright (C) 1999-2004 Eidos Interactive Copyright (C) 2005-2007 Warzone Resurrection Project Warzone 2100 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Warzone 2100 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Warzone 2100; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "lib/framework/frame.h" #include "lib/ivis_common/piedef.h" #include "lib/ivis_common/rendmode.h" // FIXME Direct iVis implementation include! #include "lib/ivis_opengl/piematrix.h" #include "lib/ivis_common/piepalette.h" #include "lib/ivis_common/piestate.h" #include "objects.h" #include "display3d.h" #include "map.h" // FIXME Direct iVis implementation include! #include "lib/ivis_opengl/screen.h" #include "component.h" #include "radar.h" #include "mapdisplay.h" #include "hci.h" #include "geometry.h" #include "intimage.h" #include "loop.h" #include "warcam.h" #include "display.h" #include "lib/gamelib/gtime.h" #include "mission.h" #include "multiplay.h" #include "lib/ivis_common/piefunc.h" #define HIT_NOTIFICATION (GAME_TICKS_PER_SEC*2) //#define CHECKBUFFER // Do assertions for buffer overun\underun #define ALPHABLEND_RADAR // Define this to do semi transparency on PSX radar. #define BLEND_RATE 0 // Semi-transparency rate for PSX radar. #define RADAR_3DFX_TPAGEID 31 #define RADAR_3DFX_TU 0 #define RADAR_3DFX_TV 0 #define RADAR_DRAW_VIEW_BOX // If defined then draw a box to show the viewing area. //#define RADAR_TRIANGLE_TOPLEFT // If defined then put direction triangle in top left // otherwise put in view box and scale it by zoom level. #ifdef RADAR_TRIANGLE_TOPLEFT #define RADAR_TRIANGLE_SIZE 16 #define RADAR_TRIANGLE_X (RADTLX+2+RADAR_TRIANGLE_SIZE/2) #define RADAR_TRIANGLE_Y (RADTLY+2+RADAR_TRIANGLE_SIZE/2) #else #define RADAR_TRIANGLE_SIZE 8 #endif #define RADAR_TRIANGLE_HEIGHT RADAR_TRIANGLE_SIZE #define RADAR_TRIANGLE_WIDTH (RADAR_TRIANGLE_SIZE/2) static UDWORD sweep; static UBYTE colBlack, colWhite, colRadarBorder, colGrey, colRadarEnemy, colRadarAlly, colRadarMe; BOOL bDrawRadarTerrain = TRUE; //radar terrain on/off BOOL bEnemyAllyRadarColor = FALSE; //enemy/ally radar color // colours for each clan on the radar map. #define CAMPAIGNS 3 static UDWORD clanColours[CAMPAIGNS][MAX_PLAYERS] = { {81,243,231,1,182,187,207,195}, {81,243,231,1,182,187,207,195}, {81,243,231,1,182,187,207,195}, }; static UDWORD flashColours[CAMPAIGNS][MAX_PLAYERS] = { {165,165,165,165,255,165,165,165}, // everything flashes red when attacked except red - it goes white! {165,165,165,165,255,165,165,165}, {165,165,165,165,255,165,165,165}, }; static UBYTE tileColours[NUM_TILES]; static BOOL radarStrobe; static UDWORD radarStrobeX,radarStrobeY,radarStrobeIndex,sweepStrobeIndex; static UBYTE *radarBuffer; static SDWORD RadarScrollX; static SDWORD RadarScrollY; static SDWORD RadarWidth; static SDWORD RadarHeight; static SDWORD RadVisWidth; static SDWORD RadVisHeight; static SDWORD RadarOffsetX; static SDWORD RadarOffsetY; static BOOL RadarRedraw; static UWORD RadarZoom; static IMAGEDEF RadarImage; static SDWORD RadarMapOriginX; static SDWORD RadarMapOriginY; static SDWORD RadarMapWidth; static SDWORD RadarMapHeight; static void CalcRadarPixelSize(UWORD *SizeH,UWORD *SizeV); static void CalcRadarScroll(UWORD boxSizeH,UWORD boxSizeV); static void ClearRadar(UBYTE *screen,UDWORD Modulus,UWORD boxSizeH,UWORD boxSizeV); static void DrawRadarTiles(UBYTE *screen,UDWORD Modulus,UWORD boxSizeH,UWORD boxSizeV); static void DrawRadarObjects(UBYTE *screen,UDWORD Modulus,UWORD boxSizeH,UWORD boxSizeV); static void DrawRadarExtras(UWORD boxSizeH,UWORD boxSizeV); static void UpdateRadar(UWORD boxSizeH,UWORD boxSizeV); void radarInitVars(void) { sweep = 0; radarStrobe = TRUE; RadarScrollX = 0; RadarScrollY = 0; RadarWidth = RADWIDTH; RadarHeight = RADHEIGHT; RadarRedraw = TRUE; RadarOffsetX = 0; RadarOffsetY = 0; RadarZoom = 0; } //called for when a new mission is started void resetRadarRedraw(void) { RadarRedraw = TRUE; } BOOL InitRadar(void) { radarBuffer = MALLOC(RADWIDTH*RADHEIGHT); if(radarBuffer==NULL) return FALSE; memset(radarBuffer,0,RADWIDTH*RADHEIGHT); RadarImage.TPageID = RADAR_3DFX_TPAGEID; // 3dfx only,radar is hard coded to texture page 31 - sort this out? RadarImage.Tu = 0; RadarImage.Tv = 0; RadarImage.Width = (UWORD)RadarWidth; RadarImage.Height = (UWORD)RadarHeight; RadarImage.XOffset = 0; RadarImage.YOffset = 0; colRadarBorder = COL_GREY; colBlack = 0; colGrey = COL_DARKGREY; colWhite = COL_WHITE; //for enemy/ally radar color mode colRadarAlly = COL_YELLOW; colRadarEnemy = COL_LIGHTRED; colRadarMe = COL_WHITE; pie_InitRadar(); return TRUE; } BOOL ShutdownRadar(void) { pie_ShutdownRadar(); FREE(radarBuffer); return TRUE; } void SetRadarZoom(UWORD ZoomLevel) { ASSERT( ZoomLevel <= MAX_RADARZOOM,"SetRadarZoom: Max radar zoom exceeded" ); if(ZoomLevel != RadarZoom) { RadarZoom = ZoomLevel; RadarRedraw = TRUE; } } UDWORD GetRadarZoom(void) { return RadarZoom; } // Given a position within the radar, return a world coordinate. // void CalcRadarPosition(UDWORD mX,UDWORD mY,UDWORD *PosX,UDWORD *PosY) { UWORD boxSizeH,boxSizeV; SDWORD sPosX, sPosY; SDWORD Xoffset,Yoffset; CalcRadarPixelSize(&boxSizeH,&boxSizeV); CalcRadarScroll(boxSizeH,boxSizeV); //*PosX = ((mX-RADTLX-RadarOffsetX)/boxSizeH)+RadarScrollX+RadarMapOriginX; //*PosY = ((mY-RADTLY-RadarOffsetY)/boxSizeV)+RadarScrollY+RadarMapOriginY; // Calculate where on the radar we clicked Xoffset=mX-RADTLX-RadarOffsetX; // we need to check for negative values (previously this meant that sPosX/Y were becoming huge) if (Xoffset<0) Xoffset=0; Yoffset=mY-RADTLY-RadarOffsetY; if (Yoffset<0) Yoffset=0; sPosX = ((Xoffset)/boxSizeH)+RadarScrollX+RadarMapOriginX; sPosY = ((Yoffset)/boxSizeV)+RadarScrollY+RadarMapOriginY; if (sPosX < scrollMinX) { sPosX = scrollMinX; } else if (sPosX > scrollMaxX) { sPosX = scrollMaxX; } if (sPosY < scrollMinY) { sPosY = scrollMinY; } else if (sPosY > scrollMaxY) { sPosY = scrollMaxY; } *PosX = (UDWORD)sPosX; *PosY = (UDWORD)sPosY; } //given a world pos, return a radar pos.. // ajl did this, so don't blame paul when it barfs... void worldPosToRadarPos(UDWORD wX,UDWORD wY,SDWORD *rX, SDWORD *rY) { SDWORD x,y; UWORD boxSizeH,boxSizeV; CalcRadarPixelSize(&boxSizeH,&boxSizeV); CalcRadarScroll(boxSizeH,boxSizeV); x= ((wX-RadarScrollX-RadarMapOriginX) *boxSizeH)+RadarOffsetX; y= ((wY-RadarScrollY-RadarMapOriginY) *boxSizeV)+RadarOffsetY; *rX = x; *rY = y; } // Kick of a new radar strobe. // void SetRadarStrobe(UDWORD x,UDWORD y) { radarStrobe = TRUE; radarStrobeX = x; radarStrobeY = y; radarStrobeIndex = 0; } // Calculate the radar pixel sizes. // static void CalcRadarPixelSize(UWORD *SizeH,UWORD *SizeV) { UWORD Size = (UWORD)(1< boxSizeV) { // boxSizeV = boxSizeH; // } else { // boxSizeH = boxSizeV; // } // // *SizeH = boxSizeH; // *SizeV = boxSizeV; //#endif } // Calculate the radar scroll positions from the current player position. // static void CalcRadarScroll(UWORD boxSizeH,UWORD boxSizeV) { SDWORD viewX,viewY; SDWORD PrevRadarOffsetX = RadarOffsetX; SDWORD PrevRadarOffsetY = RadarOffsetY; SDWORD PrevRadarScrollX = RadarScrollX; SDWORD PrevRadarScrollY = RadarScrollY; SDWORD PrevRadarMapOriginX = RadarMapOriginX; SDWORD PrevRadarMapOriginY = RadarMapOriginY; SDWORD PrevRadarMapWidth = RadarMapWidth; SDWORD PrevRadarMapHeight = RadarMapHeight; SDWORD BorderX; SDWORD BorderY; RadarMapOriginX = scrollMinX; RadarMapOriginY = scrollMinY; RadarMapWidth = scrollMaxX- scrollMinX; RadarMapHeight = scrollMaxY - scrollMinY; RadVisWidth = RadarWidth; RadVisHeight = RadarHeight; if(RadarMapWidth < RadVisWidth/boxSizeH) { RadVisWidth = RadarMapWidth*boxSizeH; RadarOffsetX = (RadarWidth-RadVisWidth)/2; } else { RadarOffsetX = 0; } if(RadarMapHeight < RadVisHeight/boxSizeV) { RadVisHeight = RadarMapHeight*boxSizeV; RadarOffsetY = (RadarHeight-RadVisHeight)/2; } else { RadarOffsetY = 0; } BorderX = (RadVisWidth - visibleXTiles*boxSizeH) / 2; BorderY = (RadVisHeight - visibleYTiles*boxSizeV) / 2; BorderX /= boxSizeH; BorderY /= boxSizeV; if(BorderX > 16) { BorderX = 16; } else if(BorderX < 0) { BorderX = 0; } if(BorderY > 16) { BorderY = 16; } else if(BorderY < 0) { BorderY = 0; } viewX = ((player.p.x/TILE_UNITS)-RadarScrollX-RadarMapOriginX); viewY = ((player.p.z/TILE_UNITS)-RadarScrollY-RadarMapOriginY); if(viewX < BorderX) { RadarScrollX += viewX-BorderX; } viewX += visibleXTiles; if(viewX > (RadVisWidth/boxSizeH)-BorderX) { RadarScrollX += viewX-(RadVisWidth/boxSizeH)+BorderX; } if(viewY < BorderY) { RadarScrollY += viewY-BorderY; } viewY += visibleYTiles; if(viewY > (RadVisHeight/boxSizeV)-BorderY) { RadarScrollY += viewY-(RadVisHeight/boxSizeV)+BorderY; } if(RadarScrollX < 0) { RadarScrollX = 0; } else if(RadarScrollX > RadarMapWidth-(RadVisWidth/boxSizeH)) { RadarScrollX = RadarMapWidth-(RadVisWidth/boxSizeH); } if(RadarScrollY < 0) { RadarScrollY = 0; } else if(RadarScrollY > RadarMapHeight-(RadVisHeight/boxSizeV)) { RadarScrollY = RadarMapHeight-(RadVisHeight/boxSizeV); } if( (PrevRadarOffsetX != RadarOffsetX) || (PrevRadarOffsetY != RadarOffsetY) || (PrevRadarScrollX != RadarScrollX) || (PrevRadarScrollY != RadarScrollY) || (PrevRadarMapOriginX != RadarMapOriginX) || (PrevRadarMapOriginY != RadarMapOriginY) || (PrevRadarMapWidth != RadarMapWidth) || (PrevRadarMapHeight != RadarMapHeight) ) { RadarRedraw = TRUE; } } void drawRadar(void) { UWORD boxSizeH,boxSizeV; #ifdef TESTRADAR godMode = TRUE; scrollMinX = 0; scrollMinY = 0; scrollMaxX = scrollMinX+191; scrollMaxY = scrollMinY+127; #endif CalcRadarPixelSize(&boxSizeH,&boxSizeV); CalcRadarScroll(boxSizeH,boxSizeV); if(RadarRedraw) { if((RadVisWidth != RadarWidth) || (RadVisHeight != RadarHeight)) { ClearRadar(radarBuffer,RADWIDTH,boxSizeH,boxSizeV); } } DrawRadarTiles(radarBuffer,RADWIDTH,boxSizeH,boxSizeV); DrawRadarObjects(radarBuffer,RADWIDTH,boxSizeH,boxSizeV); pie_DownLoadRadar(radarBuffer,RADAR_3DFX_TPAGEID); iV_TransBoxFill( RADTLX,RADTLY, RADTLX + RADWIDTH, RADTLY + RADHEIGHT); pie_RenderRadar(&RadarImage,radarBuffer,RadarWidth,RADTLX,RADTLY); DrawRadarExtras(boxSizeH,boxSizeV); UpdateRadar(boxSizeH,boxSizeV); RadarRedraw = FALSE; } void downloadAtStartOfFrame( void ) { pie_DownLoadRadar(radarBuffer,RADAR_3DFX_TPAGEID); } static void UpdateRadar(UWORD boxSizeH,UWORD boxSizeV) { if(!gamePaused()) { sweep += boxSizeV; } if(sweep >= (UDWORD)RadarHeight) { sweep = 0; } if(!gamePaused()) { if(sweepStrobeIndex++>=BOX_PULSE_SIZE) { sweepStrobeIndex = 0; } } } // Clear the radar buffer. // static void ClearRadar(UBYTE *screen,UDWORD Modulus,UWORD boxSizeH,UWORD boxSizeV) { SDWORD i,j; UBYTE *Scr,*WScr; SDWORD RadWidth,RadHeight; RadWidth = RadarWidth; RadHeight = RadarHeight; Scr = screen; for(i=0; i= VisHeight) ){ return; } EndY = 1; Scr +=SweepPos*Modulus; psTile += (SweepPos/SizeV)*mapWidth; } if(SizeH==1) { for (i=0; i= radarBuffer , "WScr Onderflow" ); ASSERT( ((UDWORD)WScr) < ((UDWORD)radarBuffer)+RADWIDTH*RADHEIGHT , "WScr Overrun" ); #endif if ( TEST_TILE_VISIBLE(selectedPlayer,WTile) OR godMode) { if (bDrawRadarTerrain) { //draw radar terrain on/off feature int i = tileColours[(WTile->texture & TILE_NUMMASK)] * iV_PALETTE_SHADE_LEVEL; int j = WTile->illumination >> ShadeDiv; *WScr = iV_SHADE_TABLE[i + j]; } else { *WScr = colBlack; } } else { *WScr = colBlack; } /* Next pixel, next tile */ WScr++; WTile++; } Scr += Modulus; psTile += mapWidth; } } else { for (i=0; itexture & TILE_NUMMASK)]; Val = iV_SHADE_TABLE[(Val * iV_PALETTE_SHADE_LEVEL+ (WTile->illumination >> ShadeDiv))]; Ptr = Scr + j + i*Modulus; for(c=0; c= (UDWORD)radarBuffer , "WPtr Onderflow" ); ASSERT( ((UDWORD)WPtr) < ((UDWORD)radarBuffer)+RADWIDTH*RADHEIGHT , "WPtr Overrun" ); #endif if (bDrawRadarTerrain) { //radar terrain *WPtr = Val; } else { *WPtr = colBlack; } WPtr++; } Ptr += Modulus; } } else { Ptr = Scr + j + i*Modulus; for(c=0; c= (UDWORD)radarBuffer , "WPtr Onderflow" ); ASSERT( ((UDWORD)WPtr) < ((UDWORD)radarBuffer)+RADWIDTH*RADHEIGHT , "WPtr Overrun" ); #endif *WPtr = colBlack;//colGrey; WPtr++; } Ptr += Modulus; } } WTile++; } psTile += mapWidth; } } } // Draw the droids and structure positions on the radar. // static void DrawRadarObjects(UBYTE *screen,UDWORD Modulus,UWORD boxSizeH,UWORD boxSizeV) { SDWORD c,d; UBYTE clan; SDWORD x = 0, y = 0; DROID *psDroid; STRUCTURE *psStruct; PROXIMITY_DISPLAY *psProxDisp; VIEW_PROXIMITY *psViewProx; UBYTE *Ptr,*WPtr; SDWORD SizeH,SizeV; SDWORD bw,bh; SDWORD SSizeH,SSizeV; SDWORD SweepPos; SDWORD VisWidth; SDWORD VisHeight; SDWORD OffsetX; SDWORD OffsetY; UBYTE playerCol,col; UBYTE flashCol; UBYTE camNum; SizeH = boxSizeH; SizeV = boxSizeV; VisWidth = RadVisWidth; VisHeight = RadVisHeight; // SweepPos = sweep - RadarOffsetY; OffsetX = RadarOffsetX; OffsetY = RadarOffsetY; SweepPos = sweep - RadarOffsetY; if( (SweepPos < 0) || (SweepPos >= RadVisHeight) ){ return; } camNum = getCampaignNumber()-1; /* Show droids on map - go through all players */ for(clan = 0; clan < MAX_PLAYERS; clan++) { //draw enemies in red, allies in yellow, if bEnemyAllyRadarColor is TRUE if (bEnemyAllyRadarColor) { if (clan == selectedPlayer) { playerCol = colRadarMe; // grey } else { //enemy or ally (red or yellow) playerCol = (aiCheckAlliances(selectedPlayer, clan) ? colRadarAlly : colRadarEnemy); } } else { //original 8-color mode playerCol = clanColours[camNum][getPlayerColour(clan)]; } flashCol = flashColours[camNum][getPlayerColour(clan)]; /* Go through all droids */ for(psDroid = apsDroidLists[clan]; psDroid != NULL; psDroid = psDroid->psNext) { if(psDroid->visible[selectedPlayer] OR godMode OR (bMultiPlayer && game.type == TEAMPLAY && aiCheckAlliances(selectedPlayer,psDroid->player)) ) { x=(psDroid->x/TILE_UNITS)-RadarScrollX; y=(psDroid->y/TILE_UNITS)-RadarScrollY; x -= RadarMapOriginX; y -= RadarMapOriginY; x *= boxSizeH; y *= boxSizeV; if(TRUE || (RadarRedraw)) { if((x < VisWidth) && (y < VisHeight) && (x >= 0) && (y >= 0)) { Ptr = screen + x + y*Modulus + OffsetX + OffsetY*Modulus; // if((clan == selectedPlayer) AND (gameTime-psDroid->timeLastHit < HIT_NOTIFICATION)) { /* if(gameTime%250<125) { col = playerCol; } else { col = 165;//COL_RED; } */ col = flashCol; } else { col = playerCol; } for(c=0; c= (UDWORD)radarBuffer , "WPtr Onderflow" ); ASSERT( ((UDWORD)WPtr) < ((UDWORD)radarBuffer)+RADWIDTH*RADHEIGHT , "WPtr Overrun" ); #endif *WPtr = col; WPtr++; } Ptr += Modulus; } } } } } } /* Do the same for structures */ for(clan = 0; clan < MAX_PLAYERS; clan++) { //draw enemies in red, allies in yellow, if bEnemyAllyRadarColor is TRUE if (bEnemyAllyRadarColor) { if (clan == selectedPlayer) { playerCol = colRadarMe; //grey } else { //enemy or ally (red or yellow) playerCol = (aiCheckAlliances(selectedPlayer,clan) ? colRadarAlly: colRadarEnemy); } } else { //original 8-color mode playerCol = clanColours[camNum][getPlayerColour(clan)]; } flashCol = flashColours[camNum][getPlayerColour(clan)]; /* Go through all structures */ for(psStruct = apsStructLists[clan]; psStruct != NULL; psStruct = psStruct->psNext) { if(psStruct->visible[selectedPlayer] OR godMode OR (bMultiPlayer && game.type == TEAMPLAY && aiCheckAlliances(selectedPlayer,psStruct->player)) ) { x=(psStruct->x/TILE_UNITS)-RadarScrollX; y=(psStruct->y/TILE_UNITS)-RadarScrollY; x -= RadarMapOriginX; y -= RadarMapOriginY; x *= boxSizeH; y *= boxSizeV; // Get structures tile size. bw = (UWORD)psStruct->pStructureType->baseWidth; bh = (UWORD)psStruct->pStructureType->baseBreadth; // Need to offset for the structures top left corner. x -= bw >> 1; y -= bh >> 1; x = x&(~(boxSizeH-1)); y = y&(~(boxSizeV-1)); // if( ((y >= sweep) && (y <= sweep+(bh*boxSizeV))) || (RadarRedraw) ) { SSizeH = (SWORD)boxSizeH*bh; SSizeV = (SWORD)boxSizeV*bw; // Clip the structure box. if(x < 0) { SSizeH += x; x = 0; } if(y < 0) { SSizeV += y; y=0; } if(x+SSizeH > VisWidth) { SSizeH -= (x+SSizeH) - VisWidth; } if(y+SSizeV > VisHeight) { SSizeV -= (y+SSizeV) - VisHeight; } // And draw it. if((SSizeV > 0) && (SSizeH > 0)) { Ptr = screen + x + y*Modulus + OffsetX + OffsetY*Modulus; if((clan == selectedPlayer) AND (gameTime - psStruct->timeLastHit < HIT_NOTIFICATION)) { /* if(gameTime%250<125) { col = playerCol; } else { col = 165;//COL_RED; } */ col = flashCol; } else { col = playerCol; } for(c=0; c= (UDWORD)radarBuffer , "WPtr Onderflow" ); ASSERT( ((UDWORD)WPtr) < ((UDWORD)radarBuffer)+RADWIDTH*RADHEIGHT , "WPtr Overrun" ); #endif *WPtr = (UBYTE)col; WPtr++; } Ptr += Modulus; } //store the radar coords psStruct->radarX = (UWORD)(x + OffsetX); psStruct->radarY = (UWORD)(y + OffsetY); } // } } } } //now set up coords for Proximity Messages - but only for selectedPlayer for(psProxDisp = apsProxDisp[selectedPlayer]; psProxDisp != NULL; psProxDisp = psProxDisp->psNext) { if (psProxDisp->type == POS_PROXDATA) { psViewProx = (VIEW_PROXIMITY *)((VIEWDATA *)psProxDisp->psMessage-> pViewData)->pData; x = (psViewProx->x/TILE_UNITS)-RadarScrollX; y = (psViewProx->y/TILE_UNITS)-RadarScrollY; } else if (psProxDisp->type == POS_PROXOBJ) { x = (((BASE_OBJECT *)psProxDisp->psMessage->pViewData)->x / TILE_UNITS) - RadarScrollX; y = (((BASE_OBJECT *)psProxDisp->psMessage->pViewData)->y / TILE_UNITS) - RadarScrollY; } x -= RadarMapOriginX; y -= RadarMapOriginY; x *= boxSizeH; y *= boxSizeV; if(TRUE) { psProxDisp->radarX = 0; psProxDisp->radarY = 0; if((x < VisWidth) && (y < VisHeight) && (x >= 0) && (y >= 0)) { //store the coords psProxDisp->radarX = x + OffsetX; psProxDisp->radarY = y + OffsetY; } } } } // Rotate an array of 2d vectors about a given angle, also translates them after rotating. // void RotateVector2D(iVector *Vector,iVector *TVector,iVector *Pos,int Angle,int Count) { int Cos = COS(Angle); int Sin = SIN(Angle); int ox = 0; int oy = 0; int i; iVector *Vec = Vector; iVector *TVec = TVector; if(Pos) { ox = Pos->x; oy = Pos->y; } for(i=0; ix = ( (Vec->x*Cos + Vec->y*Sin) >> FP12_SHIFT ) + ox; TVec->y = ( (Vec->y*Cos - Vec->x*Sin) >> FP12_SHIFT ) + oy; Vec++; TVec++; } } // Returns the world position which corresponds to the center of the radar view rectangle. // void GetRadarPlayerPos(UDWORD *XPos,UDWORD *YPos) { *XPos = player.p.x + (visibleXTiles/2)*TILE_UNITS; *YPos = player.p.z + (visibleYTiles/2)*TILE_UNITS; } SDWORD getDistanceAdjust( void ) { UDWORD origDistance; SDWORD dif; origDistance = MAXDISTANCE; dif = origDistance-distance; if(dif <0 ) dif = 0; dif/=100; return(dif); } SDWORD getLengthAdjust( void ) { SDWORD pitch; UDWORD lookingDown,lookingFar; SDWORD dif; pitch = 360 - (player.r.x/DEG_1); // Max at lookingDown = (0-MIN_PLAYER_X_ANGLE); lookingFar = (0-MAX_PLAYER_X_ANGLE); dif = pitch-lookingFar; if(dif <0) dif = 0; if(dif>(lookingDown-lookingFar)) dif = (lookingDown-lookingFar); return(dif/2); } /* Draws a Myth/FF7 style viewing window */ void drawViewingWindow( UDWORD x, UDWORD y, UDWORD boxSizeH,UDWORD boxSizeV ) { iVector v[4],tv[4],centre; UDWORD shortX,longX,yDrop,yDropVar; SDWORD dif = getDistanceAdjust(); SDWORD dif2 = getLengthAdjust(); UDWORD colour = 0; UDWORD camNumber; shortX = ((visibleXTiles/4)-(dif/6)) * boxSizeH; longX = ((visibleXTiles/2)-(dif/4)) * boxSizeH; yDropVar = ((visibleYTiles/2)-(dif2/3)) * boxSizeV; yDrop = ((visibleYTiles/2)-dif2/3) * boxSizeV; v[0].x = longX; // FIXME -unsigned will remain unsigned!!! v[0].y = -yDropVar; v[1].x = -longX; v[1].y = -yDropVar; v[2].x = shortX; v[2].y = yDrop; v[3].x = -shortX; v[3].y = yDrop; centre.x = RADTLX+x+(visibleXTiles*boxSizeH)/2; centre.y = RADTLY+y+(visibleYTiles*boxSizeV)/2; RotateVector2D(v,tv,¢re,player.r.y,4); // iV_Line(tv[0].x,tv[0].y,tv[1].x,tv[1].y,colWhite); // iV_Line(tv[1].x,tv[1].y,tv[3].x,tv[3].y,colWhite); // iV_Line(tv[3].x,tv[3].y,tv[2].x,tv[2].y,colWhite); // iV_Line(tv[2].x,tv[2].y,tv[0].x,tv[0].y,colWhite); camNumber = getCampaignNumber(); switch(camNumber) { case 1: colour = 0x3fffffff; //white break; case 2: colour = 0x3fffffff; //white break; case 3: colour = 0x3f3fff3f; //green? default: break; } /* Send the four points to the draw routine and the clip box params */ pie_DrawViewingWindow(tv,RADTLX,RADTLY,RADTLX+RADWIDTH,RADTLY+RADHEIGHT,colour); } static void DrawRadarExtras(UWORD boxSizeH,UWORD boxSizeV) { // UDWORD viewX,viewY; SDWORD viewX,viewY; SDWORD offsetX,offsetY; offsetX = offsetY = viewX = ((player.p.x/TILE_UNITS)-RadarScrollX-RadarMapOriginX)*boxSizeH; viewY = ((player.p.z/TILE_UNITS)-RadarScrollY-RadarMapOriginY)*boxSizeV; viewX += RadarOffsetX; viewY += RadarOffsetY; viewX = viewX&(~(boxSizeH-1)); viewY = viewY&(~(boxSizeV-1)); //don't update the strobe whilst the game is paused if (!gameUpdatePaused()) { /* if(radarStrobe) { iV_Line(RADTLX+radarStrobeX,RADTLY,RADTLX+radarStrobeX,RADBRY,boxPulseColours[radarStrobeIndex]); iV_Line(RADTLX,RADTLY+radarStrobeY,RADBRX,RADTLY+radarStrobeY,boxPulseColours[radarStrobeIndex++]); sweep = viewY; if(radarStrobeIndex >= BOX_PULSE_SIZE) { radarStrobe = FALSE; radarStrobeIndex = 0; } } */ } drawViewingWindow(viewX,viewY,boxSizeH,boxSizeV); DrawEnableLocks(FALSE); RenderWindowFrame(&FrameRadar,RADTLX-1,RADTLY-1,RADWIDTH+2,RADHEIGHT+2); DrawEnableLocks(TRUE); // Draw the radar border. } // Does a screen coordinate lie within the radar area? // BOOL CoordInRadar(int x,int y) { if( (x >=RADTLX -1 ) && (x < RADTLX +RADWIDTH+1) && (y >=RADTLY -1) && (y < RADTLY +RADHEIGHT+1) ) { return TRUE; } return FALSE; } void calcRadarColour(UBYTE *tileBitmap, UDWORD tileNumber) { UDWORD i, j; UBYTE penNumber; UBYTE fRed,fGreen,fBlue; UBYTE red,green,blue; UDWORD tRed,tGreen,tBlue; iColour* psPalette; tRed = tGreen = tBlue = 0; #define SAMPLES 8 #if 0 /* Got through every pixel */ //what all 4096 of them for(i=0; i