Skip to content

Commit fe1ec22

Browse files
committed
feat(radar): Save Radar hidden and forced status for each Player to show correct radar states when switching teams (#1715)
1 parent a20744f commit fe1ec22

File tree

22 files changed

+197
-153
lines changed

22 files changed

+197
-153
lines changed

Core/GameEngine/Include/Common/GameUtility.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
#pragma once
2020

21+
#include "Lib/BaseType.h"
22+
2123
// For miscellaneous game utility functions.
2224

2325
class Player;
@@ -26,7 +28,8 @@ typedef Int PlayerIndex;
2628
namespace rts
2729
{
2830

29-
Bool localPlayerIsObserving();
31+
bool localPlayerIsObserving();
32+
bool localPlayerHasRadar();
3033
Player* getObservedOrLocalPlayer(); ///< Get the current observed or local player. Is never null.
3134
Player* getObservedOrLocalPlayer_Safe(); ///< Get the current observed or local player. Is never null, except when the application does not have players.
3235
PlayerIndex getObservedOrLocalPlayerIndex_Safe(); ///< Get the current observed or local player index. Returns 0 when the application does not have players.

Core/GameEngine/Source/Common/GameUtility.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ static void changePlayerCommon(Player* player)
4949

5050
} // namespace detail
5151

52-
Bool localPlayerIsObserving()
52+
bool localPlayerIsObserving()
5353
{
5454
if (TheGameLogic->isInReplayGame() || TheGameLogic->isInShellGame())
5555
return true;
@@ -60,6 +60,22 @@ Bool localPlayerIsObserving()
6060
return false;
6161
}
6262

63+
bool localPlayerHasRadar()
64+
{
65+
// Using "local" instead of "observed or local" player because as an observer we prefer
66+
// the radar to be turned on when observing a player that has no radar.
67+
const Player* player = ThePlayerList->getLocalPlayer();
68+
const PlayerIndex index = player->getPlayerIndex();
69+
70+
if (TheRadar->isRadarForced(index))
71+
return true;
72+
73+
if (!TheRadar->isRadarHidden(index) && player->hasRadar())
74+
return true;
75+
76+
return false;
77+
}
78+
6379
Player* getObservedOrLocalPlayer()
6480
{
6581
DEBUG_ASSERTCRASH(TheControlBar != NULL, ("TheControlBar is NULL"));

Generals/Code/GameEngine/Include/Common/Radar.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,9 @@ class Radar : public Snapshot,
180180
Bool radarToWorld( const ICoord2D *radar, Coord3D *world ); ///< radar point to world point on terrain
181181
Bool radarToWorld2D( const ICoord2D *radar, Coord3D *world ); ///< radar point to world point (x,y only!)
182182
Bool worldToRadar( const Coord3D *world, ICoord2D *radar ); ///< translate world point to radar (x,y)
183-
Bool localPixelToRadar( const ICoord2D *pixel, ICoord2D *radar ); ///< translate pixel (with UL of radar being (0,0)) to logical radar coords
183+
Bool localPixelToRadar( const ICoord2D *pixel, ICoord2D *radar ); ///< translate pixel (with UL of radar being (0,0)) to logical radar coordinates
184184
Bool screenPixelToWorld( const ICoord2D *pixel, Coord3D *world ); ///< translate pixel (with UL of the screen being (0,0)) to world position in the world
185-
Object *objectUnderRadarPixel( const ICoord2D *pixel ); ///< return the object (if any) represented by the pixel coords passed in
185+
Object *objectUnderRadarPixel( const ICoord2D *pixel ); ///< return the object (if any) represented by the pixel coordinates passed in
186186
void findDrawPositions( Int startX, Int startY, Int width, Int height,
187187
ICoord2D *ul, ICoord2D *lr ); ///< make translation for screen area of radar square to scaled aspect ratio preserving points inside the radar area
188188

@@ -203,22 +203,22 @@ class Radar : public Snapshot,
203203
virtual RadarObjectType removeObject( Object *obj ); ///< remove object from radar
204204

205205
// radar options
206-
void hide( Bool hide ) { m_radarHidden = hide; } ///< hide/unhide the radar
207-
Bool isRadarHidden( void ) { return m_radarHidden; } ///< is radar hidden
206+
void hide( Int playerIndex, Bool hide ) { m_radarHidden[playerIndex] = hide; } ///< hide/show the radar
207+
Bool isRadarHidden( Int playerIndex ) { return m_radarHidden[playerIndex]; } ///< is radar hidden
208208
// other radar option methods here like the ability to show a certain
209209
// team, show buildings, show units at all, etc
210210

211211
// forcing the radar on/off regardless of player situation
212-
void forceOn( Bool force ) { m_radarForceOn = force; } ///< force the radar to be on
213-
Bool isRadarForced( void ) { return m_radarForceOn; } ///< is radar forced on?
212+
void forceOn( Int playerIndex, Bool force ) { m_radarForceOn[playerIndex] = force; } ///< force the radar to be on
213+
Bool isRadarForced( Int playerIndex ) { return m_radarForceOn[playerIndex]; } ///< is radar forced on?
214214

215215
/// refresh the water values for the radar
216216
virtual void refreshTerrain( TerrainLogic *terrain );
217217

218218
/// refresh the radar when the state of world objects changes drastically
219219
virtual void refreshObjects() {};
220220

221-
/// queue a refresh of the terran at the next available time
221+
/// queue a refresh of the terrain at the next available time
222222
virtual void queueTerrainRefresh( void );
223223

224224
virtual void newMap( TerrainLogic *terrain ); ///< reset radar for new map
@@ -252,11 +252,11 @@ class Radar : public Snapshot,
252252

253253
void clearAllEvents( void ); ///< remove all radar events in progress
254254

255-
// search the object list for an object that maps to the given logical radar coords
255+
// search the object list for an object that maps to the given logical radar coordinates
256256
Object *searchListForRadarLocationMatch( RadarObject *listHead, ICoord2D *radarMatch );
257257

258-
Bool m_radarHidden; ///< true when radar is not visible
259-
Bool m_radarForceOn; ///< true when radar is forced to be on
258+
Bool m_radarHidden[MAX_PLAYER_COUNT]; ///< true when radar is not visible
259+
Bool m_radarForceOn[MAX_PLAYER_COUNT]; ///< true when radar is forced to be on
260260
RadarObject *m_objectList; ///< list of objects in the radar
261261
RadarObject *m_localObjectList; /** list of objects for the local player, sorted
262262
* in exactly the same priority as the regular

Generals/Code/GameEngine/Source/Common/System/Radar.cpp

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ Radar::Radar( void )
214214
m_radarWindow = NULL;
215215
m_objectList = NULL;
216216
m_localObjectList = NULL;
217-
m_radarHidden = false;
218-
m_radarForceOn = false;
217+
std::fill(m_radarHidden, m_radarHidden + ARRAY_SIZE(m_radarHidden), false);
218+
std::fill(m_radarForceOn, m_radarForceOn + ARRAY_SIZE(m_radarForceOn), false);
219219
m_terrainAverageZ = 0.0f;
220220
m_waterAverageZ = 0.0f;
221221
m_xSample = 0.0f;
@@ -291,8 +291,11 @@ void Radar::reset( void )
291291
// clear all events
292292
clearAllEvents();
293293

294+
// TheSuperHackers @todo Reset m_radarHidden?
295+
//std::fill(m_radarHidden, m_radarHidden + ARRAY_SIZE(m_radarHidden), false);
296+
294297
// stop forcing the radar on
295-
m_radarForceOn = false;
298+
std::fill(m_radarForceOn, m_radarForceOn + ARRAY_SIZE(m_radarForceOn), false);
296299

297300
}
298301

@@ -1484,21 +1487,46 @@ static void xferRadarObjectList( Xfer *xfer, RadarObject **head )
14841487
// ------------------------------------------------------------------------------------------------
14851488
/** Xfer Method
14861489
* Version Info:
1487-
* 1: Initial version */
1490+
* 1: Initial version
1491+
* 2: TheSuperHackers @tweak Serialize m_radarHidden, m_radarForceOn for each player
1492+
*/
14881493
// ------------------------------------------------------------------------------------------------
14891494
void Radar::xfer( Xfer *xfer )
14901495
{
14911496

14921497
// version
1498+
#if RETAIL_COMPATIBLE_XFER_SAVE
14931499
XferVersion currentVersion = 1;
1500+
#else
1501+
XferVersion currentVersion = 2;
1502+
#endif
14941503
XferVersion version = currentVersion;
14951504
xfer->xferVersion( &version, currentVersion );
14961505

1497-
// radar hidden
1498-
xfer->xferBool( &m_radarHidden );
14991506

1500-
// radar force on
1501-
xfer->xferBool( &m_radarForceOn );
1507+
if (version <= 1)
1508+
{
1509+
const Int localPlayerIndex = ThePlayerList->getLocalPlayer()->getPlayerIndex();
1510+
Bool value;
1511+
1512+
// radar hidden
1513+
value = m_radarHidden[localPlayerIndex];
1514+
xfer->xferBool( &value );
1515+
m_radarHidden[localPlayerIndex] = value;
1516+
1517+
// radar force on
1518+
value = m_radarForceOn[localPlayerIndex];
1519+
xfer->xferBool( &value );
1520+
m_radarForceOn[localPlayerIndex] = value;
1521+
}
1522+
else
1523+
{
1524+
static_assert(sizeof(m_radarHidden) == 16, "Increase version if size changes");
1525+
xfer->xferUser(&m_radarHidden, sizeof(m_radarHidden));
1526+
1527+
static_assert(sizeof(m_radarForceOn) == 16, "Increase version if size changes");
1528+
xfer->xferUser(&m_radarForceOn, sizeof(m_radarForceOn));
1529+
}
15021530

15031531
// save our local object list
15041532
xferRadarObjectList( xfer, &m_localObjectList );

Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
3232
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
3333

34+
#include "Common/GameUtility.h"
3435
#include "Common/NameKeyGenerator.h"
3536
#include "Common/Player.h"
3637
#include "Common/PlayerList.h"
@@ -64,15 +65,11 @@ WindowLayout *popupCommunicatorLayout = NULL;
6465
WindowMsgHandledType LeftHUDInput( GameWindow *window, UnsignedInt msg,
6566
WindowMsgData mData1, WindowMsgData mData2 )
6667
{
67-
68-
// get player
69-
Player *player = ThePlayerList->getLocalPlayer();
70-
7168
//
7269
// if the player doesn't have a radar, or the radar is hidden, and the radar is not being
7370
// forced to on, we just eat input over the radar window
7471
//
75-
if( !TheRadar->isRadarForced() && (TheRadar->isRadarHidden() || !player->hasRadar()) )
72+
if( !rts::localPlayerHasRadar() )
7673
return MSG_HANDLED;
7774

7875
// If the middle mouse button is depressed, then just let the message fall all the
@@ -152,15 +149,14 @@ WindowMsgHandledType LeftHUDInput( GameWindow *window, UnsignedInt msg,
152149

153150
// is the mouse in the radar window
154151
ICoord2D radar;
155-
if( (TheRadar->isRadarHidden() == FALSE || TheRadar->isRadarForced()) &&
156-
TheRadar->localPixelToRadar( &mouse, &radar ) )
152+
if( TheRadar->localPixelToRadar( &mouse, &radar ) )
157153
{
158154

159155
/*
160156
//
161157
// this is an example piece of code to find the object under the pixel position
162158
// of the radar ... should we in the future wish to allow commands to be executed
163-
// on objects throught he radar. note tho that this is extremely hard to do because
159+
// on objects through the radar. note tho that this is extremely hard to do because
164160
// the pixels on the radar are very small and it's hard to do accurate targeting
165161
//
166162
@@ -252,9 +248,8 @@ WindowMsgHandledType LeftHUDInput( GameWindow *window, UnsignedInt msg,
252248
// completely drawn with the radar ... so it's just a translation from
253249
// our window size we're drawing into to the radar cell size
254250
//
255-
if( (TheRadar->isRadarHidden() == FALSE || TheRadar->isRadarForced()) &&
256-
TheRadar->localPixelToRadar( &mouse, &radar ) &&
257-
TheRadar->radarToWorld( &radar, &world ) )
251+
if( TheRadar->localPixelToRadar( &mouse, &radar ) &&
252+
TheRadar->radarToWorld( &radar, &world ) )
258253
{
259254

260255
// No drawables, or a right click automatically means its a look at.

Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,13 +1356,7 @@ void InGameUI::handleRadiusCursor()
13561356
// from screen to world
13571357
// But only if the radar is on.
13581358
//
1359-
Bool radarOn = TheRadar->isRadarForced()
1360-
|| ( !TheRadar->isRadarHidden()
1361-
&& ThePlayerList->getLocalPlayer()
1362-
&& ThePlayerList->getLocalPlayer()->hasRadar()
1363-
);
1364-
1365-
if( !radarOn || (TheRadar->screenPixelToWorld( &mouseIO->pos, &pos ) == FALSE) )// if radar off, or point not on radar
1359+
if( !rts::localPlayerHasRadar() || (TheRadar->screenPixelToWorld( &mouseIO->pos, &pos ) == FALSE) )// if radar off, or point not on radar
13661360
TheTacticalView->screenToTerrain( &mouseIO->pos, &pos );
13671361

13681362
m_curRadiusCursor.setPosition(pos); //world space position of center of decal
@@ -2693,10 +2687,7 @@ void InGameUI::createCommandHint( const GameMessage *msg )
26932687
setMouseCursor( Mouse::GENERIC_INVALID );
26942688
else if( drawSelectable && obj->isLocallyControlled() && !obj->isKindOf(KINDOF_MINE))
26952689
setMouseCursor( Mouse::SELECTING );
2696-
else if( TheRadar->isRadarWindow( window ) &&
2697-
TheRadar->isRadarForced() == FALSE &&
2698-
(TheRadar->isRadarHidden() ||
2699-
ThePlayerList->getLocalPlayer()->hasRadar() == FALSE) )
2690+
else if( TheRadar->isRadarWindow( window ) && !rts::localPlayerHasRadar() )
27002691
setMouseCursor( Mouse::ARROW );
27012692
else
27022693
setMouseCursor( Mouse::MOVETO );

Generals/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2876,18 +2876,11 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
28762876
//-----------------------------------------------------------------------------------------
28772877
case GameMessage::MSG_META_VIEW_LAST_RADAR_EVENT:
28782878
{
2879-
// Player *player = ThePlayerList->getLocalPlayer();
2879+
// You don't need radar for the space bar. That's silly.
2880+
Coord3D lastEvent;
28802881

2881-
// if the local player has a radar, center on last event (if any)
2882-
// Excuse me? You don't need radar for the spacebar. That's silly.
2883-
// if( TheRadar->isRadarForced() || ( TheRadar->isRadarHidden() == false && player->hasRadar() ) )
2884-
{
2885-
Coord3D lastEvent;
2886-
2887-
if( TheRadar->getLastEventLoc( &lastEvent ) )
2888-
TheTacticalView->lookAt( &lastEvent );
2889-
2890-
}
2882+
if( TheRadar->getLastEventLoc( &lastEvent ) )
2883+
TheTacticalView->lookAt( &lastEvent );
28912884

28922885
disp = DESTROY_MESSAGE;
28932886
break;

Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2874,15 +2874,15 @@ void ScriptActions::doTeamRadarCreateEvent(const AsciiString& teamName, Int even
28742874
//-------------------------------------------------------------------------------------------------
28752875
void ScriptActions::doRadarDisable(void)
28762876
{
2877-
TheRadar->hide(true);
2877+
TheRadar->hide(ThePlayerList->getLocalPlayer()->getPlayerIndex(), true);
28782878
}
28792879

28802880
//-------------------------------------------------------------------------------------------------
28812881
/** doRadarEnable */
28822882
//-------------------------------------------------------------------------------------------------
28832883
void ScriptActions::doRadarEnable(void)
28842884
{
2885-
TheRadar->hide(false);
2885+
TheRadar->hide(ThePlayerList->getLocalPlayer()->getPlayerIndex(), false);
28862886
}
28872887

28882888
//-------------------------------------------------------------------------------------------------
@@ -4789,15 +4789,15 @@ void ScriptActions::doDestroyAllContained(const AsciiString& unitName, Int damag
47894789
//-------------------------------------------------------------------------------------------------
47904790
void ScriptActions::doRadarForceEnable(void)
47914791
{
4792-
TheRadar->forceOn(true);
4792+
TheRadar->forceOn(ThePlayerList->getLocalPlayer()->getPlayerIndex(), true);
47934793
}
47944794

47954795
//-------------------------------------------------------------------------------------------------
47964796
/** doRadarRevertNormal */
47974797
//-------------------------------------------------------------------------------------------------
47984798
void ScriptActions::doRadarRevertNormal(void)
47994799
{
4800-
TheRadar->forceOn(false);
4800+
TheRadar->forceOn(ThePlayerList->getLocalPlayer()->getPlayerIndex(), false);
48014801
}
48024802

48034803
//-------------------------------------------------------------------------------------------------

Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/VictoryConditions.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "Common/GameAudio.h"
3333
#include "Common/GameCommon.h"
3434
#include "Common/GameEngine.h"
35+
#include "Common/GameUtility.h"
3536
#include "Common/KindOf.h"
3637
#include "Common/PlayerList.h"
3738
#include "Common/Player.h"
@@ -140,7 +141,7 @@ void VictoryConditions::reset( void )
140141
//-------------------------------------------------------------------------------------------------
141142
void VictoryConditions::update( void )
142143
{
143-
if (!TheRecorder->isMultiplayer() || (m_localSlotNum == -1 && !m_isObserver))
144+
if (!TheRecorder->isMultiplayer() || (m_localSlotNum < 0 && !m_isObserver))
144145
return;
145146

146147
// Check for a single winning alliance
@@ -226,7 +227,7 @@ void VictoryConditions::update( void )
226227
//MessageBoxOk(TheGameText->fetch("GUI:Defeat"), TheGameText->fetch("GUI:LocalDefeat"), NULL);
227228
}
228229
m_localPlayerDefeated = true; // don't check again
229-
TheRadar->forceOn(TRUE);
230+
TheRadar->forceOn(localPlayer->getPlayerIndex(), TRUE);
230231
SetInGameChatType( INGAME_CHAT_EVERYONE ); // can't chat to allies after death. Only to other observers.
231232
}
232233
}
@@ -326,8 +327,6 @@ void VictoryConditions::cachePlayerPtrs( void )
326327
if (m_localSlotNum < 0)
327328
{
328329
m_localPlayerDefeated = true; // if we have no local player, don't check for defeat
329-
DEBUG_ASSERTCRASH(TheRadar, ("No Radar!"));
330-
TheRadar->forceOn(TRUE);
331330
m_isObserver = true;
332331
}
333332
}

0 commit comments

Comments
 (0)