297 lines
13 KiB
C++
297 lines
13 KiB
C++
/*
|
|
** Command & Conquer Generals(tm)
|
|
** Copyright 2025 Electronic Arts Inc.
|
|
**
|
|
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// (c) 2001-2003 Electronic Arts Inc. //
|
|
// //
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// FILE: Radar.h //////////////////////////////////////////////////////////////////////////////////
|
|
// Author: Colin Day, January 2002
|
|
// Desc: Logical radar implementation
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#pragma once
|
|
|
|
#ifndef __RADAR_H_
|
|
#define __RADAR_H_
|
|
|
|
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
|
#include "Lib/BaseType.h"
|
|
#include "Common/SubsystemInterface.h"
|
|
#include "Common/GameMemory.h"
|
|
#include "GameClient/Display.h" // for ShroudLevel
|
|
#include "GameClient/Color.h"
|
|
|
|
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
|
|
class GameWindow;
|
|
class Object;
|
|
class Player;
|
|
class TerrainLogic;
|
|
|
|
// GLOBAL /////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// the following is used for the resolution of the radar "cells" ... this is how accurate
|
|
// the radar is and also reflects directly the size of the image we build ... which with
|
|
// WW3D must be a square power of two as well
|
|
//
|
|
enum
|
|
{
|
|
RADAR_CELL_WIDTH = 128, // radar created at this horz resolution
|
|
RADAR_CELL_HEIGHT = 128 // radar created at this vert resolution
|
|
};
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
/** These event types determine the colors radar events happen in to make it easier for us
|
|
* to play events with a consistent color scheme */
|
|
//-------------------------------------------------------------------------------------------------
|
|
enum RadarEventType
|
|
{
|
|
RADAR_EVENT_INVALID = 0,
|
|
RADAR_EVENT_CONSTRUCTION,
|
|
RADAR_EVENT_UPGRADE,
|
|
RADAR_EVENT_UNDER_ATTACK,
|
|
RADAR_EVENT_INFORMATION,
|
|
RADAR_EVENT_BEACON_PULSE,
|
|
RADAR_EVENT_INFILTRATION, //for defection, hijacking, hacking, carbombing, and other sneaks
|
|
RADAR_EVENT_BATTLE_PLAN,
|
|
RADAR_EVENT_STEALTH_DISCOVERED, // we discovered a stealth unit
|
|
RADAR_EVENT_STEALTH_NEUTRALIZED, // our stealth unit has been revealed
|
|
RADAR_EVENT_FAKE, //Internally creates a radar event, but doesn't notify the player (unit lost
|
|
//for example, so we can use the spacebar to jump to the event).
|
|
|
|
RADAR_EVENT_NUM_EVENTS // keep this last
|
|
|
|
};
|
|
|
|
// PROTOTYPES /////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
/** Radar objects are objects that are on the radar, go figure :) */
|
|
//-------------------------------------------------------------------------------------------------
|
|
class RadarObject : public MemoryPoolObject,
|
|
public Snapshot
|
|
{
|
|
|
|
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( RadarObject, "RadarObject" )
|
|
|
|
public:
|
|
|
|
RadarObject( void );
|
|
// destructor prototype defined by memory pool glue
|
|
|
|
// color management
|
|
void setColor( Color c ) { m_color = c; }
|
|
inline Color getColor( void ) const { return m_color; }
|
|
|
|
inline void friend_setObject( Object *obj ) { m_object = obj; }
|
|
inline Object *friend_getObject( void ) { return m_object; }
|
|
inline const Object *friend_getObject( void ) const { return m_object; }
|
|
|
|
inline void friend_setNext( RadarObject *next ) { m_next = next; }
|
|
inline RadarObject *friend_getNext( void ) { return m_next; }
|
|
inline const RadarObject *friend_getNext( void ) const { return m_next; }
|
|
|
|
Bool isTemporarilyHidden() const;
|
|
|
|
protected:
|
|
|
|
// snapshot methods
|
|
virtual void crc( Xfer *xfer );
|
|
virtual void xfer( Xfer *xfer );
|
|
virtual void loadPostProcess( void );
|
|
|
|
Object *m_object; ///< the object
|
|
RadarObject *m_next; ///< next radar object
|
|
Color m_color; ///< color to draw for this object on the radar
|
|
|
|
};
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
/** Radar priorities. Keep this in sync with the priority names list below */
|
|
//-------------------------------------------------------------------------------------------------
|
|
enum RadarPriorityType
|
|
{
|
|
RADAR_PRIORITY_INVALID, // a priority that has not been set (in general it won't show up on the radar)
|
|
RADAR_PRIORITY_NOT_ON_RADAR, // object specifically forbidden from being on the radar
|
|
RADAR_PRIORITY_STRUCTURE, // structure level drawing priority
|
|
RADAR_PRIORITY_UNIT, // unit level drawing priority
|
|
RADAR_PRIORITY_LOCAL_UNIT_ONLY, // unit priority, but only on the radar if controlled by the local player
|
|
|
|
RADAR_PRIORITY_NUM_PRIORITIES // keep this last
|
|
};
|
|
#ifdef DEFINE_RADAR_PRIORITY_NAMES
|
|
static const char *RadarPriorityNames[] =
|
|
{
|
|
"INVALID", // a priority that has not been set (in general it won't show up on the radar)
|
|
"NOT_ON_RADAR", // object specifically forbidden from being on the radar
|
|
"STRUCTURE", // structure level drawing priority
|
|
"UNIT", // unit level drawing priority
|
|
"LOCAL_UNIT_ONLY", // unit priority, but only on the radar if controlled by the local player
|
|
|
|
NULL // keep this last
|
|
};
|
|
#endif // DEFINE_RADAR_PRIOTITY_NAMES
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
/** Interface for the radar */
|
|
//-------------------------------------------------------------------------------------------------
|
|
class Radar : public Snapshot,
|
|
public SubsystemInterface
|
|
{
|
|
|
|
public:
|
|
|
|
Radar( void );
|
|
virtual ~Radar( void );
|
|
|
|
virtual void init( void ) { } ///< subsystem initialization
|
|
virtual void reset( void ); ///< subsystem reset
|
|
virtual void update( void ); ///< subsystem per frame update
|
|
|
|
// is the game window parameter the radar window
|
|
Bool isRadarWindow( GameWindow *window ) { return (m_radarWindow == window) && (m_radarWindow != NULL); }
|
|
|
|
Bool radarToWorld( const ICoord2D *radar, Coord3D *world ); ///< radar point to world point on terrain
|
|
Bool worldToRadar( const Coord3D *world, ICoord2D *radar ); ///< translate world point to radar (x,y)
|
|
Bool localPixelToRadar( const ICoord2D *pixel, ICoord2D *radar ); ///< translate pixel (with UL of radar being (0,0)) to logical radar coords
|
|
Bool screenPixelToWorld( const ICoord2D *pixel, Coord3D *world ); ///< translate pixel (with UL of the screen being (0,0)) to world position in the world
|
|
Object *objectUnderRadarPixel( const ICoord2D *pixel ); ///< return the object (if any) represented by the pixel coords passed in
|
|
void findDrawPositions( Int startX, Int startY, Int width, Int height,
|
|
ICoord2D *ul, ICoord2D *lr ); ///< make translation for screen area of radar square to scaled aspect ratio preserving points inside the radar area
|
|
|
|
// priority inquiry
|
|
Bool isPriorityVisible( RadarPriorityType priority ) const; ///< is the priority passed in a "visible" one on the radar
|
|
|
|
// radar events
|
|
void createEvent( const Coord3D *world, RadarEventType type, Real secondsToLive = 4.0f ); ///< create radar event at location in world
|
|
void createPlayerEvent( Player *player, const Coord3D *world, RadarEventType type, Real secondsToLive = 4.0f ); ///< create radar event using player colors
|
|
|
|
Bool getLastEventLoc( Coord3D *eventPos ); ///< get last event loc (if any)
|
|
void tryUnderAttackEvent( const Object *obj ); ///< try to make an "under attack" event if it's the proper time
|
|
void tryInfiltrationEvent( const Object *obj ); ///< try to make an "infiltration" event if it's the proper time
|
|
Bool tryEvent( RadarEventType event, const Coord3D *pos ); ///< try to make a "stealth" event
|
|
|
|
// adding and removing objects from the radar
|
|
void addObject( Object *obj ); ///< add object to radar
|
|
void removeObject( Object *obj ); ///< remove object from radar
|
|
void examineObject( Object *obj ); ///< re-examine object and resort if needed
|
|
|
|
// radar options
|
|
void hide( Bool hide ) { m_radarHidden = hide; } ///< hide/unhide the radar
|
|
Bool isRadarHidden( void ) { return m_radarHidden; } ///< is radar hidden
|
|
// other radar option methods here like the ability to show a certain
|
|
// team, show buildings, show units at all, etc
|
|
|
|
// forcing the radar on/off regardless of player situation
|
|
void forceOn( Bool force ) { m_radarForceOn = force; } ///< force the radar to be on
|
|
Bool isRadarForced( void ) { return m_radarForceOn; } ///< is radar forced on?
|
|
|
|
/// refresh the water values for the radar
|
|
virtual void refreshTerrain( TerrainLogic *terrain );
|
|
|
|
/// queue a refresh of the terran at the next available time
|
|
virtual void queueTerrainRefresh( void );
|
|
|
|
virtual void newMap( TerrainLogic *terrain ); ///< reset radar for new map
|
|
|
|
virtual void draw( Int pixelX, Int pixelY, Int width, Int height ) = 0; ///< draw the radar
|
|
|
|
/// empty the entire shroud
|
|
virtual void clearShroud() = 0;
|
|
|
|
/// set the shroud level at shroud cell x,y
|
|
virtual void setShroudLevel( Int x, Int y, CellShroudStatus setting ) = 0;
|
|
|
|
protected:
|
|
|
|
// snapshot methods
|
|
virtual void crc( Xfer *xfer );
|
|
virtual void xfer( Xfer *xfer );
|
|
virtual void loadPostProcess( void );
|
|
|
|
/// internal method for creating a radar event with specific colors
|
|
void internalCreateEvent( const Coord3D *world, RadarEventType type, Real secondsToLive,
|
|
const RGBAColorInt *color1, const RGBAColorInt *color2 );
|
|
|
|
void deleteListResources( void ); ///< delete list radar resources used
|
|
Bool deleteFromList( Object *obj, RadarObject **list ); ///< try to remove object from specific list
|
|
|
|
inline Real getTerrainAverageZ() const { return m_terrainAverageZ; }
|
|
inline Real getWaterAverageZ() const { return m_waterAverageZ; }
|
|
inline const RadarObject* getObjectList() const { return m_objectList; }
|
|
inline const RadarObject* getLocalObjectList() const { return m_localObjectList; }
|
|
|
|
void clearAllEvents( void ); ///< remove all radar events in progress
|
|
|
|
// search the object list for an object that maps to the given logical radar coords
|
|
Object *searchListForRadarLocationMatch( RadarObject *listHead, ICoord2D *radarMatch );
|
|
|
|
Bool m_radarHidden; ///< true when radar is not visible
|
|
Bool m_radarForceOn; ///< true when radar is forced to be on
|
|
RadarObject *m_objectList; ///< list of objects in the radar
|
|
RadarObject *m_localObjectList; /** list of objects for the local player, sorted
|
|
* in exactly the same priority as the regular
|
|
* object list for all other objects */
|
|
|
|
Real m_terrainAverageZ; ///< average Z for terrain samples
|
|
Real m_waterAverageZ; ///< average Z for water samples
|
|
|
|
//
|
|
// when dealing with world sampling we will sample at these intervals so that
|
|
// the whole map can be accounted for within our RADAR_CELL_WIDTH and
|
|
// RADAR_CELL_HEIGHT resolutions
|
|
//
|
|
Real m_xSample;
|
|
Real m_ySample;
|
|
|
|
enum { MAX_RADAR_EVENTS = 64 };
|
|
struct RadarEvent
|
|
{
|
|
RadarEventType type; ///< type of this radar event
|
|
Bool active; ///< TRUE when event is "active", otherwise it's just historical information in the event array to look through
|
|
UnsignedInt createFrame; ///< frame event was created on
|
|
UnsignedInt dieFrame; ///< frame the event will go away on
|
|
UnsignedInt fadeFrame; ///< start fading out on this frame
|
|
RGBAColorInt color1; ///< color 1 for drawing
|
|
RGBAColorInt color2; ///< color 2 for drawing
|
|
Coord3D worldLoc; ///< location of event in the world
|
|
ICoord2D radarLoc; ///< 2D radar location of the event
|
|
Bool soundPlayed; ///< TRUE when we have played the radar sound for this
|
|
};
|
|
RadarEvent m_event[ MAX_RADAR_EVENTS ];///< our radar events
|
|
Int m_nextFreeRadarEvent; ///< index into m_event for where to store the next event
|
|
Int m_lastRadarEvent; ///< index of the most recent radar event
|
|
|
|
GameWindow *m_radarWindow; ///< window we display the radar in
|
|
|
|
Region3D m_mapExtent; ///< extents of the current map
|
|
|
|
UnsignedInt m_queueTerrainRefreshFrame; ///< frame we requested the last terrain refresh on
|
|
|
|
};
|
|
|
|
// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
|
|
extern Radar *TheRadar; ///< the radar singleton extern
|
|
|
|
#endif // __RADAR_H_
|
|
|
|
|
|
|