diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h b/GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h index 2300812361..518c2f62f7 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h @@ -74,38 +74,38 @@ enum RadiusCursorType CPP_11(: Int) RADIUSCURSOR_FRIENDLY_SPECIALPOWER, RADIUSCURSOR_OFFENSIVE_SPECIALPOWER, RADIUSCURSOR_SUPERWEAPON_SCATTER_AREA, - - RADIUSCURSOR_PARTICLECANNON, + + RADIUSCURSOR_PARTICLECANNON, RADIUSCURSOR_A10STRIKE, RADIUSCURSOR_CARPETBOMB, RADIUSCURSOR_DAISYCUTTER, RADIUSCURSOR_PARADROP, - RADIUSCURSOR_SPYSATELLITE, + RADIUSCURSOR_SPYSATELLITE, RADIUSCURSOR_SPECTREGUNSHIP, RADIUSCURSOR_HELIX_NAPALM_BOMB, - RADIUSCURSOR_NUCLEARMISSILE, + RADIUSCURSOR_NUCLEARMISSILE, RADIUSCURSOR_EMPPULSE, RADIUSCURSOR_ARTILLERYBARRAGE, RADIUSCURSOR_NAPALMSTRIKE, RADIUSCURSOR_CLUSTERMINES, - RADIUSCURSOR_SCUDSTORM, + RADIUSCURSOR_SCUDSTORM, RADIUSCURSOR_ANTHRAXBOMB, - RADIUSCURSOR_AMBUSH, + RADIUSCURSOR_AMBUSH, RADIUSCURSOR_RADAR, RADIUSCURSOR_SPYDRONE, RADIUSCURSOR_FRENZY, - + RADIUSCURSOR_CLEARMINES, RADIUSCURSOR_AMBULANCE, - RADIUSCURSOR_COUNT + RADIUSCURSOR_COUNT }; #ifdef DEFINE_RADIUSCURSOR_NAMES -static const char *const TheRadiusCursorNames[] = +static const char *const TheRadiusCursorNames[] = { "NONE", "ATTACK_DAMAGE_AREA", @@ -117,34 +117,34 @@ static const char *const TheRadiusCursorNames[] = "OFFENSIVE_SPECIALPOWER", //red "SUPERWEAPON_SCATTER_AREA",//red - "PARTICLECANNON", + "PARTICLECANNON", "A10STRIKE", "CARPETBOMB", "DAISYCUTTER", "PARADROP", - "SPYSATELLITE", + "SPYSATELLITE", "SPECTREGUNSHIP", "HELIX_NAPALM_BOMB", - "NUCLEARMISSILE", + "NUCLEARMISSILE", "EMPPULSE", "ARTILLERYBARRAGE", "NAPALMSTRIKE", "CLUSTERMINES", - "SCUDSTORM", + "SCUDSTORM", "ANTHRAXBOMB", - "AMBUSH", + "AMBUSH", "RADAR", "SPYDRONE", "FRENZY", - + "CLEARMINES", "AMBULANCE", - nullptr + nullptr }; -static_assert(ARRAY_SIZE(TheRadiusCursorNames) == RADIUSCURSOR_COUNT + 1, "Incorrect array size"); +static_assert(ARRAY_SIZE(TheRadiusCursorNames) == RADIUSCURSOR_COUNT + 1, "Incorrect array size"); #endif // ------------------------------------------------------------------------------------------------ @@ -169,7 +169,7 @@ typedef std::list::const_iterator DrawableListCIt; // ------------------------------------------------------------------------------------------------ class SuperweaponInfo : public MemoryPoolObject { - MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(SuperweaponInfo, "SuperweaponInfo") + MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(SuperweaponInfo, "SuperweaponInfo") private: // not saved @@ -187,10 +187,10 @@ class SuperweaponInfo : public MemoryPoolObject Bool hiddenByScience, Bool ready, Bool evaReadyPlayed, - const AsciiString& superweaponNormalFont, - Int superweaponNormalPointSize, + const AsciiString& superweaponNormalFont, + Int superweaponNormalPointSize, Bool superweaponNormalBold, - Color c, + Color c, const SpecialPowerTemplate* spt ); @@ -207,7 +207,7 @@ class SuperweaponInfo : public MemoryPoolObject UnsignedInt m_timestamp; ///< seconds shown in display string Bool m_hiddenByScript; Bool m_hiddenByScience; - Bool m_ready; ///< Stores if we were ready last draw, since readiness can change without time changing + Bool m_ready; ///< Stores if we were ready last draw, since readiness can change without time changing Bool m_evaReadyPlayed; ///< Stores if Eva announced superweapon is ready // not saved, but public Bool m_forceUpdateText; @@ -222,7 +222,7 @@ typedef std::map SuperweaponMap; // Popup message box class PopupMessageData : public MemoryPoolObject { - MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(PopupMessageData, "PopupMessageData") + MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(PopupMessageData, "PopupMessageData") public: UnicodeString message; Int x; @@ -238,7 +238,7 @@ EMPTY_DTOR(PopupMessageData) // ------------------------------------------------------------------------------------------------ class NamedTimerInfo : public MemoryPoolObject { - MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NamedTimerInfo, "NamedTimerInfo") + MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NamedTimerInfo, "NamedTimerInfo") public: AsciiString m_timerName; ///< Timer name, needed on Load to reconstruct Map. UnicodeString timerText; ///< timer text @@ -260,7 +260,7 @@ enum {MAX_SUBTITLE_LINES = 4}; ///< The maximum number of lines a subtitle // Floating Text Data class FloatingTextData : public MemoryPoolObject { - MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(FloatingTextData, "FloatingTextData") + MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(FloatingTextData, "FloatingTextData") public: FloatingTextData(void); //~FloatingTextData(void); @@ -276,7 +276,7 @@ class FloatingTextData : public MemoryPoolObject typedef std::list FloatingTextList; typedef FloatingTextList::iterator FloatingTextListIt; -enum +enum { DEFAULT_FLOATING_TEXT_TIMEOUT = LOGICFRAMES_PER_SECOND/3, }; @@ -316,17 +316,17 @@ typedef WorldAnimationList::iterator WorldAnimationListIterator; // ------------------------------------------------------------------------------------------------ /** Basic functionality common to all in-game user interfaces */ -// ------------------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------------------ class InGameUI : public SubsystemInterface, public Snapshot { - + friend class Drawable; // for selection/deselection transactions - -protected: - - typedef std::list ObjectList; - typedef std::list::iterator ObjectListIt; - + +protected: + + typedef std::list ObjectList; + typedef std::list::iterator ObjectListIt; + public: // *************************************************************************************** enum SelectionRules @@ -366,7 +366,7 @@ friend class Drawable; // for selection/deselection transactions void refreshObserverStatsResources(); void toggleObserverStats() { m_observerStatsHidden = !m_observerStatsHidden; } // Toggle visibility of the observer stats overlay - + // Inherited from subsystem interface ----------------------------------------------------------- virtual void init( void ); ///< Initialize the in-game user interface virtual void update( void ); ///< Update the UI by calling preDraw(), draw(), and postDraw() @@ -386,20 +386,20 @@ friend class Drawable; // for selection/deselection transactions #else virtual void messageColor(const RGBColor* rgbColor, UnicodeString format, ...); ///< display a colored message to the user #endif - virtual void messageNoFormat( const UnicodeString& message ); ///< display a message to the user - virtual void messageNoFormat( const RGBColor *rgbColor, const UnicodeString& message ); ///< display a colored message to the user + virtual void messageNoFormat( const UnicodeString& message ); ///< display a message to the user + virtual void messageNoFormat( const RGBColor *rgbColor, const UnicodeString& message ); ///< display a colored message to the user virtual void message( UnicodeString format, ... ); ///< display a message to the user virtual void message( AsciiString stringManagerLabel, ... );///< display a message to the user virtual void toggleMessages( void ) { m_messagesOn = 1 - m_messagesOn; } ///< toggle messages on/off virtual Bool isMessagesOn( void ) { return m_messagesOn; } ///< are the display messages on void freeMessageResources( void ); ///< free resources for the ui messages - void freeCustomUiResources( void ); ///< free resources for custom ui elements + void freeCustomUiResources( void ); ///< free resources for custom ui elements Color getMessageColor(Bool altColor) { return (altColor)?m_messageColor2:m_messageColor1; } - + // interface for military style messages virtual void militarySubtitle( const AsciiString& label, Int duration ); // time in milliseconds virtual void removeMilitarySubtitle( void ); - + // for can't build messages virtual void displayCantBuildMessage( LegalBuildCode lbc ); ///< display message to use as to why they can't build here @@ -413,7 +413,7 @@ friend class Drawable; // for selection/deselection transactions virtual void createMouseoverHint( const GameMessage *msg ); ///< An object is mouse hovered over, start hint if any virtual void createCommandHint( const GameMessage *msg ); ///< Used by HintSpy. Someone is selected so generate the right Cursor for the potential action virtual void createGarrisonHint( const GameMessage *msg ); ///< A garrison command has occurred, start graphical "hint" - + virtual void addSuperweapon(Int playerIndex, const AsciiString& powerName, ObjectID id, const SpecialPowerTemplate *powerTemplate); virtual Bool removeSuperweapon(Int playerIndex, const AsciiString& powerName, ObjectID id, const SpecialPowerTemplate *powerTemplate); virtual void objectChangedTeam(const Object *obj, Int oldPlayerIndex, Int newPlayerIndex); // notification for superweapons, etc @@ -462,14 +462,14 @@ friend class Drawable; // for selection/deselection transactions virtual const DrawableList *getAllSelectedDrawables( void ) const; ///< Return the list of all the currently selected Drawable IDs. virtual const DrawableList *getAllSelectedLocalDrawables( void ); ///< Return the list of all the currently selected Drawable IDs owned by the current player. virtual Drawable *getFirstSelectedDrawable( void ); ///< get the first selected drawable (if any) - virtual DrawableID getSoloNexusSelectedDrawableID( void ) { return m_soloNexusSelectedDrawableID; } ///< Return the one drawable of the nexus if only 1 angry mob is selected + virtual DrawableID getSoloNexusSelectedDrawableID( void ) { return m_soloNexusSelectedDrawableID; } ///< Return the one drawable of the nexus if only 1 angry mob is selected virtual Bool isDrawableSelected( DrawableID idToCheck ) const; ///< Return true if the selected ID is in the drawable list - virtual Bool areAllObjectsSelected(const std::vector& objectsToCheck) const; ///< Return true if all of the selected objects are in the drawable list - virtual Bool isAnySelectedKindOf( KindOfType kindOf ) const; ///< is any selected object a kind of + virtual Bool areAllObjectsSelected(const std::vector& objectsToCheck) const; ///< Return true if all of the selected objects are in the drawable list + virtual Bool isAnySelectedKindOf( KindOfType kindOf ) const; ///< is any selected object a kind of virtual Bool isAllSelectedKindOf( KindOfType kindOf ) const; ///< are all selected objects a kind of virtual void setRadiusCursor(RadiusCursorType r, const SpecialPowerTemplate* sp, WeaponSlotType wslot); - virtual void setRadiusCursorNone() { setRadiusCursor(RADIUSCURSOR_NONE, nullptr, PRIMARY_WEAPON); } + virtual void setRadiusCursorNone() { setRadiusCursor(RADIUSCURSOR_NONE, nullptr, PRIMARY_WEAPON); } virtual void setInputEnabled( Bool enable ); ///< Set the input enabled or disabled virtual Bool getInputEnabled( void ) { return m_inputEnabled; } ///< Get the current input status @@ -479,21 +479,21 @@ friend class Drawable; // for selection/deselection transactions virtual void preDraw( void ); ///< Logic which needs to occur before the UI renders virtual void draw( void ) = 0; ///< Render the in-game user interface virtual void postDraw( void ); ///< Logic which needs to occur after the UI renders - virtual void postWindowDraw( void ); ///< Logic which needs to occur after the WindowManager has repainted the menus + virtual void postWindowDraw( void ); ///< Logic which needs to occur after the WindowManager has repainted the menus - /// Ingame video playback + /// Ingame video playback virtual void playMovie( const AsciiString& movieName ); virtual void stopMovie( void ); virtual VideoBuffer* videoBuffer( void ); - /// Ingame cameo video playback + /// Ingame cameo video playback virtual void playCameoMovie( const AsciiString& movieName ); virtual void stopCameoMovie( void ); virtual VideoBuffer* cameoVideoBuffer( void ); - // mouse over information + // mouse over information virtual DrawableID getMousedOverDrawableID( void ) const; ///< Get drawble ID of drawable under cursor - + /// Set the ingame flag as to if we have the Quit menu up or not virtual void setQuitMenuVisible( Bool t ) { m_isQuitMenuVisible = t; } virtual Bool isQuitMenuVisible( void ) const { return m_isQuitMenuVisible; } @@ -519,11 +519,11 @@ friend class Drawable; // for selection/deselection transactions virtual Int selectMatchingAcrossMap(); ///< selects matching units across map virtual Int selectMatchingAcrossRegion( IRegion2D *region ); // -1 = no locally-owned selection, 0+ = # of units selected - virtual Int selectAllUnitsByType(KindOfMaskType mustBeSet, KindOfMaskType mustBeClear); - virtual Int selectAllUnitsByTypeAcrossScreen(KindOfMaskType mustBeSet, KindOfMaskType mustBeClear); - virtual Int selectAllUnitsByTypeAcrossMap(KindOfMaskType mustBeSet, KindOfMaskType mustBeClear); - virtual Int selectAllUnitsByTypeAcrossRegion( IRegion2D *region, KindOfMaskType mustBeSet, KindOfMaskType mustBeClear ); - + virtual Int selectAllUnitsByType(KindOfMaskType mustBeSet, KindOfMaskType mustBeClear); + virtual Int selectAllUnitsByTypeAcrossScreen(KindOfMaskType mustBeSet, KindOfMaskType mustBeClear); + virtual Int selectAllUnitsByTypeAcrossMap(KindOfMaskType mustBeSet, KindOfMaskType mustBeClear); + virtual Int selectAllUnitsByTypeAcrossRegion( IRegion2D *region, KindOfMaskType mustBeSet, KindOfMaskType mustBeClear ); + virtual void buildRegion( const ICoord2D *anchor, const ICoord2D *dest, IRegion2D *region ); ///< builds a region around the specified coordinates virtual Bool getDisplayedMaxWarning( void ) { return m_displayedMaxWarning; } @@ -538,7 +538,7 @@ friend class Drawable; // for selection/deselection transactions Bool isDrawableCaptionBold( void ) { return m_drawableCaptionBold; } Color getDrawableCaptionColor( void ) { return m_drawableCaptionColor; } - Bool shouldMoveRMBScrollAnchor( void ) { return m_moveRMBScrollAnchor; } + Bool shouldMoveRMBScrollAnchor( void ) { return m_moveRMBScrollAnchor; } Bool isClientQuiet( void ) const { return m_clientQuiet; } Bool isInWaypointMode( void ) const { return m_waypointMode; } @@ -551,11 +551,11 @@ friend class Drawable; // for selection/deselection transactions void setForceMoveMode( Bool enabled ) { m_forceMoveToMode = enabled; } void setForceAttackMode( Bool enabled ) { m_forceAttackMode = enabled; } void setPreferSelectionMode( Bool enabled ) { m_preferSelection = enabled; } - + void toggleAttackMoveToMode( void ) { m_attackMoveToMode = !m_attackMoveToMode; } Bool isInAttackMoveToMode( void ) const { return m_attackMoveToMode; } void clearAttackMoveToMode( void ) { m_attackMoveToMode = FALSE; } - + void setCameraRotateLeft( Bool set ) { m_cameraRotatingLeft = set; } void setCameraRotateRight( Bool set ) { m_cameraRotatingRight = set; } void setCameraZoomIn( Bool set ) { m_cameraZoomingIn = set; } @@ -571,14 +571,14 @@ friend class Drawable; // for selection/deselection transactions virtual void addIdleWorker( Object *obj ); virtual void removeIdleWorker( Object *obj, Int playerNumber ); virtual void selectNextIdleWorker( void ); - static std::vector getUniqueIdleWorkers(const ObjectList& idleWorkers); + static std::vector getUniqueIdleWorkers(const ObjectList& idleWorkers); virtual void recreateControlBar( void ); - virtual void refreshCustomUiResources( void ); - virtual void refreshNetworkLatencyResources(void); - virtual void refreshRenderFpsResources(void); - virtual void refreshSystemTimeResources( void ); - virtual void refreshGameTimeResources( void ); + virtual void refreshCustomUiResources( void ); + virtual void refreshNetworkLatencyResources(void); + virtual void refreshRenderFpsResources(void); + virtual void refreshSystemTimeResources( void ); + virtual void refreshGameTimeResources( void ); virtual void disableTooltipsUntil(UnsignedInt frameNum); virtual void clearTooltipsDisabled(); @@ -599,14 +599,14 @@ friend class Drawable; // for selection/deselection transactions virtual void resetIdleWorker( void ); - void updateRenderFpsString(); - void drawNetworkLatency(Int &x, Int &y); - void drawRenderFps(Int &x, Int &y); - void drawSystemTime(Int &x, Int &y); - void drawGameTime(); - void drawObserverStats(Int &x, Int &y); - Bool m_observerStatsHidden = false; // hide/show observer overlay - + void updateRenderFpsString(); + void drawNetworkLatency(Int &x, Int &y); + void drawRenderFps(Int &x, Int &y); + void drawSystemTime(Int &x, Int &y); + void drawGameTime(); + void drawObserverStats(Int &x, Int &y); + Bool m_observerStatsHidden = false; // hide/show observer overlay + public: void registerWindowLayout(WindowLayout *layout); // register a layout for updates void unregisterWindowLayout(WindowLayout *layout); // stop updates for this layout @@ -614,16 +614,16 @@ friend class Drawable; // for selection/deselection transactions void triggerDoubleClickAttackMoveGuardHint( void ); - + public: // World 2D animation methods - void addWorldAnimation( Anim2DTemplate *animTemplate, + void addWorldAnimation( Anim2DTemplate *animTemplate, const Coord3D *pos, WorldAnimationOptions options, Real durationInSeconds, Real zRisePerSecond ); -#if defined(RTS_DEBUG) +#if defined(RTS_DEBUG) virtual void DEBUG_addFloatingText(const AsciiString& text,const Coord3D * pos, Color color); #endif @@ -633,7 +633,7 @@ friend class Drawable; // for selection/deselection transactions virtual void xfer( Xfer *xfer ); virtual void loadPostProcess( void ); -protected: +protected: // ---------------------------------------------------------------------------------------------- // Protected Types ------------------------------------------------------------------------------ @@ -649,7 +649,7 @@ friend class Drawable; // for selection/deselection transactions }; // mouse mode interface - enum MouseMode + enum MouseMode { MOUSEMODE_DEFAULT = 0, MOUSEMODE_BUILD_PLACE, @@ -665,6 +665,7 @@ friend class Drawable; // for selection/deselection transactions UnsignedInt money; UnsignedInt cpm; Int xp; + Int rank; Real kd; Int sp; Int powerValue; @@ -696,7 +697,7 @@ friend class Drawable; // for selection/deselection transactions struct MilitarySubtitleData { UnicodeString subtitle; ///< The complete subtitle to be drawn, each line is separated by L"\n" - UnsignedInt index; ///< the current index that we are at through the subtitle + UnsignedInt index; ///< the current index that we are at through the subtitle ICoord2D position; ///< Where on the screen the subtitle should be drawn DisplayString *displayStrings[MAX_SUBTITLE_LINES]; ///< We'll only allow MAX_SUBTITLE_LINES worth of display strings UnsignedInt currentDisplayString; ///< contains the current display string we're on. (also lets us know the last display string allocated @@ -719,26 +720,26 @@ friend class Drawable; // for selection/deselection transactions void incrementSelectCount( void ) { ++m_selectCount; } ///< Increase by one the running total of "selected" drawables void decrementSelectCount( void ) { --m_selectCount; } ///< Decrease by one the running total of "selected" drawables virtual View *createView( void ) = 0; ///< Factory for Views - void evaluateSoloNexus( Drawable *newlyAddedDrawable = nullptr ); + void evaluateSoloNexus( Drawable *newlyAddedDrawable = nullptr ); /// expire a hint from of the specified type at the hint index void expireHint( HintType type, UnsignedInt hintIndex ); - void createControlBar( void ); ///< create the control bar user interface - void createReplayControl( void ); ///< create the replay control window - - void setMouseCursor(Mouse::MouseCursor c); - - -#if defined(GENERALS_ONLINE) - void addMessageText( const UnicodeString& formattedMessage, const RGBColor *rgbColor = nullptr, bool bIsChatMsg = false ); ///< internal workhorse for adding plain text for messages -#else void addMessageText( const UnicodeString& formattedMessage, const RGBColor *rgbColor = nullptr ); ///< internal workhorse for adding plain text for messages -#endif - void removeMessageAtIndex( Int i ); ///< remove the message at index i - - void updateFloatingText( void ); ///< Update function to move our floating text - void drawFloatingText( void ); ///< Draw all our floating text - void clearFloatingText( void ); ///< clear the floating text list + void createControlBar( void ); ///< create the control bar user interface + void createReplayControl( void ); ///< create the replay control window + + void setMouseCursor(Mouse::MouseCursor c); + + +#if defined(GENERALS_ONLINE) + void addMessageText( const UnicodeString& formattedMessage, const RGBColor *rgbColor = nullptr, bool bIsChatMsg = false ); ///< internal workhorse for adding plain text for messages +#else void addMessageText( const UnicodeString& formattedMessage, const RGBColor *rgbColor = nullptr ); ///< internal workhorse for adding plain text for messages +#endif + void removeMessageAtIndex( Int i ); ///< remove the message at index i + + void updateFloatingText( void ); ///< Update function to move our floating text + void drawFloatingText( void ); ///< Draw all our floating text + void clearFloatingText( void ); ///< clear the floating text list void clearWorldAnimations( void ); ///< delete all world animations void updateAndDrawWorldAnimations( void ); ///< update and draw visible world animations @@ -778,9 +779,9 @@ friend class Drawable; // for selection/deselection transactions Int m_maxSelectCount; ///< Max number of objects to select UnsignedInt m_frameSelectionChanged; ///< Frame when the selection last changed. - Int m_duringDoubleClickAttackMoveGuardHintTimer; ///< Frames left to draw the doubleClickFeedbackTimer - Coord3D m_duringDoubleClickAttackMoveGuardHintStashedPosition; - + Int m_duringDoubleClickAttackMoveGuardHintTimer; ///< Frames left to draw the doubleClickFeedbackTimer + Coord3D m_duringDoubleClickAttackMoveGuardHintStashedPosition; + // Video playback data VideoBuffer* m_videoBuffer; ///< video playback buffer VideoStreamInterface* m_videoStream; ///< Video stream; @@ -789,63 +790,63 @@ friend class Drawable; // for selection/deselection transactions VideoBuffer* m_cameoVideoBuffer;///< video playback buffer VideoStreamInterface* m_cameoVideoStream;///< Video stream; - // Network Latency Counter - DisplayString * m_networkLatencyString; - AsciiString m_networkLatencyFont; - Int m_networkLatencyPointSize; - Bool m_networkLatencyBold; - Coord2D m_networkLatencyPosition; - Color m_networkLatencyColor; - Color m_networkLatencyDropColor; - UnsignedInt m_lastNetworkLatencyFrames; - - // Render FPS Counter - DisplayString * m_renderFpsString; - DisplayString * m_renderFpsLimitString; - AsciiString m_renderFpsFont; - Int m_renderFpsPointSize; - Bool m_renderFpsBold; - Coord2D m_renderFpsPosition; - Color m_renderFpsColor; - Color m_renderFpsLimitColor; - Color m_renderFpsDropColor; - UnsignedInt m_renderFpsRefreshMs; - UnsignedInt m_lastRenderFps; - UnsignedInt m_lastRenderFpsLimit; - UnsignedInt m_lastRenderFpsUpdateMs; - - // System Time - DisplayString * m_systemTimeString; - AsciiString m_systemTimeFont; - Int m_systemTimePointSize; - Bool m_systemTimeBold; - Coord2D m_systemTimePosition; - Color m_systemTimeColor; - Color m_systemTimeDropColor; - - // Game Time - DisplayString * m_gameTimeString; - DisplayString * m_gameTimeFrameString; - AsciiString m_gameTimeFont; - Int m_gameTimePointSize; - Bool m_gameTimeBold; - Coord2D m_gameTimePosition; - Color m_gameTimeColor; - Color m_gameTimeDropColor; - + // Network Latency Counter + DisplayString * m_networkLatencyString; + AsciiString m_networkLatencyFont; + Int m_networkLatencyPointSize; + Bool m_networkLatencyBold; + Coord2D m_networkLatencyPosition; + Color m_networkLatencyColor; + Color m_networkLatencyDropColor; + UnsignedInt m_lastNetworkLatencyFrames; + + // Render FPS Counter + DisplayString * m_renderFpsString; + DisplayString * m_renderFpsLimitString; + AsciiString m_renderFpsFont; + Int m_renderFpsPointSize; + Bool m_renderFpsBold; + Coord2D m_renderFpsPosition; + Color m_renderFpsColor; + Color m_renderFpsLimitColor; + Color m_renderFpsDropColor; + UnsignedInt m_renderFpsRefreshMs; + UnsignedInt m_lastRenderFps; + UnsignedInt m_lastRenderFpsLimit; + UnsignedInt m_lastRenderFpsUpdateMs; + + // System Time + DisplayString * m_systemTimeString; + AsciiString m_systemTimeFont; + Int m_systemTimePointSize; + Bool m_systemTimeBold; + Coord2D m_systemTimePosition; + Color m_systemTimeColor; + Color m_systemTimeDropColor; + + // Game Time + DisplayString * m_gameTimeString; + DisplayString * m_gameTimeFrameString; + AsciiString m_gameTimeFont; + Int m_gameTimePointSize; + Bool m_gameTimeBold; + Coord2D m_gameTimePosition; + Color m_gameTimeColor; + Color m_gameTimeDropColor; + // Observer Stats Overlay DisplayString* m_observerStatsString; AsciiString m_observerStatsFont; Int m_observerStatsPointSize; Bool m_observerStatsBold; Coord2D m_observerStatsPosition; - Int m_observerStatsLineStep; - -#if defined(GENERALS_ONLINE) + Int m_observerStatsLineStep; + +#if defined(GENERALS_ONLINE) Color m_colorGood; - Color m_colorBad; -#endif - + Color m_colorBad; +#endif + // message data UIMessage m_uiMessages[ MAX_UI_MESSAGES ];/**< messages to display to the user, the array is organized with newer messages at @@ -854,7 +855,7 @@ friend class Drawable; // for selection/deselection transactions SuperweaponMap m_superweapons[MAX_PLAYER_COUNT]; Coord2D m_superweaponPosition; Real m_superweaponFlashDuration; - + // superweapon timer font info AsciiString m_superweaponNormalFont; Int m_superweaponNormalPointSize; @@ -937,22 +938,22 @@ friend class Drawable; // for selection/deselection transactions PopupMessageData * m_popupMessageData; Color m_popupMessageColor; - + Bool m_waypointMode; ///< are we in waypoint plotting mode? Bool m_forceAttackMode; ///< are we in force attack mode? Bool m_forceMoveToMode; ///< are we in force move mode? Bool m_attackMoveToMode; ///< are we in attack move mode? Bool m_preferSelection; ///< the shift key has been depressed. - Bool m_cameraRotatingLeft; + Bool m_cameraRotatingLeft; Bool m_cameraRotatingRight; Bool m_cameraZoomingIn; Bool m_cameraTrackingDrawable; Bool m_cameraZoomingOut; - + Bool m_drawRMBScrollAnchor; Bool m_moveRMBScrollAnchor; - Bool m_clientQuiet; ///< When the user clicks exit,restart, etc. this is set true + Bool m_clientQuiet; ///< When the user clicks exit,restart, etc. this is set true ///< to skip some client sounds/fx during shutdown // World Animation Data @@ -966,8 +967,8 @@ friend class Drawable; // for selection/deselection transactions DrawableID m_soloNexusSelectedDrawableID; ///< The drawable of the nexus, if only one angry mob is selected, otherwise, null #if defined(GENERALS_ONLINE) - int m_lastFPS = -1; - int m_currentFPS = -1; + int m_lastFPS = -1; + int m_currentFPS = -1; int64_t lastFPSUpdate = -1; #endif @@ -981,3 +982,4 @@ friend class Drawable; // for selection/deselection transactions // the singleton extern InGameUI *TheInGameUI; + diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp index 71f00fa3cb..018258642f 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp @@ -2090,6 +2090,9 @@ void InGameUI::reset( void ) // reset the command bar TheControlBar->reset(); + // Reset the observer overlay visibility + m_observerStatsHidden = false; + TheTacticalView->setDefaultView(0.0f, 0.0f, 1.0f); ResetInGameChat(); @@ -5989,9 +5992,7 @@ void InGameUI::drawObserverStats(Int& x, Int& y) if (!localPlayer || (TheGameLogic && TheGameLogic->getFrame() <= 1)) return; - Bool isObserver = localPlayer->isPlayerObserver(); - Bool isDefeated = TheVictoryConditions && TheVictoryConditions->hasSinglePlayerBeenDefeated(localPlayer); - if (!isObserver && !isDefeated) + if (!localPlayer->isPlayerObserver() && !localPlayer->isPlayerDead()) return; if (!isAtHudAnchorPos(m_observerStatsPosition) || m_observerStatsHidden) @@ -6008,7 +6009,7 @@ void InGameUI::drawObserverStats(Int& x, Int& y) static const Int numCols = 8; static const wchar_t* headers[numCols] = { - L"(T) Name", L"Army", L"Cash", L"Cash/m", L"XP", L"K/D", L"SP", L"Power" + L"(T) Name", L"Army", L"Cash", L"Cash/m", L"(R) XP", L"SP", L"K/D", L"Power" }; static UnsignedInt lastUpdateFrame = 0; @@ -6037,52 +6038,33 @@ void InGameUI::drawObserverStats(Int& x, Int& y) players.clear(); players.reserve(MAX_PLAYER_COUNT); - // These are system players we want to skip - static const char* EXCLUDED_NAMES[] = { - "PlyrCivilian", "PlyrAmerica", "PlyrChina", "PlyrGLA", "Paradrops", - "PlyrChinaTankGeneral", "PlyrAmericaLaserGeneral", "PlyrAmericaAirForceGeneral", - "UncloakedGLA", "PlyrAmericaAirForce", "PlyrChinaTank", "PlyrNeutral" - }; + for (Int slotIndex = 0; slotIndex < MAX_SLOTS; ++slotIndex) { + const GameSlot* slot = TheGameInfo ? TheGameInfo->getConstSlot(slotIndex) : nullptr; + if (!slot || !slot->isOccupied()) + continue; - for (Int i = 0; i < MAX_PLAYER_COUNT; ++i) { - Player* p = ThePlayerList->getNthPlayer(i); + AsciiString nameKeyStr; + nameKeyStr.format("player%d", slotIndex); + const NameKeyType key = TheNameKeyGenerator->nameToKey(nameKeyStr); + Player* p = ThePlayerList->findPlayerWithNameKey(key); if (!p || !p->isPlayerActive()) continue; + if (p->isPlayerObserver()) + continue; + UnicodeString name = p->getPlayerDisplayName(); if (name.isEmpty()) continue; - // Skip system players - AsciiString asciiName; - asciiName.translate(name); - bool skip = false; - for (const char* excluded : EXCLUDED_NAMES) { - if (asciiName == excluded) { - skip = true; - break; - } - } - if (skip) continue; - - // Truncate long names - if (name.getLength() > 8) { + // Truncate long names + if (name.getLength() > 12) { UnicodeString tmp; - tmp.format(L"%.*ls.", 8, name.str()); + tmp.format(L"%.*ls.", 12, name.str()); name = tmp; } - - // Find team - Int team = -1; - if (TheGameInfo) { - for (Int s = 0; s < MAX_SLOTS; ++s) { - const GameSlot* slot = TheGameInfo->getConstSlot(s); - if (slot && slot->isOccupied() && slot->isPlayer(name)) { - team = slot->getTeamNumber(); - break; - } - } - } + + Int team = slot->getTeamNumber(); // Gather stats Money* money = p->getMoney(); @@ -6091,6 +6073,7 @@ void InGameUI::drawObserverStats(Int& x, Int& y) Int kills = sk ? sk->getTotalUnitsDestroyed() : 0; Int deaths = sk ? sk->getTotalUnitsLost() : 0; Real kd = deaths > 0 ? (Real)kills / deaths : (Real)kills; + Int rank = p->getRankLevel(); // Faction abbreviations, we don't want to show full army names like that AsciiString side = p->getSide(); @@ -6114,7 +6097,7 @@ void InGameUI::drawObserverStats(Int& x, Int& y) name, faction, team, money ? money->countMoney() : 0, money ? money->getCashPerMinute() : 0, - p->getSkillPoints(), kd, + p->getSkillPoints(), rank, kd, p->getSciencePurchasePoints(), powerDelta, hasPower, energy && !energy->hasSufficientPower(), @@ -6122,6 +6105,12 @@ void InGameUI::drawObserverStats(Int& x, Int& y) }); } + std::sort(players.begin(), players.end(), + [](const PlayerData& a, const PlayerData& b) { + if (a.team != b.team) + return a.team < b.team; // sort by team first + }); + // Format cash and cash/m with commas auto formatNum = [](UnsignedInt v) -> UnicodeString { std::wstring s = std::to_wstring(v); @@ -6158,14 +6147,13 @@ void InGameUI::drawObserverStats(Int& x, Int& y) cells[1] = pd.faction; cells[2] = formatNum(pd.money); cells[3].format(L"+%ls", formatNum(pd.cpm).str()); - cells[4].format(L"%d", pd.xp); - cells[5].format(L"%.1f", pd.kd); - cells[6].format(L"%d", pd.sp); - cells[7] = pd.showPower ? (pd.lowPower ? L"OFF/" : L"ON/") : L"-"; + cells[4].format(L"(%d) %d", pd.rank, pd.xp); + cells[5].format(L"%d", pd.sp); + cells[6].format(L"%.1f", pd.kd); if (pd.showPower) { - UnicodeString tmp; - tmp.format(pd.lowPower ? L"OFF/%d" : L"ON/%d", pd.powerValue); - cells[7] = tmp; + cells[7].format(pd.lowPower ? L"OFF (%d)" : L"ON (%d)", pd.powerValue); + } else { + cells[7] = L"-"; } for (Int i = 0; i < numCols; ++i) { @@ -6229,7 +6217,7 @@ void InGameUI::drawObserverStats(Int& x, Int& y) Int contentY = baseY + padY; // Draw background - TheWindowManager->winFillRect(TheWindowManager->winMakeColor(0, 0, 0, 140), 1, baseX, baseY, baseX + bgW, baseY + bgH); + TheWindowManager->winFillRect(TheWindowManager->winMakeColor(0, 0, 0, 180), 1, baseX, baseY, baseX + bgW, baseY + bgH); // Draw border Color border = TheWindowManager->winMakeColor(255, 255, 255, 225); @@ -6283,7 +6271,7 @@ void InGameUI::refreshObserverStatsResources(void) Int adjustedFontSize = TheGlobalLanguageData->adjustFontSize(m_observerStatsPointSize); GameFont* statsFont = TheWindowManager->winFindFont(m_observerStatsFont, adjustedFontSize, m_observerStatsBold); m_observerStatsString->setFont(statsFont); - m_observerStatsLineStep = adjustedFontSize + 10; // vertical spacing between lines + m_observerStatsLineStep = statsFont ? statsFont->height + 2 : adjustedFontSize + 2; // Line spacing based on real font height } void InGameUI::refreshCustomUiResources(void)