679 lines
18 KiB
C++
679 lines
18 KiB
C++
/*
|
|
This file is part of Warzone 2100.
|
|
Copyright (C) 1999-2004 Eidos Interactive
|
|
Copyright (C) 2005-2013 Warzone 2100 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 <string.h>
|
|
|
|
#include "lib/framework/frame.h"
|
|
#include "lib/framework/fixedpoint.h"
|
|
#include "lib/ivis_opengl/pieblitfunc.h"
|
|
// FIXME Direct iVis implementation include!
|
|
#include "lib/ivis_opengl/piematrix.h"
|
|
#include "lib/ivis_opengl/piepalette.h"
|
|
#include "lib/ivis_opengl/piestate.h"
|
|
#include "lib/ivis_opengl/piefunc.h"
|
|
#include "lib/ivis_opengl/bitimage.h"
|
|
#include "lib/gamelib/gtime.h"
|
|
#include "advvis.h"
|
|
#include "objects.h"
|
|
#include "display3d.h"
|
|
#include "map.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 "mission.h"
|
|
#include "multiplay.h"
|
|
#include "intdisplay.h"
|
|
#include "texture.h"
|
|
|
|
#define HIT_NOTIFICATION (GAME_TICKS_PER_SEC * 2)
|
|
#define RADAR_FRAME_SKIP 10
|
|
|
|
bool bEnemyAllyRadarColor = false; /**< Enemy/ally radar color. */
|
|
RADAR_DRAW_MODE radarDrawMode = RADAR_MODE_DEFAULT; /**< Current mini-map mode. */
|
|
bool rotateRadar; ///< Rotate the radar?
|
|
|
|
static PIELIGHT colRadarAlly, colRadarMe, colRadarEnemy;
|
|
static PIELIGHT tileColours[MAX_TILES];
|
|
static UDWORD *radarBuffer = NULL;
|
|
static Vector3i playerpos;
|
|
|
|
PIELIGHT clanColours[]=
|
|
{ // see frontend2.png for team color order.
|
|
// [r,g,b,a]
|
|
{{0,255,0,255}}, // green Player 0
|
|
{{255,192,40,255}}, // orange Player 1
|
|
{{255,255,255,255}}, // grey Player 2
|
|
{{0,0,0,255}}, // black Player 3
|
|
{{255,0,0,255}}, // red Player 4
|
|
{{20,20,255,255}}, // blue Player 5
|
|
{{255,0,192,255}}, // pink Player 6
|
|
{{0,255,255,255}}, // cyan Player 7
|
|
{{255,255,0,255}}, // yellow Player 8
|
|
{{144,0,255,255}}, // purple Player 9
|
|
{{200,255,255,255}}, // white Player A (Should be brighter than grey, but grey is already maximum.)
|
|
{{128,128,255,255}}, // bright blue Player B
|
|
{{128,255,128,255}}, // neon green Player C
|
|
{{128,0,0,255}}, // infrared Player D
|
|
{{64,0,128,255}}, // ultraviolet Player E
|
|
{{128,128,0,255}}, // brown Player F
|
|
};
|
|
|
|
static PIELIGHT flashColours[]=
|
|
{ //right now the flash color is all bright red
|
|
{{254,37,37,200}}, // Player 0
|
|
{{254,37,37,200}}, // Player 1
|
|
{{254,37,37,200}}, // Player 2
|
|
{{254,37,37,200}}, // Player 3
|
|
{{254,37,37,200}}, // Player 4 (notice, brighter red)
|
|
{{254,37,37,200}}, // Player 5
|
|
{{254,37,37,200}}, // Player 6
|
|
{{254,37,37,200}}, // Player 7
|
|
{{254,37,37,200}}, // Player 8
|
|
{{254,37,37,200}}, // Player 9
|
|
{{254,37,37,200}}, // Player A
|
|
{{254,37,37,200}}, // Player B
|
|
{{254,37,37,200}}, // Player C
|
|
{{254,37,37,200}}, // Player D
|
|
{{254,37,37,200}}, // Player E
|
|
{{254,37,37,200}}, // Player F
|
|
};
|
|
|
|
static SDWORD radarWidth, radarHeight, radarCenterX, radarCenterY, radarTexWidth, radarTexHeight;
|
|
static uint8_t RadarZoom;
|
|
static float RadarZoomMultiplier = 1.0f;
|
|
static UDWORD radarBufferSize = 0;
|
|
static int frameSkip = 0;
|
|
|
|
static void DrawRadarTiles();
|
|
static void DrawRadarObjects();
|
|
static void DrawRadarExtras();
|
|
static void DrawNorth();
|
|
static void setViewingWindow();
|
|
|
|
static void radarSize(int ZoomLevel)
|
|
{
|
|
float zoom = (float)ZoomLevel * RadarZoomMultiplier / 16.0;
|
|
radarWidth = radarTexWidth * zoom;
|
|
radarHeight = radarTexHeight * zoom;
|
|
if (rotateRadar)
|
|
{
|
|
radarCenterX = pie_GetVideoBufferWidth() - BASE_GAP * 4 - MAX(radarHeight, radarWidth) / 2;
|
|
radarCenterY = pie_GetVideoBufferHeight() - BASE_GAP * 4 - MAX(radarWidth, radarHeight) / 2;
|
|
}
|
|
else
|
|
{
|
|
radarCenterX = pie_GetVideoBufferWidth() - BASE_GAP * 4 - radarWidth / 2;
|
|
radarCenterY = pie_GetVideoBufferHeight() - BASE_GAP * 4 - radarHeight / 2;
|
|
}
|
|
debug(LOG_WZ, "radar=(%u,%u) tex=(%u,%u) size=(%u,%u)", radarCenterX, radarCenterY, radarTexWidth, radarTexHeight, radarWidth, radarHeight);
|
|
}
|
|
|
|
void radarInitVars()
|
|
{
|
|
radarTexWidth = 0;
|
|
radarTexHeight = 0;
|
|
RadarZoom = DEFAULT_RADARZOOM;
|
|
debug(LOG_WZ, "Resetting radar zoom to %u", RadarZoom);
|
|
radarSize(RadarZoom);
|
|
playerpos = Vector3i(-1, -1, -1);
|
|
}
|
|
|
|
bool InitRadar()
|
|
{
|
|
// Ally/enemy/me colors
|
|
colRadarAlly = WZCOL_YELLOW;
|
|
colRadarEnemy = WZCOL_RED;
|
|
colRadarMe = WZCOL_WHITE;
|
|
if (mapWidth < 150) // too small!
|
|
{
|
|
RadarZoom = pie_GetVideoBufferWidth() <= 640 ? 14 : DEFAULT_RADARZOOM * 2;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool resizeRadar()
|
|
{
|
|
if (radarBuffer)
|
|
{
|
|
free(radarBuffer);
|
|
}
|
|
radarTexWidth = scrollMaxX - scrollMinX;
|
|
radarTexHeight = scrollMaxY - scrollMinY;
|
|
radarBufferSize = radarTexWidth * radarTexHeight * sizeof(UDWORD);
|
|
radarBuffer = (uint32_t *)malloc(radarBufferSize);
|
|
memset(radarBuffer, 0, radarBufferSize);
|
|
if (rotateRadar)
|
|
{
|
|
RadarZoomMultiplier = (float)MAX(RADWIDTH, RADHEIGHT) / (float)MAX(radarTexWidth, radarTexHeight);
|
|
}
|
|
else
|
|
{
|
|
RadarZoomMultiplier = 1.0f;
|
|
}
|
|
debug(LOG_WZ, "Setting radar zoom to %u", RadarZoom);
|
|
radarSize(RadarZoom);
|
|
pie_SetRadar(-radarWidth/2.0 - 1, -radarHeight/2.0 - 1, radarWidth, radarHeight,
|
|
radarTexWidth, radarTexHeight, rotateRadar || (RadarZoom % 16 != 0));
|
|
setViewingWindow();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ShutdownRadar()
|
|
{
|
|
free(radarBuffer);
|
|
radarBuffer = NULL;
|
|
return true;
|
|
}
|
|
|
|
void SetRadarZoom(uint8_t ZoomLevel)
|
|
{
|
|
if (ZoomLevel < 4) // old savegame format didn't save zoom levels very well
|
|
{
|
|
ZoomLevel = DEFAULT_RADARZOOM;
|
|
}
|
|
if (ZoomLevel > MAX_RADARZOOM)
|
|
{
|
|
ZoomLevel = MAX_RADARZOOM;
|
|
}
|
|
if (ZoomLevel < MIN_RADARZOOM)
|
|
{
|
|
ZoomLevel = MIN_RADARZOOM;
|
|
}
|
|
debug(LOG_WZ, "Setting radar zoom to %u from %u", ZoomLevel, RadarZoom);
|
|
RadarZoom = ZoomLevel;
|
|
radarSize(RadarZoom);
|
|
frameSkip = 0;
|
|
resizeRadar();
|
|
}
|
|
|
|
uint8_t GetRadarZoom()
|
|
{
|
|
return RadarZoom;
|
|
}
|
|
|
|
/** Calculate the radar pixel sizes. Returns pixels per tile. */
|
|
static void CalcRadarPixelSize(float *SizeH, float *SizeV)
|
|
{
|
|
*SizeH = (float)radarHeight / (float)radarTexHeight;
|
|
*SizeV = (float)radarWidth / (float)radarTexWidth;
|
|
}
|
|
|
|
/** Given a position within the radar, return a world coordinate. */
|
|
void CalcRadarPosition(int mX, int mY, int *PosX, int *PosY)
|
|
{
|
|
int sPosX, sPosY;
|
|
float pixSizeH, pixSizeV;
|
|
|
|
Vector2f pos;
|
|
pos.x = mX - radarCenterX;
|
|
pos.y = mY - radarCenterY;
|
|
if (rotateRadar)
|
|
{
|
|
pos = Vector2f_Rotate2f(pos, -player.r.y);
|
|
}
|
|
pos.x += radarWidth/2.0;
|
|
pos.y += radarHeight/2.0;
|
|
|
|
CalcRadarPixelSize(&pixSizeH, &pixSizeV);
|
|
sPosX = pos.x / pixSizeH; // adjust for pixel size
|
|
sPosY = pos.y / pixSizeV;
|
|
sPosX += scrollMinX; // adjust for scroll limits
|
|
sPosY += scrollMinY;
|
|
|
|
#if REALLY_DEBUG_RADAR
|
|
debug(LOG_ERROR, "m=(%d,%d) radar=(%d,%d) pos(%d,%d), scroll=(%u-%u,%u-%u) sPos=(%d,%d), pixSize=(%f,%f)",
|
|
mX, mY, radarX, radarY, posX, posY, scrollMinX, scrollMaxX, scrollMinY, scrollMaxY, sPosX, sPosY, pixSizeH, pixSizeV);
|
|
#endif
|
|
|
|
// old safety code -- still necessary?
|
|
sPosX = clip(sPosX, scrollMinX, scrollMaxX);
|
|
sPosY = clip(sPosY, scrollMinY, scrollMaxY);
|
|
|
|
*PosX = sPosX;
|
|
*PosY = sPosY;
|
|
}
|
|
|
|
void drawRadar()
|
|
{
|
|
float pixSizeH, pixSizeV;
|
|
|
|
CalcRadarPixelSize(&pixSizeH, &pixSizeV);
|
|
|
|
ASSERT_OR_RETURN(, radarBuffer, "No radar buffer allocated");
|
|
|
|
// Do not recalculate frustum window coordinates if position or zoom does not change
|
|
if (playerpos.x != player.p.x || playerpos.y != player.p.y || playerpos.z != player.p.z)
|
|
{
|
|
setViewingWindow();
|
|
}
|
|
playerpos = player.p; // cache position
|
|
|
|
if (frameSkip <= 0)
|
|
{
|
|
DrawRadarTiles();
|
|
DrawRadarObjects();
|
|
pie_DownLoadRadar(radarBuffer);
|
|
frameSkip = RADAR_FRAME_SKIP;
|
|
}
|
|
frameSkip--;
|
|
pie_SetRendMode(REND_ALPHA);
|
|
pie_MatBegin();
|
|
pie_TRANSLATE(radarCenterX, radarCenterY, 0);
|
|
if (rotateRadar)
|
|
{
|
|
// rotate the map
|
|
pie_MatRotZ(player.r.y);
|
|
DrawNorth();
|
|
}
|
|
pie_RenderRadar();
|
|
pie_MatBegin();
|
|
pie_TRANSLATE(-radarWidth/2 - 1, -radarHeight/2 - 1, 0);
|
|
DrawRadarExtras();
|
|
pie_MatEnd();
|
|
drawRadarBlips(-radarWidth/2.0 - 1, -radarHeight/2.0 - 1, pixSizeH, pixSizeV);
|
|
pie_MatEnd();
|
|
}
|
|
|
|
static void DrawNorth()
|
|
{
|
|
iV_DrawImage(IntImages, RADAR_NORTH, -((radarWidth / 2.0) + iV_GetImageWidth(IntImages, RADAR_NORTH) + 1), -(radarHeight / 2.0));
|
|
}
|
|
|
|
static PIELIGHT appliedRadarColour(RADAR_DRAW_MODE radarDrawMode, MAPTILE *WTile)
|
|
{
|
|
PIELIGHT WScr = WZCOL_BLACK; // squelch warning
|
|
|
|
// draw radar on/off feature
|
|
if (!getRevealStatus() && !TEST_TILE_VISIBLE(selectedPlayer, WTile))
|
|
{
|
|
return WZCOL_RADAR_BACKGROUND;
|
|
}
|
|
|
|
switch(radarDrawMode)
|
|
{
|
|
case RADAR_MODE_TERRAIN:
|
|
{
|
|
// draw radar terrain on/off feature
|
|
PIELIGHT col = tileColours[TileNumber_tile(WTile->texture)];
|
|
|
|
col.byte.r = sqrtf(col.byte.r * WTile->illumination);
|
|
col.byte.b = sqrtf(col.byte.b * WTile->illumination);
|
|
col.byte.g = sqrtf(col.byte.g * WTile->illumination);
|
|
if (terrainType(WTile) == TER_CLIFFFACE)
|
|
{
|
|
col.byte.r /= 2;
|
|
col.byte.g /= 2;
|
|
col.byte.b /= 2;
|
|
}
|
|
if (!hasSensorOnTile(WTile, selectedPlayer))
|
|
{
|
|
col.byte.r = col.byte.r * 2 / 3;
|
|
col.byte.g = col.byte.g * 2 / 3;
|
|
col.byte.b = col.byte.b * 2 / 3;
|
|
}
|
|
if (!TEST_TILE_VISIBLE(selectedPlayer, WTile))
|
|
{
|
|
col.byte.r /= 2;
|
|
col.byte.g /= 2;
|
|
col.byte.b /= 2;
|
|
}
|
|
WScr = col;
|
|
}
|
|
break;
|
|
case RADAR_MODE_COMBINED:
|
|
{
|
|
// draw radar terrain on/off feature
|
|
PIELIGHT col = tileColours[TileNumber_tile(WTile->texture)];
|
|
|
|
col.byte.r = sqrtf(col.byte.r * (WTile->illumination + WTile->height / ELEVATION_SCALE) / 2);
|
|
col.byte.b = sqrtf(col.byte.b * (WTile->illumination + WTile->height / ELEVATION_SCALE) / 2);
|
|
col.byte.g = sqrtf(col.byte.g * (WTile->illumination + WTile->height / ELEVATION_SCALE) / 2);
|
|
if (terrainType(WTile) == TER_CLIFFFACE)
|
|
{
|
|
col.byte.r /= 2;
|
|
col.byte.g /= 2;
|
|
col.byte.b /= 2;
|
|
}
|
|
if (!hasSensorOnTile(WTile, selectedPlayer))
|
|
{
|
|
col.byte.r = col.byte.r * 2 / 3;
|
|
col.byte.g = col.byte.g * 2 / 3;
|
|
col.byte.b = col.byte.b * 2 / 3;
|
|
}
|
|
if (!TEST_TILE_VISIBLE(selectedPlayer, WTile))
|
|
{
|
|
col.byte.r /= 2;
|
|
col.byte.g /= 2;
|
|
col.byte.b /= 2;
|
|
}
|
|
WScr = col;
|
|
}
|
|
break;
|
|
case RADAR_MODE_HEIGHT_MAP:
|
|
{
|
|
WScr.byte.r = WScr.byte.g = WScr.byte.b = WTile->height / ELEVATION_SCALE;
|
|
}
|
|
break;
|
|
case RADAR_MODE_NO_TERRAIN:
|
|
{
|
|
WScr = WZCOL_RADAR_BACKGROUND;
|
|
}
|
|
break;
|
|
case NUM_RADAR_MODES:
|
|
{
|
|
assert(false);
|
|
}
|
|
break;
|
|
}
|
|
return WScr;
|
|
}
|
|
|
|
/** Draw the map tiles on the radar. */
|
|
static void DrawRadarTiles()
|
|
{
|
|
SDWORD x, y;
|
|
|
|
for (x = scrollMinX; x < scrollMaxX; x++)
|
|
{
|
|
for (y = scrollMinY; y < scrollMaxY; y++)
|
|
{
|
|
MAPTILE *psTile = mapTile(x, y);
|
|
size_t pos = radarTexWidth * (y - scrollMinY) + (x - scrollMinX);
|
|
|
|
ASSERT(pos * sizeof(*radarBuffer) < radarBufferSize, "Buffer overrun");
|
|
if (y == scrollMinY || x == scrollMinX || y == scrollMaxY - 1 || x == scrollMaxX - 1)
|
|
{
|
|
radarBuffer[pos] = WZCOL_BLACK.rgba;
|
|
continue;
|
|
}
|
|
radarBuffer[pos] = appliedRadarColour(radarDrawMode, psTile).rgba;
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Draw the droids and structure positions on the radar. */
|
|
static void DrawRadarObjects()
|
|
{
|
|
UBYTE clan;
|
|
PIELIGHT playerCol;
|
|
PIELIGHT flashCol;
|
|
int x, y;
|
|
|
|
/* Show droids on map - go through all players */
|
|
for(clan = 0; clan < MAX_PLAYERS; clan++)
|
|
{
|
|
DROID *psDroid;
|
|
|
|
//see if have to draw enemy/ally color
|
|
if (bEnemyAllyRadarColor)
|
|
{
|
|
if (clan == selectedPlayer)
|
|
{
|
|
playerCol = colRadarMe;
|
|
}
|
|
else
|
|
{
|
|
playerCol = (aiCheckAlliances(selectedPlayer, clan) ? colRadarAlly : colRadarEnemy);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//original 8-color mode
|
|
STATIC_ASSERT(MAX_PLAYERS <= ARRAY_SIZE(clanColours));
|
|
playerCol = clanColours[getPlayerColour(clan)];
|
|
}
|
|
|
|
STATIC_ASSERT(MAX_PLAYERS <= ARRAY_SIZE(flashColours));
|
|
flashCol = flashColours[getPlayerColour(clan)];
|
|
|
|
/* Go through all droids */
|
|
for(psDroid = apsDroidLists[clan]; psDroid != NULL; psDroid = psDroid->psNext)
|
|
{
|
|
if (psDroid->pos.x < world_coord(scrollMinX) || psDroid->pos.y < world_coord(scrollMinY)
|
|
|| psDroid->pos.x >= world_coord(scrollMaxX) || psDroid->pos.y >= world_coord(scrollMaxY))
|
|
{
|
|
continue;
|
|
}
|
|
if (psDroid->visible[selectedPlayer]
|
|
|| (bMultiPlayer && alliancesSharedVision(game.alliance)
|
|
&& aiCheckAlliances(selectedPlayer,psDroid->player)))
|
|
{
|
|
int x = psDroid->pos.x / TILE_UNITS;
|
|
int y = psDroid->pos.y / TILE_UNITS;
|
|
size_t pos = (x - scrollMinX) + (y - scrollMinY) * radarTexWidth;
|
|
|
|
ASSERT(pos * sizeof(*radarBuffer) < radarBufferSize, "Buffer overrun");
|
|
if (clan == selectedPlayer && gameTime-psDroid->timeLastHit < HIT_NOTIFICATION)
|
|
{
|
|
radarBuffer[pos] = flashCol.rgba;
|
|
}
|
|
else
|
|
{
|
|
radarBuffer[pos] = playerCol.rgba;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Do the same for structures */
|
|
for (x = scrollMinX; x < scrollMaxX; x++)
|
|
{
|
|
for (y = scrollMinY; y < scrollMaxY; y++)
|
|
{
|
|
MAPTILE *psTile = mapTile(x, y);
|
|
STRUCTURE *psStruct;
|
|
size_t pos = (x - scrollMinX) + (y - scrollMinY) * radarTexWidth;
|
|
|
|
ASSERT(pos * sizeof(*radarBuffer) < radarBufferSize, "Buffer overrun");
|
|
if (!TileHasStructure(psTile))
|
|
{
|
|
continue;
|
|
}
|
|
psStruct = (STRUCTURE *)psTile->psObject;
|
|
clan = psStruct->player;
|
|
|
|
//see if have to draw enemy/ally color
|
|
if (bEnemyAllyRadarColor)
|
|
{
|
|
if (clan == selectedPlayer)
|
|
{
|
|
playerCol = colRadarMe;
|
|
}
|
|
else
|
|
{
|
|
playerCol = (aiCheckAlliances(selectedPlayer, clan) ? colRadarAlly: colRadarEnemy);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//original 8-color mode
|
|
playerCol = clanColours[getPlayerColour(clan)];
|
|
}
|
|
flashCol = flashColours[getPlayerColour(clan)];
|
|
|
|
if (psStruct->visible[selectedPlayer]
|
|
|| (bMultiPlayer && alliancesSharedVision(game.alliance)
|
|
&& aiCheckAlliances(selectedPlayer, psStruct->player)))
|
|
{
|
|
if (clan == selectedPlayer && gameTime - psStruct->timeLastHit < HIT_NOTIFICATION)
|
|
{
|
|
radarBuffer[pos] = flashCol.rgba;
|
|
}
|
|
else
|
|
{
|
|
radarBuffer[pos] = playerCol.rgba;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Rotate an array of 2d vectors about a given angle, also translates them after rotating. */
|
|
static void RotateVector2D(Vector3i *Vector, Vector3i *TVector, Vector3i *Pos, int Angle, int Count)
|
|
{
|
|
int64_t Cos = iCos(Angle);
|
|
int64_t Sin = iSin(Angle);
|
|
int ox = 0;
|
|
int oy = 0;
|
|
int i;
|
|
Vector3i *Vec = Vector;
|
|
Vector3i *TVec = TVector;
|
|
|
|
if (Pos)
|
|
{
|
|
ox = Pos->x;
|
|
oy = Pos->y;
|
|
}
|
|
|
|
for (i = 0; i < Count; i++)
|
|
{
|
|
TVec->x = ((Vec->x*Cos + Vec->y*Sin) >> 16) + ox;
|
|
TVec->y = ((Vec->y*Cos - Vec->x*Sin) >> 16) + oy;
|
|
Vec++;
|
|
TVec++;
|
|
}
|
|
}
|
|
|
|
static SDWORD getDistanceAdjust( void )
|
|
{
|
|
int dif = std::max<int>(MAXDISTANCE - getViewDistance(), 0);
|
|
|
|
return dif / 100;
|
|
}
|
|
|
|
static SDWORD getLengthAdjust( void )
|
|
{
|
|
const int pitch = 360 - (player.r.x/DEG_1);
|
|
|
|
// Max at
|
|
const int lookingDown = (0 - MIN_PLAYER_X_ANGLE);
|
|
const int lookingFar = (0 - MAX_PLAYER_X_ANGLE);
|
|
|
|
int dif = MAX(pitch - lookingFar, 0);
|
|
if (dif > (lookingDown - lookingFar))
|
|
{
|
|
dif = (lookingDown - lookingFar);
|
|
}
|
|
|
|
return dif / 2;
|
|
}
|
|
|
|
/** Draws a Myth/FF7 style viewing window */
|
|
static void setViewingWindow()
|
|
{
|
|
float pixSizeH, pixSizeV;
|
|
Vector3i v[4], tv[4], centre;
|
|
int shortX, longX, yDrop, yDropVar;
|
|
int dif = getDistanceAdjust();
|
|
int dif2 = getLengthAdjust();
|
|
PIELIGHT colour;
|
|
CalcRadarPixelSize(&pixSizeH, &pixSizeV);
|
|
int x = player.p.x * pixSizeH / TILE_UNITS;
|
|
int y = player.p.z * pixSizeV / TILE_UNITS;
|
|
|
|
shortX = ((visibleTiles.x / 4) - (dif / 6)) * pixSizeH;
|
|
longX = ((visibleTiles.x / 2) - (dif / 4)) * pixSizeH;
|
|
yDropVar = ((visibleTiles.y / 2) - (dif2 / 3)) * pixSizeV;
|
|
yDrop = ((visibleTiles.y / 2) - dif2 / 3) * pixSizeV;
|
|
|
|
v[0].x = longX;
|
|
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 = x - scrollMinX * pixSizeH;
|
|
centre.y = y - scrollMinY * pixSizeV;
|
|
|
|
RotateVector2D(v,tv,¢re,player.r.y,4);
|
|
|
|
switch (getCampaignNumber())
|
|
{
|
|
case 1:
|
|
case 2:
|
|
// white
|
|
colour.byte.r = UBYTE_MAX;
|
|
colour.byte.g = UBYTE_MAX;
|
|
colour.byte.b = UBYTE_MAX;
|
|
colour.byte.a = 0x3f;
|
|
break;
|
|
case 3:
|
|
// greenish
|
|
colour.byte.r = 0x3f;
|
|
colour.byte.a = 0x3f;
|
|
colour.byte.g = UBYTE_MAX;
|
|
colour.byte.b = 0x3f;
|
|
default:
|
|
// black
|
|
colour.rgba = 0;
|
|
colour.byte.a = 0x3f;
|
|
break;
|
|
}
|
|
|
|
/* Send the four points to the draw routine and the clip box params */
|
|
pie_SetViewingWindow(tv, colour);
|
|
}
|
|
|
|
static void DrawRadarExtras()
|
|
{
|
|
pie_DrawViewingWindow();
|
|
RenderWindowFrame(FRAME_RADAR, -1, -1, radarWidth + 2, radarHeight + 2);
|
|
}
|
|
|
|
/** Does a screen coordinate lie within the radar area? */
|
|
bool CoordInRadar(int x,int y)
|
|
{
|
|
Vector2f pos;
|
|
pos.x = x - radarCenterX;
|
|
pos.y = y - radarCenterY;
|
|
if (rotateRadar)
|
|
{
|
|
pos = Vector2f_Rotate2f(pos, -player.r.y);
|
|
}
|
|
pos.x += radarWidth/2.0;
|
|
pos.y += radarHeight/2.0;
|
|
|
|
if (pos.x<0 || pos.y<0 || pos.x>=radarWidth || pos.y>=radarHeight)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void radarColour(UDWORD tileNumber, uint8_t r, uint8_t g, uint8_t b)
|
|
{
|
|
tileColours[tileNumber].byte.r = r;
|
|
tileColours[tileNumber].byte.g = g;
|
|
tileColours[tileNumber].byte.b = b;
|
|
tileColours[tileNumber].byte.a = 255;
|
|
}
|