/*
** Command & Conquer Generals Zero Hour(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: ControlBarObserver.cpp /////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Electronic Arts Pacific.
//
// Confidential Information
// Copyright (C) 2002 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// created: Aug 2002
//
// Filename: ControlBarObserver.cpp
//
// author: Chris Huybregts
//
// purpose: All things related to the Observer Control bar, are in here.
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// USER INCLUDES //////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
#include "Common/NameKeyGenerator.h"
#include "Common/PlayerList.h"
#include "Common/Player.h"
#include "Common/PlayerTemplate.h"
#include "Common/KindOf.h"
#include "Common/Recorder.h"
#include "GameClient/ControlBar.h"
#include "GameClient/GameWindowManager.h"
#include "GameClient/GadgetPushButton.h"
#include "GameClient/GadgetStaticText.h"
#include "GameClient/GameText.h"
#include "GameNetwork/NetworkDefs.h"
//-----------------------------------------------------------------------------
// DEFINES ////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
enum { MAX_BUTTONS = 8};
static NameKeyType buttonPlayerID[MAX_BUTTONS] = { NAMEKEY_INVALID,NAMEKEY_INVALID,
NAMEKEY_INVALID,NAMEKEY_INVALID,
NAMEKEY_INVALID,NAMEKEY_INVALID,
NAMEKEY_INVALID,NAMEKEY_INVALID };
static NameKeyType staticTextPlayerID[MAX_BUTTONS] = { NAMEKEY_INVALID,NAMEKEY_INVALID,
NAMEKEY_INVALID,NAMEKEY_INVALID,
NAMEKEY_INVALID,NAMEKEY_INVALID,
NAMEKEY_INVALID,NAMEKEY_INVALID };
static GameWindow *ObserverPlayerInfoWindow = NULL;
static GameWindow *ObserverPlayerListWindow = NULL;
static GameWindow *buttonPlayer[MAX_BUTTONS] = {NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL };
static GameWindow *staticTextPlayer[MAX_BUTTONS] = {NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL };
static NameKeyType buttonCancelID = NAMEKEY_INVALID;
static GameWindow *winFlag = NULL;
static GameWindow *winGeneralPortrait = NULL;
static GameWindow *staticTextNumberOfUnits = NULL;
static GameWindow *staticTextNumberOfBuildings = NULL;
static GameWindow *staticTextNumberOfUnitsKilled = NULL;
static GameWindow *staticTextNumberOfUnitsLost = NULL;
static GameWindow *staticTextPlayerName = NULL;
//-----------------------------------------------------------------------------
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
void ControlBar::initObserverControls( void )
{
ObserverPlayerInfoWindow = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:ObserverPlayerInfoWindow"));
ObserverPlayerListWindow = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:ObserverPlayerListWindow"));
for (Int i = 0; i < MAX_BUTTONS; i++)
{
AsciiString tmpString;
tmpString.format("ControlBar.wnd:ButtonPlayer%d", i);
buttonPlayerID[i] = TheNameKeyGenerator->nameToKey( tmpString );
buttonPlayer[i] = TheWindowManager->winGetWindowFromId( ObserverPlayerListWindow, buttonPlayerID[i] );
tmpString.format("ControlBar.wnd:StaticTextPlayer%d", i);
staticTextPlayerID[i] = TheNameKeyGenerator->nameToKey( tmpString );
staticTextPlayer[i] = TheWindowManager->winGetWindowFromId( ObserverPlayerListWindow, staticTextPlayerID[i] );
}
staticTextNumberOfUnits = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:StaticTextNumberOfUnits"));
staticTextNumberOfBuildings = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:StaticTextNumberOfBuildings"));
staticTextNumberOfUnitsKilled = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:StaticTextNumberOfUnitsKilled"));
staticTextNumberOfUnitsLost = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:StaticTextNumberOfUnitsLost"));
staticTextPlayerName = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:StaticTextPlayerName"));
winFlag = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:WinFlag"));
winGeneralPortrait = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:WinGeneralPortrait"));
buttonCancelID = TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonCancel");
}
//-------------------------------------------------------------------------------------------------
/** System callback for the ControlBarObserverSystem */
//-------------------------------------------------------------------------------------------------
WindowMsgHandledType ControlBarObserverSystem( GameWindow *window, UnsignedInt msg,
WindowMsgData mData1, WindowMsgData mData2 )
{
static NameKeyType buttonCommunicator = NAMEKEY_INVALID;
switch( msg )
{
// --------------------------------------------------------------------------------------------
case GWM_CREATE:
{
break;
} // end create
//---------------------------------------------------------------------------------------------
case GBM_MOUSE_ENTERING:
case GBM_MOUSE_LEAVING:
{
break;
}
//---------------------------------------------------------------------------------------------
case GBM_SELECTED:
case GBM_SELECTED_RIGHT:
{
GameWindow *control = (GameWindow *)mData1;
Int controlID = control->winGetWindowId();
if( controlID == buttonCancelID)
{
TheControlBar->setObserverLookAtPlayer(NULL);
ObserverPlayerInfoWindow->winHide(TRUE);
ObserverPlayerListWindow->winHide(FALSE);
TheControlBar->populateObserverList();
}
for(Int i = 0; i winHide(FALSE);
ObserverPlayerListWindow->winHide(TRUE);
TheControlBar->setObserverLookAtPlayer((Player *) GadgetButtonGetData( buttonPlayer[i]));
if(TheControlBar->getObserverLookAtPlayer())
TheControlBar->populateObserverInfoWindow();
return MSG_HANDLED;
}
}
// if( controlID == buttonCommunicator && TheGameLogic->getGameMode() == GAME_INTERNET )
/*
{
popupCommunicatorLayout = TheWindowManager->winCreateLayout( AsciiString( "Menus/PopupCommunicator.wnd" ) );
popupCommunicatorLayout->runInit();
popupCommunicatorLayout->hide( FALSE );
popupCommunicatorLayout->bringForward();
}
*/
break;
} // end button selected
//---------------------------------------------------------------------------------------------
default:
return MSG_IGNORED;
} // end switch( msg )
return MSG_HANDLED;
} // end ControlBarSystem
//-----------------------------------------------------------------------------
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
void ControlBar::populateObserverList( void )
{
Int currentButton = 0, i;
if(TheRecorder->isMultiplayer())
{
for (i = 0; i < MAX_SLOTS; ++i)
{
AsciiString name;
name.format("player%d", i);
Player *p = ThePlayerList->findPlayerWithNameKey(TheNameKeyGenerator->nameToKey(name));
if(p)
{
if(p->isPlayerObserver())
continue;
DEBUG_ASSERTCRASH(currentButton < MAX_BUTTONS, ("ControlBar::populateObserverList trying to populate more buttons then we have"));
GadgetButtonSetData(buttonPlayer[currentButton], (void *)p);
GadgetButtonSetEnabledImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getEnabledImage() );
//GadgetButtonSetHiliteImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getHiliteImage() );
//GadgetButtonSetHiliteSelectedImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getPushedImage() );
//GadgetButtonSetDisabledImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getDisabledImage() );
buttonPlayer[currentButton]->winSetTooltip(p->getPlayerDisplayName());
buttonPlayer[currentButton]->winHide(FALSE);
buttonPlayer[currentButton]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES );
const GameSlot *slot = TheGameInfo->getConstSlot(currentButton);
Color playerColor = p->getPlayerColor();
Color backColor = GameMakeColor(0, 0, 0, 255);
staticTextPlayer[currentButton]->winSetEnabledTextColors( playerColor, backColor );
staticTextPlayer[currentButton]->winHide(FALSE);
AsciiString teamStr;
teamStr.format("Team:%d", slot->getTeamNumber() + 1);
if (slot->isAI() && slot->getTeamNumber() == -1)
teamStr = "Team:AI";
UnicodeString text;
text.format(TheGameText->fetch("CONTROLBAR:ObsPlayerLabel"), p->getPlayerDisplayName().str(),
TheGameText->fetch(teamStr).str());
GadgetStaticTextSetText(staticTextPlayer[currentButton], text );
++currentButton;
}
}
for(currentButton; currentButtonwinHide(TRUE);
staticTextPlayer[currentButton]->winHide(TRUE);
}
}
else
{
for(i =0; i < MAX_PLAYER_COUNT; ++i)
{
Player *p = ThePlayerList->getNthPlayer(i);
if(p && !p->isPlayerObserver() && p->getPlayerType() == PLAYER_HUMAN)
{
DEBUG_ASSERTCRASH(currentButton < MAX_BUTTONS, ("ControlBar::populateObserverList trying to populate more buttons then we have"));
GadgetButtonSetData(buttonPlayer[currentButton], (void *)p);
GadgetButtonSetEnabledImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getEnabledImage() );
//GadgetButtonSetHiliteImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getHiliteImage() );
//GadgetButtonSetHiliteSelectedImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getPushedImage() );
//GadgetButtonSetDisabledImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getDisabledImage() );
buttonPlayer[currentButton]->winSetTooltip(p->getPlayerDisplayName());
buttonPlayer[currentButton]->winHide(FALSE);
buttonPlayer[currentButton]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES );
Color playerColor = p->getPlayerColor();
Color backColor = GameMakeColor(0, 0, 0, 255);
staticTextPlayer[currentButton]->winSetEnabledTextColors( playerColor, backColor );
staticTextPlayer[currentButton]->winHide(FALSE);
GadgetStaticTextSetText(staticTextPlayer[currentButton], p->getPlayerDisplayName());
++currentButton;
break;
}
}
for(currentButton; currentButtonwinHide(TRUE);
staticTextPlayer[currentButton]->winHide(TRUE);
}
}
}
void ControlBar::populateObserverInfoWindow ( void )
{
if(ObserverPlayerInfoWindow->winIsHidden())
return;
if( !m_observerLookAtPlayer )
{
ObserverPlayerInfoWindow->winHide(TRUE);
ObserverPlayerListWindow->winHide(FALSE);
populateObserverList();
return;
}
UnicodeString uString;
KindOfMaskType mask,clearmask;
mask.set(KINDOF_SCORE);
clearmask.set(KINDOF_STRUCTURE);
uString.format(L"%d",m_observerLookAtPlayer->countObjects(mask,clearmask));
GadgetStaticTextSetText(staticTextNumberOfUnits, uString);
Int numBuildings = 0;
mask.clear();
mask.set(KINDOF_SCORE);
mask.set(KINDOF_STRUCTURE);
clearmask.clear();
numBuildings = m_observerLookAtPlayer->countObjects(mask,clearmask);
mask.clear();
mask.set(KINDOF_SCORE_CREATE);
mask.set(KINDOF_STRUCTURE);
numBuildings += m_observerLookAtPlayer->countObjects(mask,clearmask);
mask.clear();
mask.set(KINDOF_SCORE_DESTROY);
mask.set(KINDOF_STRUCTURE);
numBuildings += m_observerLookAtPlayer->countObjects(mask,clearmask);
uString.format(L"%d",numBuildings);
GadgetStaticTextSetText(staticTextNumberOfBuildings, uString);
uString.format(L"%d",m_observerLookAtPlayer->getScoreKeeper()->getTotalUnitsDestroyed());
GadgetStaticTextSetText(staticTextNumberOfUnitsKilled, uString);
uString.format(L"%d",m_observerLookAtPlayer->getScoreKeeper()->getTotalUnitsLost());
GadgetStaticTextSetText(staticTextNumberOfUnitsLost, uString);
GadgetStaticTextSetText(staticTextPlayerName, m_observerLookAtPlayer->getPlayerDisplayName());
Color color = m_observerLookAtPlayer->getPlayerColor();
staticTextPlayerName->winSetEnabledTextColors(color, GameMakeColor(0,0,0,255));
winFlag->winSetEnabledImage(0, m_observerLookAtPlayer->getPlayerTemplate()->getFlagWaterMarkImage());
winGeneralPortrait->winHide(FALSE);
}