From c068f22329d5cc722622a2183bbb22eef2093df7 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 24 Aug 2026 11:16:07 +0200 Subject: initial import --- src/parsec/h_radar.cpp | 617 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 617 insertions(+) create mode 100644 src/parsec/h_radar.cpp (limited to 'src/parsec/h_radar.cpp') diff --git a/src/parsec/h_radar.cpp b/src/parsec/h_radar.cpp new file mode 100644 index 0000000..d8f094d --- /dev/null +++ b/src/parsec/h_radar.cpp @@ -0,0 +1,617 @@ +/* + * PARSEC - Radar Display Code + * + * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:37 $ + * + * Orginally written by: + * Copyright (c) Markus Hadwiger 1996-1999 + * Copyright (c) Andreas Varga 1999 + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include +#include +#include +#include +#include +#include + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// subsystem headers +#include "aud_defs.h" + +// drawing subsystem +#include "d_bmap.h" +#include "d_misc.h" + +// mathematics header +#include "utl_math.h" + +// local module header +#include "h_radar.h" + +// proprietary module headers +#include "con_arg.h" +#include "con_aux.h" +#include "con_com.h" +#include "con_main.h" +#include "e_color.h" +#include "e_supp.h" +#include "h_cockpt.h" +#include "obj_ctrl.h" +#include "obj_cust.h" + + + +// epsilon for null vector ---------------------------------------------------- +// +#define EPS_VECLEN 1e-7 + + +// colors of radar objects ---------------------------------------------------- +// +#define TARGET_RADAR_OBJ_COL 255 // white +#define NORMAL_RADAR_OBJ_COL1 80 // red +#define NORMAL_RADAR_OBJ_COL2 87 +#define NORMAL_RADAR_OBJ_COL3 91 +#define MISSILE_RADAR_OBJ_COL 167 // yellow +#define STARGATE_RADAR_OBJ_COL 225 // blue +#define PLANET_RADAR_OBJ_COL 102 // green +#define TELEPORTER_RADAR_OBJ_COL 102 // green // FIXME: use this for now + + +// generic string paste area -------------------------------------------------- +// +#define PASTE_STR_LEN 255 +static char paste_str[ PASTE_STR_LEN + 1 ]; + + +// geometry of radar ---------------------------------------------------------- +// +int hud_radar_w; +int hud_radar_h; +int hud_radar_x; +int hud_radar_y; + +int hud_radar_bitm_x; +int hud_radar_bitm_y; + + +// check vector length for zero ----------------------------------------------- +// +INLINE +int LenZero( hprec_t len ) +{ + ASSERT( len >= 0 ); + if ( len < EPS_VECLEN ) { + MSGOUT( "radar: diminishing vector encountered." ); + return TRUE; + } + return FALSE; +} + + +// area of radar frame -------------------------------------------------------- +// +static int area_x; +static int area_y; +static int area_width; +static int area_height; + + +// draw radar object after calculating its position --------------------------- +// +PRIVATE +void CalcDrawRadarObj( GenObject *objpo, int col ) +{ + ASSERT( objpo != NULL ); + + // fetch ship's position + float ox = GEOMV_TO_FLOAT( objpo->CurrentXmatrx[ 0 ][ 3 ] ); + float oy = GEOMV_TO_FLOAT( objpo->CurrentXmatrx[ 1 ][ 3 ] ); + float oz = GEOMV_TO_FLOAT( objpo->CurrentXmatrx[ 2 ][ 3 ] ); + + // square components + hprec_t ox2 = ox * ox; + hprec_t oy2 = oy * oy; + hprec_t oz2 = oz * oz; + + // length of vector + hprec_t len = sqrt( ox2 + oy2 + oz2 ); + if ( LenZero( len ) ) + return; + + // length of projection onto (xz)-plane + hprec_t lxz = sqrt( ox2 + oz2 ); + if ( LenZero( lxz ) ) + return; + + // yaw of projected vector (theta) + hprec_t yaw = asin( ox / lxz ); + + // bring range to [-PI..0] and [0..+PI] + if ( oz < 0 ) + yaw = ( ox < 0 ) ? -HPREC_PI - yaw : HPREC_PI - yaw; + + // x axis is sin( yaw/2 ) weighted with cos( y-axis ): + // combined left/right and front/back info in sine scale + // [ formula: x = sin( theta/2 ) * cos( phi ) ] + hprec_t rx = sin( yaw / 2 ) * ( lxz / len ); + + // y axis is sin( pitch ): + // above/below info in sine scale + // [ formula: y = sin( phi ) ] + hprec_t ry = oy / len; + + // draw actual radar object dot + int radarx = (int)( rx * area_width ); + int radary = (int)( ry * area_height ); + D_DrawRadarObj( area_x + radarx , area_y + radary, COLINDX_TO_VISUAL( col ) ); +} + + +// the range of the elite radar ----------------------------------------------- +// +#define ELITE_RADAR_RANGE_MIN 4096.0 +#define ELITE_RADAR_RANGE_MAX 65535.0 + +static int radar_range = (int)ELITE_RADAR_RANGE_MIN; + + +// draw radar object after calculating its position --------------------------- +// +PRIVATE +void CalcDrawEliteRadarObj( GenObject *objpo, int col ) +{ + ASSERT( objpo != NULL ); + + // fetch ship's position + float ox = GEOMV_TO_FLOAT( objpo->CurrentXmatrx[ 0 ][ 3 ] ); + float oy = GEOMV_TO_FLOAT( objpo->CurrentXmatrx[ 1 ][ 3 ] ); + float oz = GEOMV_TO_FLOAT( objpo->CurrentXmatrx[ 2 ][ 3 ] ); + + int radar_width = 200; + int radar_width_2 = 200 / 2; + int radar_height = 32; + int radar_height_2 = 32 / 2; + int radar_centerx = Screen_XOfs + 2; + int radar_centery = Screen_Height - 100 + 68; + + if ( AUX_DRAW_COCKPIT && AUX_DRAW_COCKPIT_RADAR ) { + radar_centerx = (int)(Screen_Width - 0.4953f * Scaled_Screen_Width + 1); + radar_centery = (int)(Screen_Height - 0.1187f * Scaled_Screen_Height); + radar_width = (int)(130 * scale_tab[ cp_scale ]); + radar_width_2 = (int)(( 130 / 2 ) * scale_tab[ cp_scale ]); + radar_height = (int)(32 * scale_tab[ cp_scale ]); + radar_height_2 = (int)(( 32 / 2 ) * scale_tab[ cp_scale ]); + } + + // square components + hprec_t ox2 = ox * ox; + hprec_t oy2 = oy * oy; + hprec_t oz2 = oz * oz; + + // length of vector + hprec_t len = sqrt( ox2 + oy2 + oz2 ); + if ( LenZero( len ) ) + return; + + // don't draw objects that are too far away + if ( len > radar_range ) + return; + + hprec_t rx = ( ox / radar_range ) * radar_width_2; + hprec_t ry = ( -oz / radar_range ) * radar_height_2; + hprec_t rz = ( -oy / radar_range ) * ( Screen_Height - radar_centery - 3 ); + + int radar_x = (int)(radar_centerx + rx) +; + int radar_y = (int)(radar_centery + ry); + + int height = (int)rz; + + // draw actual radar object + visual_t xlatcol = COLINDX_TO_VISUAL( col ); + if ( height > 0 ) { + + D_DrawVertBar( radar_x, radar_y - height, xlatcol, height + 1 ); + D_DrawHorzBar( radar_x, radar_y - height, xlatcol, 2 ); + + } else if ( height < 0 ) { + + D_DrawVertBar( radar_x, radar_y, xlatcol, -height + 1 ); + D_DrawHorzBar( radar_x, radar_y - height, xlatcol, 2 ); + + } else { + + D_DrawHorzBar( radar_x, radar_y, xlatcol, 2 ); + } +} + + +// scan ship objects for radar ------------------------------------------------ +// +INLINE +void RadarScanShipObjects() +{ + GenObject *targetobj = NULL; + + for ( GenObject *walkobjs = FetchFirstShip(); walkobjs; ) { + + // set color for normal objects + int rocolor = NORMAL_RADAR_OBJ_COL2; + + if ( AUX_ENABLE_DEPTHCUED_RADAR_DOTS && !AUX_ENABLE_ELITE_RADAR ) { + + Vertex3 shippos; + FetchTVector( walkobjs->ObjPosition, &shippos ); + + Vertex3 myshippos; + FetchTVector( MyShip->ObjPosition, &myshippos ); + + Vector3 dist; + VECSUB( &dist, &shippos, &myshippos ); + + geomv_t vx = dist.X; + geomv_t vy = dist.Y; + geomv_t vz = dist.Z; + + ABS_GEOMV( vx ); + ABS_GEOMV( vy ); + ABS_GEOMV( vz ); + + int distance = 0; + if ( ( vx > GEOMV_VANISHING ) || + ( vy > GEOMV_VANISHING ) || + ( vz > GEOMV_VANISHING ) ) { + distance = GEOMV_TO_INT( VctLenX( &dist ) ); + } + + if ( distance > 4096 ) { + rocolor = NORMAL_RADAR_OBJ_COL3; + } else if ( distance > 2048 ) { + rocolor = NORMAL_RADAR_OBJ_COL2; + } else { + rocolor = NORMAL_RADAR_OBJ_COL1; + } + } + + // ensure that the target object is drawn last + if ( walkobjs->HostObjNumber == TargetObjNumber ) { + + if ( targetobj == NULL ) { + targetobj = walkobjs; + + if ( ( walkobjs = walkobjs->NextObj ) == NULL ) { + walkobjs = targetobj; + } + + continue; + } + + rocolor = TARGET_RADAR_OBJ_COL; + } + + // depict ship's position on radar + if ( AUX_ENABLE_ELITE_RADAR ) { + CalcDrawEliteRadarObj( walkobjs, rocolor ); + } else { + CalcDrawRadarObj( walkobjs, rocolor ); + } + + if ( walkobjs == targetobj ) { + break; + } + + if ( ( walkobjs = walkobjs->NextObj ) == NULL ) { + walkobjs = targetobj; + } + } +} + + +// scan missile objects for radar --------------------------------------------- +// +INLINE +void RadarScanMissileObjects() +{ + GenObject *walkobjs = FetchFirstMissile(); + for ( ; walkobjs; walkobjs = walkobjs->NextObj ) { + + // set color for missile objects + int rocolor = MISSILE_RADAR_OBJ_COL; + + // depict missile's position on radar + if ( AUX_ENABLE_ELITE_RADAR ) { + CalcDrawEliteRadarObj( walkobjs, rocolor ); + } else { + CalcDrawRadarObj( walkobjs, rocolor ); + } + } +} + + +// scan stargate objects for radar -------------------------------------------- +// +INLINE +void RadarScanStargateObjects() +{ + GenObject *walkobjs = FetchFirstCustom(); + for ( ; walkobjs; walkobjs = walkobjs->NextObj ) { + + // get type id of the custom stargate + static dword stargate_typeid = TYPE_ID_INVALID; + if ( stargate_typeid == TYPE_ID_INVALID ) { + stargate_typeid = OBJ_FetchCustomTypeId( "stargate" ); + } + + // we only want to walk stargates + if ( walkobjs->ObjectType != stargate_typeid ) { + continue; + } + + // set color for stargate objects + int rocolor = STARGATE_RADAR_OBJ_COL; + + // depict stargate's position on radar + if ( AUX_ENABLE_ELITE_RADAR ) { + CalcDrawEliteRadarObj( walkobjs, rocolor ); + } else { + CalcDrawRadarObj( walkobjs, rocolor ); + } + } +} + +// scan teleporter objects for radar ------------------------------------------ +// +INLINE +void RadarScanTeleporterObjects() +{ + GenObject *walkobjs = FetchFirstCustom(); + for ( ; walkobjs; walkobjs = walkobjs->NextObj ) { + + // get type id of the custom stargate + static dword teleporter_typeid = TYPE_ID_INVALID; + if ( teleporter_typeid == TYPE_ID_INVALID ) { + teleporter_typeid = OBJ_FetchCustomTypeId( "teleporter" ); + } + + // we only want to walk stargates + if ( walkobjs->ObjectType != teleporter_typeid ) { + continue; + } + + // set color for stargate objects + int rocolor = TELEPORTER_RADAR_OBJ_COL; + + // depict stargate's position on radar + if ( AUX_ENABLE_ELITE_RADAR ) { + CalcDrawEliteRadarObj( walkobjs, rocolor ); + } else { + CalcDrawRadarObj( walkobjs, rocolor ); + } + } +} + + +// scan planet objects for radar ----------------------------------------------- +// +INLINE +void RadarScanPlanetObjects() +{ + GenObject *walkobjs = FetchFirstCustom(); + for ( ; walkobjs; walkobjs = walkobjs->NextObj ) { + + // get type id of the custom planet + static dword planet_typeid = TYPE_ID_INVALID; + if ( planet_typeid == TYPE_ID_INVALID ) { + planet_typeid = OBJ_FetchCustomTypeId( "planet" ); + } + + // we only want to walk planets + if ( walkobjs->ObjectType != planet_typeid ) { + continue; + } + + // set color for planet objects + int rocolor = PLANET_RADAR_OBJ_COL; + + // depict planet's position on radar + if ( AUX_ENABLE_ELITE_RADAR ) { + CalcDrawEliteRadarObj( walkobjs, rocolor ); + } else { + CalcDrawRadarObj( walkobjs, rocolor ); + } + } +} + + +// draw radar display (contents): dots denoting spacecrafts ------------------- +// +void HUD_DrawHUDRadar() +{ + if ( !AUX_ENABLE_ELITE_RADAR ) { + + // make sure dots are positioned in/scaled to frame + if ( AUX_DRAW_COCKPIT && AUX_DRAW_COCKPIT_RADAR ) { + + float center_x = 322.0f / 640.0f; // offset from left edge of screen + float center_y = 65.0f / 480.0f; // offset from top of texture + float width = 43.0f / 640.0f; + + area_x = (int)(center_x * Screen_Width); + area_y = (int)(Screen_Height - ( cockpitinfo[ RADAR ].ypos - center_y ) * Scaled_Screen_Height); + area_width = (int)(width * Scaled_Screen_Width); + area_height = area_width; + + } else { + + area_x = hud_radar_x; + area_y = hud_radar_y - BitmapInfo[ BM_RADAR ].height/2; + area_width = BitmapInfo[ BM_RADAR ].width/2 - hud_radar_w; + area_height = BitmapInfo[ BM_RADAR ].height/2 - hud_radar_h; + } + } + + // ship dots + RadarScanShipObjects(); + + // missile dots + if ( AUX_DRAW_MISSILES_ON_RADAR ) { + RadarScanMissileObjects(); + } + + // stargate dots + if ( AUX_DRAW_STARGATES_ON_RADAR ) { + RadarScanStargateObjects(); + } + + // planet dots + if ( AUX_DRAW_PLANETS_ON_RADAR ) { + RadarScanPlanetObjects(); + } + + // telepoter dots + if ( AUX_DRAW_TELEPORTERS_ON_RADAR ) { + RadarScanTeleporterObjects(); + } + +} + + +// draw radar frame (bitmap, no contents) ------------------------------------- +// +void HUD_DrawHUDRadarFrame() +{ + // no bitmap frame if new radar enabled + if ( AUX_DRAW_COCKPIT && AUX_DRAW_COCKPIT_RADAR ) + return; + + // standard radar is default + int radarid = BM_RADAR; + + // check for alternate radar + if ( AUX_ENABLE_ELITE_RADAR ) { + + // elite-style radar + static int eliteid = -1; + if ( eliteid == -1 ) { + eliteid = FetchBitmapId( BM_NAME_RADAR2 ); + if ( eliteid == -1 ) { + return; + } + } + + radarid = eliteid; + } + + int drawx = hud_radar_bitm_x - BitmapInfo[ radarid ].width/2; + int drawy = hud_radar_bitm_y - BitmapInfo[ radarid ].height; + + // draw radar circle + D_PutTrBitmap( BitmapInfo[ radarid ].bitmappointer, + BitmapInfo[ radarid ].width, + BitmapInfo[ radarid ].height, + drawx, drawy ); +} + + +// change range of elite radar ------------------------------------------------ +// +PRIVATE +int Cmd_RADAR_RANGE( char *paramstr ) +{ + //NOTE: + //CONCOM: + // range_command ::= 'radar.range' [] + + ASSERT( paramstr != NULL ); + HANDLE_COMMAND_DOMAIN_SEP( paramstr ); + + int range = radar_range; + char *scan; + + if ( (scan = QueryIntArgumentEx( paramstr, "%d", &range )) ) { + + // determine if delta modification (++/--) + int delta = 0; + if ( ( scan[ 0 ] == '+' ) && ( scan[ 1 ] == '+' ) ) + delta = 1; + else if ( ( scan[ 0 ] == '-' ) && ( scan[ 1 ] == '-' ) ) + delta = -1; + if ( delta != 0 ) + scan += 2; + + if ( *scan != 0 ) { + char *errpart; + + long sval = strtol( scan, &errpart, 10 ); + if ( *errpart == 0 ) { + if ( delta != 0 ) + sval = range + sval * delta; + if ( sval >= ELITE_RADAR_RANGE_MIN && sval <= ELITE_RADAR_RANGE_MAX ) { + radar_range = sval; + } else { + + //NOTE: + // if delta modification was used, don't print a range_error + // but just beep to give the user some feedback... + + if ( delta != 0 ) + AUD_Select2(); + else + CON_AddLine( range_error ); + } + } else { + CON_AddLine( invalid_arg ); + } + } else { + CON_AddLine( invalid_arg ); + } + } + + return TRUE; +} + + +// module registration function ----------------------------------------------- +// +REGISTER_MODULE( H_RADAR ) +{ + user_command_s regcom; + memset( ®com, 0, sizeof( user_command_s ) ); + + // register "radar.range" command + regcom.command = "radar.range"; + regcom.numparams = 1; + regcom.execute = Cmd_RADAR_RANGE; + regcom.statedump = NULL; + CON_RegisterUserCommand( ®com ); +} + + + -- cgit v1.2.3