/* ** 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 . */ //////////////////////////////////////////////////////////////////////////////// // // // (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_