2009-05-08 13:28:41 +00:00
/*
* OpenClonk , http : //www.openclonk.org
*
2013-12-17 20:01:09 +00:00
* Copyright ( c ) 2008 - 2009 , RedWolf Design GmbH , http : //www.clonk.de/
2016-04-03 18:18:29 +00:00
* Copyright ( c ) 2009 - 2016 , The OpenClonk Team and contributors
2009-05-08 13:28:41 +00:00
*
2013-12-17 20:01:09 +00:00
* Distributed under the terms of the ISC license ; see accompanying file
* " COPYING " for details .
2009-05-08 13:28:41 +00:00
*
2013-12-17 20:01:09 +00:00
* " Clonk " is a registered trademark of Matthes Bender , used with permission .
* See accompanying file " TRADEMARK " for details .
2009-05-08 13:28:41 +00:00
*
2013-12-17 20:01:09 +00:00
* To redistribute this file separately , substitute the full license texts
* for the above references .
2009-05-08 13:28:41 +00:00
*/
// player listbox used in lobby and game over dlg
2016-04-03 18:07:56 +00:00
# include "C4Include.h"
# include "gui/C4PlayerInfoListBox.h"
2009-05-08 13:28:41 +00:00
2017-04-30 08:49:09 +00:00
# include "control/C4GameControl.h"
2016-04-03 18:07:56 +00:00
# include "control/C4PlayerInfo.h"
2017-04-30 08:49:09 +00:00
# include "control/C4RoundResults.h"
2016-04-03 18:07:56 +00:00
# include "control/C4Teams.h"
2016-10-20 21:42:46 +00:00
# include "graphics/C4Draw.h"
2017-04-30 08:49:09 +00:00
# include "graphics/C4GraphicsResource.h"
# include "gui/C4FileSelDlg.h"
# include "gui/C4GameLobby.h"
2016-04-03 18:07:56 +00:00
# include "gui/C4MouseControl.h"
# include "network/C4Network2.h"
2017-04-30 08:49:09 +00:00
# include "network/C4Network2Dialogs.h"
2009-05-08 13:28:41 +00:00
DWORD GenerateRandomPlayerColor ( int32_t iTry ) ; // in C4PlayerInfoConflicts.cpp
// ----------- ListItem --------------------------------------------------------------------------------
// helper
C4GameLobby : : MainDlg * C4PlayerInfoListBox : : ListItem : : GetLobby ( ) const
2010-03-28 18:58:01 +00:00
{
2009-06-05 15:19:46 +00:00
return : : Network . GetLobby ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4PlayerInfoListBox : : ListItem : : CanLocalChooseTeams ( int32_t idPlayer ) const
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// whether the local client can change any teams
// only if teams are available
if ( ! Game . Teams . IsMultiTeams ( ) ) return false ;
// only if global change allowed
C4GameLobby : : MainDlg * pLobby = GetLobby ( ) ;
if ( ! pLobby ) return false ;
if ( pLobby - > IsCountdown ( ) ) return false ;
// only for unjoined players
if ( idPlayer )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4PlayerInfo * pInfo = Game . PlayerInfos . GetPlayerInfoByID ( idPlayer ) ;
if ( pInfo & & pInfo - > HasJoined ( ) ) return false ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// finally, only if team settings permit
return Game . Teams . CanLocalChooseTeam ( idPlayer ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : ListItem : : DrawElement ( C4TargetFacet & cgo )
2010-03-28 18:58:01 +00:00
{
2011-10-03 14:30:18 +00:00
if ( dwBackground ) pDraw - > DrawBoxDw ( cgo . Surface , cgo . TargetX + rcBounds . x , cgo . TargetY + rcBounds . y , cgo . TargetX + rcBounds . x + rcBounds . Wdt - 1 , cgo . TargetY + rcBounds . y + rcBounds . Hgt - 1 , dwBackground ) ;
2009-05-08 13:28:41 +00:00
typedef C4GUI : : Window BaseClass ;
BaseClass : : DrawElement ( cgo ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// ----------- PlayerListItem -----------------------------------------------------------------------
C4PlayerInfoListBox : : PlayerListItem : : PlayerListItem ( C4PlayerInfoListBox * pForListBox , int32_t idClient ,
2010-03-28 18:58:01 +00:00
int32_t idPlayer , bool fSavegamePlayer , C4GUI : : Element * pInsertBeforeElement )
2016-11-02 23:58:02 +00:00
: ListItem ( pForListBox ) , pScoreLabel ( nullptr ) , pTimeLabel ( nullptr ) , pExtraLabel ( nullptr ) ,
pRankIcon ( nullptr ) , pTeamCombo ( nullptr ) , pTeamPic ( nullptr ) , fIconSet ( false ) , fJoinedInfoSet ( false ) ,
2010-03-28 18:58:01 +00:00
dwJoinClr ( 0 ) , dwPlrClr ( 0 ) , idClient ( idClient ) , idPlayer ( idPlayer ) , fFreeSavegamePlayer ( fSavegamePlayer )
{
2009-05-08 13:28:41 +00:00
bool fIsEvaluation = pForListBox - > IsEvaluation ( ) , fIsLobby = pForListBox - > IsLobby ( ) ;
C4PlayerInfo * pInfo = GetPlayerInfo ( ) ; assert ( pInfo ) ;
uint32_t dwTextColor = pForListBox - > GetTextColor ( ) ;
CStdFont * pCustomFont = pForListBox - > GetCustomFont ( ) ;
uint32_t dwPlayerColor ;
if ( fIsEvaluation )
dwPlayerColor = dwTextColor ;
else
dwPlayerColor = pInfo - > GetLobbyColor ( ) | C4GUI_MessageFontAlpha ;
// league account name? Overwrite the shown name
StdStrBuf sPlayerName ( pInfo - > GetLobbyName ( ) ) ;
// calc height
2010-06-27 00:42:48 +00:00
int32_t iHeight = : : GraphicsResource . TextFont . GetLineHeight ( ) + C4GUI : : ComboBox : : GetDefaultHeight ( ) + 3 * IconLabelSpacing ;
2009-05-08 13:28:41 +00:00
// create subcomponents
pIcon = new C4GUI : : Icon ( C4Rect ( 0 , 0 , iHeight , iHeight ) , C4GUI : : Ico_UnknownPlayer ) ;
if ( Game . Parameters . isLeague ( ) )
pRankIcon = new C4GUI : : Icon ( C4Rect ( 0 , 0 , C4GUI : : ComboBox : : GetDefaultHeight ( ) , C4GUI : : ComboBox : : GetDefaultHeight ( ) ) , C4GUI : : Ico_None ) ;
if ( Game . Teams . IsMultiTeams ( ) & & ! ( fIsEvaluation & & pList - > IsTeamFilter ( ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// will be moved when the item is added to the list, and the position moved
pTeamCombo = new C4GUI : : ComboBox ( C4Rect ( 0 , 0 , 10 , 10 ) ) ;
pTeamCombo - > SetComboCB ( new C4GUI : : ComboBox_FillCallback < PlayerListItem > ( this , & PlayerListItem : : OnTeamComboFill , & PlayerListItem : : OnTeamComboSelChange ) ) ;
pTeamCombo - > SetSimple ( true ) ;
if ( pCustomFont )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pTeamCombo - > SetFont ( pCustomFont ) ;
pTeamCombo - > SetColors ( dwTextColor , C4GUI_StandardBGColor , 0 ) ;
}
2010-03-28 18:58:01 +00:00
UpdateTeam ( ) ;
}
2009-05-08 13:28:41 +00:00
// Evaluation
if ( fIsEvaluation )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Team image if known and if not placed on top of box anyway
if ( ! pList - > IsTeamFilter ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4Team * pTeam = Game . Teams . GetTeamByID ( pInfo - > GetTeam ( ) ) ;
if ( pTeam & & pTeam - > GetIconSpec ( ) & & * pTeam - > GetIconSpec ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pTeamPic = new C4GUI : : Picture ( C4Rect ( iHeight + IconLabelSpacing , 0 , iHeight , iHeight ) , true ) ;
2016-11-02 23:58:02 +00:00
Game . DrawTextSpecImage ( pTeamPic - > GetMFacet ( ) , pTeam - > GetIconSpec ( ) , nullptr , pTeam - > GetColor ( ) ) ;
2009-05-08 13:28:41 +00:00
pTeamPic - > SetDrawColor ( pTeam - > GetColor ( ) ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Total playing time (not in team filter because then the second line is taken by the score label)
if ( ! pList - > IsTeamFilter ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
StdStrBuf sTimeLabelText ;
C4RoundResultsPlayer * pRoundResultsPlr = Game . RoundResults . GetPlayers ( ) . GetByID ( idPlayer ) ;
uint32_t iTimeTotal = pRoundResultsPlr ? pRoundResultsPlr - > GetTotalPlayingTime ( ) : 0 /* unknown - should not happen */ ;
sTimeLabelText . Format ( LoadResStr ( " IDS_CTL_TOTALPLAYINGTIME " ) , iTimeTotal / 3600 , ( iTimeTotal / 60 ) % 60 , iTimeTotal % 60 ) ;
pTimeLabel = new C4GUI : : Label ( sTimeLabelText . getData ( ) , 0 , 0 , ARight , dwTextColor , pForListBox - > GetCustomFont ( ) , false , true ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Extra info set by script
C4RoundResultsPlayer * pEvaluationPlayer = Game . RoundResults . GetPlayers ( ) . GetByID ( idPlayer ) ; ;
if ( pEvaluationPlayer )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
const char * szCustomEval = pEvaluationPlayer - > GetCustomEvaluationStrings ( ) ;
if ( szCustomEval & & * szCustomEval )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pExtraLabel = new C4GUI : : Label ( szCustomEval , 0 , 0 , ARight ) ; // positioned later
2010-06-27 00:42:48 +00:00
iHeight + = : : GraphicsResource . TextFont . GetLineHeight ( ) ;
2009-05-08 13:28:41 +00:00
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
pNameLabel = new C4GUI : : Label ( sPlayerName . getData ( ) , ( iHeight + IconLabelSpacing ) * ( 1 + ! ! pTeamPic ) , IconLabelSpacing , ALeft , dwPlayerColor , pCustomFont , ! fIsEvaluation , true ) ;
// calc own bounds - list box needs height only; width and pos will be moved by list
SetBounds ( C4Rect ( 0 , 0 , 10 , iHeight ) ) ;
// add components
AddElement ( pIcon ) ; AddElement ( pNameLabel ) ;
if ( pTeamPic ) AddElement ( pTeamPic ) ;
if ( pTimeLabel ) AddElement ( pTimeLabel ) ;
if ( pTeamCombo ) AddElement ( pTeamCombo ) ;
if ( pRankIcon ) AddElement ( pRankIcon ) ;
if ( pExtraLabel ) AddElement ( pExtraLabel ) ;
// add to listbox (will get resized horizontally and moved)
pForListBox - > InsertElement ( this , pInsertBeforeElement , PlayerListBoxIndent ) ;
// league score update
UpdateScoreLabel ( pInfo ) ;
// set ID
if ( fFreeSavegamePlayer )
idListItemID . idType = ListItem : : ID : : PLI_SAVEGAMEPLR ;
else
idListItemID . idType = ListItem : : ID : : PLI_PLAYER ;
idListItemID . id = idPlayer ;
UpdateIcon ( pInfo , GetJoinedInfo ( ) ) ;
// context menu for list item
if ( fIsLobby ) SetContextHandler ( new C4GUI : : CBContextHandler < PlayerListItem > ( this , & PlayerListItem : : OnContext ) ) ;
// update collapsed/not collapsed
fShownCollapsed = false ;
UpdateCollapsed ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : PlayerListItem : : UpdateOwnPos ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// parent for client rect
typedef C4GUI : : Window ParentClass ;
ParentClass : : UpdateOwnPos ( ) ;
C4GUI : : ComponentAligner caBounds ( GetContainedClientRect ( ) , IconLabelSpacing , IconLabelSpacing ) ;
// subtract icon(s)
caBounds . GetFromLeft ( pIcon - > GetBounds ( ) . Wdt ) ;
if ( pTeamPic ) caBounds . GetFromLeft ( pTeamPic - > GetBounds ( ) . Wdt - IconLabelSpacing ) ;
C4Rect rcExtraDataRect ;
// extra data label area
2010-06-27 00:42:48 +00:00
if ( pExtraLabel ) rcExtraDataRect = caBounds . GetFromBottom ( : : GraphicsResource . TextFont . GetLineHeight ( ) ) ;
2009-05-08 13:28:41 +00:00
// second line (team+rank)
C4GUI : : ComponentAligner caTeamArea ( caBounds . GetFromBottom ( C4GUI : : ComboBox : : GetDefaultHeight ( ) ) , 0 , 0 ) ;
2010-01-25 23:07:17 +00:00
C4Rect rcRankIcon ;
2009-05-08 13:28:41 +00:00
if ( pList - > IsEvaluation ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( pRankIcon )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
rcRankIcon = caBounds . GetFromRight ( caBounds . GetInnerHeight ( ) ) ;
if ( pExtraLabel ) rcExtraDataRect . Wdt = caBounds . GetInnerWidth ( ) ; // In evaluation view, rank icon has its own coloumn
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( pRankIcon ) rcRankIcon = caTeamArea . GetFromRight ( caTeamArea . GetInnerHeight ( ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4Rect rcTeam = caTeamArea . GetAll ( ) ;
// item to positions: team combo box
if ( pTeamCombo )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pTeamCombo - > SetBounds ( rcTeam ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// rank icon
if ( pRankIcon )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pRankIcon - > SetBounds ( rcRankIcon ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// time label
if ( pTimeLabel )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4Rect rcUpperBounds = caBounds . GetAll ( ) ;
pTimeLabel - > SetBounds ( rcTeam ) ;
pTimeLabel - > SetX0 ( rcUpperBounds . x + rcUpperBounds . Wdt ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// extra label
if ( pExtraLabel ) pExtraLabel - > SetBounds ( rcExtraDataRect ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
int32_t C4PlayerInfoListBox : : PlayerListItem : : GetListItemTopSpacing ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int32_t iSpacing = C4GUI_DefaultListSpacing ;
// evaluation: Add some extra spacing between players of different teams
if ( pList - > IsEvaluation ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4GUI : : Element * pPrevItem = GetPrev ( ) ;
if ( pPrevItem )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4PlayerInfoListBox : : ListItem * pPrevListItem = static_cast < C4PlayerInfoListBox : : ListItem * > ( pPrevItem ) ;
if ( pPrevListItem - > idListItemID . idType = = ListItem : : ID : : PLI_PLAYER )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
PlayerListItem * pPrevPlayerListItem = static_cast < C4PlayerInfoListBox : : PlayerListItem * > ( pPrevListItem ) ;
C4PlayerInfo * pThisInfo = GetPlayerInfo ( ) ;
C4PlayerInfo * pPrevInfo = pPrevPlayerListItem - > GetPlayerInfo ( ) ;
if ( pThisInfo & & pPrevInfo )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( pPrevInfo - > GetTeam ( ) ! = pThisInfo - > GetTeam ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
iSpacing + = 10 ;
}
}
}
}
}
2010-03-28 18:58:01 +00:00
return iSpacing ;
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : PlayerListItem : : UpdateIcon ( C4PlayerInfo * pInfo , C4PlayerInfo * pJoinedInfo )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// check whether icon is known
bool fResPresent = false ;
2016-11-02 23:58:02 +00:00
C4Network2Res * pRes = nullptr ;
2009-05-08 13:28:41 +00:00
if ( pInfo )
2010-01-25 04:00:59 +00:00
if ( ( pRes = pInfo - > GetRes ( ) ) )
2009-05-08 13:28:41 +00:00
fResPresent = pRes - > isComplete ( ) ;
2016-11-02 23:58:02 +00:00
C4RoundResultsPlayer * pEvaluationPlayer = nullptr ;
2009-05-08 13:28:41 +00:00
if ( pList - > IsEvaluation ( ) ) pEvaluationPlayer = Game . RoundResults . GetPlayers ( ) . GetByID ( idPlayer ) ;
2009-06-05 15:19:46 +00:00
bool fHasIcon = fResPresent | | pEvaluationPlayer | | ( ! : : Network . isEnabled ( ) & & pInfo ) ;
2009-05-08 13:28:41 +00:00
// check whether joined info is present
bool fHasJoinedInfo = ! ! pJoinedInfo ;
DWORD dwJoinedInfoClr = pJoinedInfo ? pJoinedInfo - > GetLobbyColor ( ) : 0 ;
DWORD dwPlayerClr = pInfo ? pInfo - > GetLobbyColor ( ) : 0 ;
// already up-to-date?
if ( fHasIcon = = fIconSet & & fJoinedInfoSet = = fHasJoinedInfo & & dwJoinedInfoClr = = dwJoinClr & & dwPlayerClr = = dwPlrClr ) return ;
// update then
// redraw player icon
if ( fHasIcon )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// custom icon?
if ( pEvaluationPlayer & & pEvaluationPlayer - > GetBigIcon ( ) . Surface )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pIcon - > SetFacet ( pEvaluationPlayer - > GetBigIcon ( ) ) ;
fIconSet = true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
fIconSet = pInfo - > LoadBigIcon ( pIcon - > GetMFacet ( ) ) ;
if ( ! fIconSet )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// no custom icon: create default by player color
2011-08-05 12:58:16 +00:00
pIcon - > GetMFacet ( ) . Create ( 64 , 64 ) ; // the bigicon is bigger than the normal 40x40 icon
2009-08-15 18:50:32 +00:00
: : GraphicsResource . fctPlayerClr . DrawClr ( pIcon - > GetMFacet ( ) , true , dwPlayerClr ) ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
fIconSet = true ;
}
2009-05-08 13:28:41 +00:00
else
// no player info known - either res not retrieved yet or script player
pIcon - > SetIcon ( ( pInfo & & pInfo - > GetType ( ) = = C4PT_Script ) ? C4GUI : : Ico_Host : C4GUI : : Ico_UnknownPlayer ) ;
// join
if ( fHasJoinedInfo )
2010-03-28 18:58:01 +00:00
{
2012-10-21 20:20:43 +00:00
// make sure we're not drawing on GraphicsResource
2009-05-08 13:28:41 +00:00
if ( ! pIcon - > EnsureOwnSurface ( ) ) return ;
// draw join info
C4Facet fctDraw = pIcon - > GetFacet ( ) ;
2015-11-15 12:53:01 +00:00
int32_t iSizeMax = std : : max < int32_t > ( fctDraw . Wdt , fctDraw . Hgt ) ;
2009-05-08 13:28:41 +00:00
int32_t iCrewClrHgt = iSizeMax / 2 ;
fctDraw . Hgt - = iCrewClrHgt ; fctDraw . Y + = iCrewClrHgt ;
fctDraw . Wdt = iSizeMax / 2 ;
fctDraw . X = 2 ;
// shadow
2011-10-03 14:30:18 +00:00
DWORD dwPrevMod ; bool fPrevMod = pDraw - > GetBlitModulation ( dwPrevMod ) ;
pDraw - > ActivateBlitModulation ( 1 ) ;
2009-08-15 18:50:32 +00:00
: : GraphicsResource . fctCrewClr . DrawClr ( fctDraw , true , dwJoinedInfoClr ) ;
2011-10-03 14:30:18 +00:00
if ( fPrevMod ) pDraw - > ActivateBlitModulation ( dwPrevMod ) ; else pDraw - > DeactivateBlitModulation ( ) ;
2009-05-08 13:28:41 +00:00
fctDraw . X = 0 ;
// gfx
2009-08-15 18:50:32 +00:00
: : GraphicsResource . fctCrewClr . DrawClr ( fctDraw , true , dwJoinedInfoClr ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
fJoinedInfoSet = fHasJoinedInfo ;
dwJoinClr = dwJoinedInfoClr ;
dwPlrClr = dwPlayerClr ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : PlayerListItem : : UpdateTeam ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( ! pTeamCombo ) return ; // unassigned for no teams
const char * szTeamName = " " ; bool fReadOnly = true ;
fReadOnly = ! CanLocalChooseTeam ( ) ;
int32_t idTeam ; C4Team * pTeam ;
C4PlayerInfo * pInfo = GetPlayerInfo ( ) ;
if ( ! Game . Teams . CanLocalSeeTeam ( ) )
szTeamName = LoadResStr ( " IDS_MSG_RNDTEAM " ) ;
else if ( pInfo )
2010-01-25 04:00:59 +00:00
if ( ( idTeam = pInfo - > GetTeam ( ) ) )
if ( ( pTeam = Game . Teams . GetTeamByID ( idTeam ) ) )
2009-05-08 13:28:41 +00:00
szTeamName = pTeam - > GetName ( ) ;
pTeamCombo - > SetText ( szTeamName ) ;
pTeamCombo - > SetReadOnly ( fReadOnly ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : PlayerListItem : : UpdateScoreLabel ( C4PlayerInfo * pInfo )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
assert ( pInfo ) ;
2016-11-02 23:58:02 +00:00
C4RoundResultsPlayer * pRoundResultsPlr = nullptr ;
2009-05-08 13:28:41 +00:00
if ( pList - > IsEvaluation ( ) ) pRoundResultsPlr = Game . RoundResults . GetPlayers ( ) . GetByID ( idPlayer ) ;
if ( pInfo - > getLeagueScore ( ) | | pInfo - > IsLeagueProjectedGainValid ( ) | | pRoundResultsPlr )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int32_t iScoreRightPos = ( ( pRankIcon & & pList - > IsEvaluation ( ) ) ? pRankIcon - > GetBounds ( ) . x : GetBounds ( ) . Wdt ) - IconLabelSpacing ;
int32_t iScoreYPos = IconLabelSpacing ;
// if evaluation and team lists, move score label into second line - TODO: some hack only, still needs to be done right
2009-09-16 01:29:20 +00:00
C4RoundResultsPlayer * pEvaluationPlayer = Game . RoundResults . GetPlayers ( ) . GetByID ( pInfo - > GetID ( ) ) ; ;
bool fPlayerHasEvaluationData = false ;
if ( pEvaluationPlayer )
2010-03-28 18:58:01 +00:00
{
const char * szCustomEval = pEvaluationPlayer - > GetCustomEvaluationStrings ( ) ;
if ( szCustomEval & & * szCustomEval )
fPlayerHasEvaluationData = true ;
}
2009-09-16 01:29:20 +00:00
if ( pList - > IsEvaluation ( ) & & pList - > IsTeamFilter ( ) )
iScoreYPos = GetBounds ( ) . Hgt - ( C4GUI : : ComboBox : : GetDefaultHeight ( ) * ( 1 + ( int32_t ) fPlayerHasEvaluationData ) ) - IconLabelSpacing ;
2009-08-26 12:17:41 +00:00
2009-05-08 13:28:41 +00:00
// score label visible
if ( ! pScoreLabel )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
AddElement ( pScoreLabel = new C4GUI : : Label ( " " , iScoreRightPos , iScoreYPos , ARight , pList - > GetTextColor ( ) , pList - > GetCustomFont ( ) , false ) ) ;
if ( pList - > IsEvaluation ( ) )
pScoreLabel - > SetToolTip ( LoadResStr ( " IDS_DESC_OLDANDNEWSCORE " ) ) ;
else
pScoreLabel - > SetToolTip ( LoadResStr ( " IDS_DESC_LEAGUESCOREANDPROJECTEDGA " ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
StdStrBuf sText ;
// Evaluation (GameOver)
if ( pList - > IsEvaluation ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( pInfo - > getLeagueScore ( ) | | pInfo - > IsLeagueProjectedGainValid ( ) | | ( pRoundResultsPlr & & pRoundResultsPlr - > IsLeagueScoreNewValid ( ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( pRoundResultsPlr & & pRoundResultsPlr - > IsLeagueScoreNewValid ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Show old league score, gain, and new league score
// Normally, the league server should make sure that [Old score] + [Gain] == [New score]
int32_t iOldScore = pInfo - > getLeagueScore ( ) , iScoreGain = pRoundResultsPlr - > GetLeagueScoreGain ( ) , iNewScore = pRoundResultsPlr - > GetLeagueScoreNew ( ) ;
int32_t iDiscrepancy = iNewScore - ( iOldScore + iScoreGain ) ;
if ( ! iDiscrepancy )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
sText . Format ( " {{Ico:League}}<c afafaf>%d (%+d)</c> %d %s " , ( int ) iOldScore , ( int ) iScoreGain , ( int ) iNewScore , LoadResStr ( " IDS_TEXT_SCORE " ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// If there's a discrepancy, there must have been some kind of admin intervention during the game - display it in red!
sText . Format ( " {{Ico:League}}<c afafaf>%d (%+d)</c><c ff0000>(%+d)</c> %d %s " , ( int ) iOldScore , ( int ) iScoreGain , ( int ) iDiscrepancy , ( int ) iNewScore , LoadResStr ( " IDS_TEXT_SCORE " ) ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Show old league score only
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
sText . Format ( " {{Ico:League}}<c afafaf>(%d)</c> %s " , ( int ) pInfo - > getLeagueScore ( ) , LoadResStr ( " IDS_TEXT_SCORE " ) ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-08-26 12:17:41 +00:00
else if ( pRoundResultsPlr & & pRoundResultsPlr - > IsScoreNewValid ( ) & & ! Game . RoundResults . SettlementScoreIsHidden ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// new score known
sText . Format ( " {{Ico:Settlement}}<c afafaf>%d (%+d)</c> %d %s " , ( int ) pRoundResultsPlr - > GetScoreOld ( ) , ( int ) ( pRoundResultsPlr - > GetScoreNew ( ) - pRoundResultsPlr - > GetScoreOld ( ) ) , ( int ) pRoundResultsPlr - > GetScoreNew ( ) , LoadResStr ( " IDS_TEXT_SCORE " ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-08-26 12:17:41 +00:00
else if ( pRoundResultsPlr & & ! pRoundResultsPlr - > IsScoreNewValid ( ) & & ! Game . RoundResults . SettlementScoreIsHidden ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// only old score known (e.g., player disconnected)
sText . Format ( " {{Ico:Settlement}}<c afafaf>(%d)</c> %s " , ( int ) pRoundResultsPlr - > GetScoreOld ( ) , LoadResStr ( " IDS_TEXT_SCORE " ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// nothing known. Shouldn't really happen.
sText . Ref ( " " ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Pre-evaluation (Lobby)
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Show current league score and projected gain
// Don't show if team invisible, so random surprise teams don't get spoiled
if ( pInfo - > IsLeagueProjectedGainValid ( ) & & Game . Teams . IsTeamVisible ( ) )
sText . Format ( " %d (%+d) " , ( int ) pInfo - > getLeagueScore ( ) , ( int ) pInfo - > GetLeagueProjectedGain ( ) ) ;
// Show current league score only
else
sText . Format ( " %d " , ( int ) pInfo - > getLeagueScore ( ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
pScoreLabel - > SetX0 ( iScoreRightPos ) ;
pScoreLabel - > SetText ( sText . getData ( ) , false ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else if ( pScoreLabel )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// score label invisible
delete pScoreLabel ;
2016-11-02 23:58:02 +00:00
pScoreLabel = nullptr ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
if ( pRankIcon )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int32_t iSym = 0 ;
if ( pRoundResultsPlr & & pRoundResultsPlr - > IsLeagueScoreNewValid ( ) )
iSym = pRoundResultsPlr - > GetLeagueRankSymbolNew ( ) ;
if ( ! iSym )
iSym = pInfo - > getLeagueRankSymbol ( ) ;
if ( iSym & & ! fShownCollapsed )
2010-03-28 18:58:01 +00:00
{
2015-02-12 22:05:55 +00:00
C4GUI : : Icons eRankIcon = ( C4GUI : : Icons ) ( C4GUI : : Ico_Rank1 + Clamp < int32_t > ( iSym - 1 , 0 , C4GUI : : Ico_Rank9 - C4GUI : : Ico_Rank1 ) ) ;
2009-05-08 13:28:41 +00:00
pRankIcon - > SetVisibility ( true ) ;
pRankIcon - > SetIcon ( eRankIcon ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pRankIcon - > SetVisibility ( false ) ;
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : PlayerListItem : : UpdateCollapsed ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
bool fShouldBeCollapsed = pList - > IsPlayerItemCollapsed ( this ) ;
if ( fShouldBeCollapsed = = fShownCollapsed ) return ;
// so update collapsed state
int32_t iHeight ; int32_t iNameLblX0 ;
2010-01-25 04:00:59 +00:00
if ( ( fShownCollapsed = fShouldBeCollapsed ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// calc height
2010-06-27 00:42:48 +00:00
iHeight = : : GraphicsResource . TextFont . GetLineHeight ( ) + 2 * IconLabelSpacing ;
2009-05-08 13:28:41 +00:00
// teamcombo not visible if collapsed
if ( pTeamCombo ) pTeamCombo - > SetVisibility ( false ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// calc height
2010-06-27 00:42:48 +00:00
iHeight = : : GraphicsResource . TextFont . GetLineHeight ( ) + C4GUI : : ComboBox : : GetDefaultHeight ( ) + 3 * IconLabelSpacing ;
2009-05-08 13:28:41 +00:00
// teamcombo visible if not collapsed
if ( pTeamCombo ) pTeamCombo - > SetVisibility ( true ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// update subcomponents
iNameLblX0 = iHeight + IconLabelSpacing ;
pIcon - > GetBounds ( ) = C4Rect ( 0 , 0 , iHeight , iHeight ) ;
pIcon - > UpdateOwnPos ( ) ;
pNameLabel - > SetX0 ( iNameLblX0 ) ;
// calc own bounds - use icon bounds only, because only the height is used when the item is added
SetBounds ( pIcon - > GetBounds ( ) ) ;
// update positions
pList - > UpdateElementPosition ( this , PlayerListBoxIndent ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4GUI : : ContextMenu * C4PlayerInfoListBox : : PlayerListItem : : OnContext ( C4GUI : : Element * pListItem , int32_t iX , int32_t iY )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4PlayerInfo * pInfo = GetPlayerInfo ( ) ;
assert ( pInfo ) ;
// no context menu for evaluation
2016-11-02 23:58:02 +00:00
if ( ! GetLobby ( ) ) return nullptr ;
2009-05-08 13:28:41 +00:00
// create context menu
C4GUI : : ContextMenu * pMenu = new C4GUI : : ContextMenu ( ) ;
// if this is a free player, add an option to take it over
if ( fFreeSavegamePlayer )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( pInfo - > GetType ( ) ! = C4PT_Script )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
StdCopyStrBuf strTakeOver ( LoadResStr ( " IDS_MSG_TAKEOVERPLR " ) ) ;
2016-11-02 23:58:02 +00:00
pMenu - > AddItem ( strTakeOver . getData ( ) , LoadResStr ( " IDS_MSG_TAKEOVERPLR_DESC " ) , C4GUI : : Ico_Player , nullptr ,
2010-03-28 18:58:01 +00:00
new C4GUI : : CBContextHandler < PlayerListItem > ( this , & PlayerListItem : : OnContextTakeOver ) ) ;
2010-03-27 16:05:02 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// owned players or host can manipulate players
2009-06-05 15:19:46 +00:00
if ( : : Network . isHost ( ) | | IsLocalClientPlayer ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// player removal (except for joined script players)
if ( pInfo - > GetType ( ) ! = C4PT_Script | | ! pInfo - > GetAssociatedSavegamePlayerID ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
StdCopyStrBuf strRemove ( LoadResStr ( " IDS_MSG_REMOVEPLR " ) ) ;
pMenu - > AddItem ( strRemove . getData ( ) , LoadResStr ( " IDS_MSG_REMOVEPLR_DESC " ) , C4GUI : : Ico_Close ,
2016-11-02 23:58:02 +00:00
new C4GUI : : CBMenuHandler < PlayerListItem > ( this , & PlayerListItem : : OnCtxRemove ) , nullptr ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// color was changed: Add option to assign a new color
C4PlayerInfo * pInfo = GetPlayerInfo ( ) ;
assert ( pInfo ) ;
if ( pInfo & & pInfo - > HasAutoGeneratedColor ( ) & & ( ! Game . Teams . IsTeamColors ( ) | | ! pInfo - > GetTeam ( ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
StdCopyStrBuf strNewColor ( LoadResStr ( " IDS_MSG_NEWPLRCOLOR " ) ) ;
pMenu - > AddItem ( strNewColor . getData ( ) , LoadResStr ( " IDS_MSG_NEWPLRCOLOR_DESC " ) , C4GUI : : Ico_Player ,
2016-11-02 23:58:02 +00:00
new C4GUI : : CBMenuHandler < PlayerListItem > ( this , & PlayerListItem : : OnCtxNewColor ) , nullptr ) ;
2009-05-08 13:28:41 +00:00
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// open it
return pMenu ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4GUI : : ContextMenu * C4PlayerInfoListBox : : PlayerListItem : : OnContextTakeOver ( C4GUI : : Element * pListItem , int32_t iX , int32_t iY )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// create context menu
C4GUI : : ContextMenu * pMenu = new C4GUI : : ContextMenu ( ) ;
// add options for all own, unassigned players
2009-06-05 15:19:46 +00:00
C4ClientPlayerInfos * pkInfo = : : Network . Players . GetLocalPlayerInfoPacket ( ) ;
2009-05-08 13:28:41 +00:00
if ( pkInfo )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int32_t i = 0 ; C4PlayerInfo * pInfo ;
2010-01-25 04:00:59 +00:00
while ( ( pInfo = pkInfo - > GetPlayerInfo ( i + + ) ) )
2009-05-08 13:28:41 +00:00
if ( ! pInfo - > HasJoinIssued ( ) )
if ( ! pInfo - > GetAssociatedSavegamePlayerID ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-11 13:09:53 +00:00
pMenu - > AddItem ( FormatString ( LoadResStr ( " IDS_MSG_USINGPLR " ) , pInfo - > GetName ( ) ) . getData ( ) ,
2010-03-28 18:58:01 +00:00
LoadResStr ( " IDS_MSG_USINGPLR_DESC " ) , C4GUI : : Ico_Player ,
new C4GUI : : CBMenuHandlerEx < PlayerListItem , int32_t > ( this , & PlayerListItem : : OnCtxTakeOver , pInfo - > GetID ( ) ) ) ;
}
}
2010-01-25 04:00:59 +00:00
// add option to use a new one... TODO
// add option to take over from savegame player TODO
2009-05-08 13:28:41 +00:00
// open it
return pMenu ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : PlayerListItem : : OnCtxTakeOver ( C4GUI : : Element * pListItem , const int32_t & idPlayer )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// use player idPlayer to take over this one
// this must be processed as a request by the host
// some safety first...
2009-06-05 15:19:46 +00:00
C4ClientPlayerInfos * pLocalInfo = : : Network . Players . GetLocalPlayerInfoPacket ( ) ;
2009-05-08 13:28:41 +00:00
if ( ! fFreeSavegamePlayer | | ! idPlayer | | ! pLocalInfo ) return ;
C4ClientPlayerInfos LocalInfoRequest ( * pLocalInfo ) ;
C4PlayerInfo * pGrabbingInfo = LocalInfoRequest . GetPlayerInfoByID ( idPlayer ) ;
if ( ! pGrabbingInfo ) return ;
// now adjust info packet
pGrabbingInfo - > SetAssociatedSavegamePlayer ( this - > idPlayer ) ;
// and request this update (host processes it directly)
2009-06-05 15:19:46 +00:00
: : Network . Players . RequestPlayerInfoUpdate ( LocalInfoRequest ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : PlayerListItem : : OnCtxRemove ( C4GUI : : Element * pListItem )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// only host or own player
2009-06-05 15:19:46 +00:00
if ( ! : : Network . isEnabled ( ) | | ( ! : : Network . isHost ( ) & & ! IsLocalClientPlayer ( ) ) ) return ;
2009-05-08 13:28:41 +00:00
// remove the player
// this must be processed as a request by the host
// now change it in its own request packet
C4ClientPlayerInfos * pChangeInfo = Game . PlayerInfos . GetInfoByClientID ( idClient ) ;
if ( ! pChangeInfo | | ! idPlayer ) return ;
C4ClientPlayerInfos LocalInfoRequest ( * pChangeInfo ) ;
if ( ! LocalInfoRequest . GetPlayerInfoByID ( idPlayer ) ) return ;
LocalInfoRequest . RemoveInfo ( idPlayer ) ;
// and request this update (host processes it directly)
2009-06-05 15:19:46 +00:00
: : Network . Players . RequestPlayerInfoUpdate ( LocalInfoRequest ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : PlayerListItem : : OnCtxNewColor ( C4GUI : : Element * pListItem )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// only host or own player
2009-06-05 15:19:46 +00:00
if ( ! : : Network . isEnabled ( ) | | ( ! : : Network . isHost ( ) & & ! IsLocalClientPlayer ( ) ) ) return ;
2009-05-08 13:28:41 +00:00
// just send a request to reclaim the original color to the host
// the host will deny this and decide on a new color
C4ClientPlayerInfos * pChangeInfo = Game . PlayerInfos . GetInfoByClientID ( idClient ) ;
if ( ! pChangeInfo | | ! idPlayer ) return ;
C4ClientPlayerInfos LocalInfoRequest ( * pChangeInfo ) ;
C4PlayerInfo * pPlrInfo = LocalInfoRequest . GetPlayerInfoByID ( idPlayer ) ;
if ( ! pPlrInfo ) return ;
pPlrInfo - > SetColor ( pPlrInfo - > GetOriginalColor ( ) ) ;
// and request this update (host processes it directly)
2009-06-05 15:19:46 +00:00
: : Network . Players . RequestPlayerInfoUpdate ( LocalInfoRequest ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : PlayerListItem : : OnTeamComboFill ( C4GUI : : ComboBox_FillCB * pFiller )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// add all possible teams
C4Team * pTeam ; int32_t i = 0 ;
2010-01-25 04:00:59 +00:00
while ( ( pTeam = Game . Teams . GetTeamByIndex ( i + + ) ) )
2009-05-08 13:28:41 +00:00
if ( ! pTeam - > IsFull ( ) | | GetPlayerInfo ( ) - > GetTeam ( ) = = pTeam - > GetID ( ) )
pFiller - > AddEntry ( pTeam - > GetName ( ) , pTeam - > GetID ( ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4PlayerInfoListBox : : PlayerListItem : : OnTeamComboSelChange ( C4GUI : : ComboBox * pForCombo , int32_t idNewSelection )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// always return true to mark combo sel as processed, so the GUI won't change the team text
// get new team id by name
C4Team * pNewTeam = Game . Teams . GetTeamByID ( idNewSelection ) ;
// some safety first...
if ( ! CanLocalChooseTeam ( ) | | ! pNewTeam ) return true ;
C4ClientPlayerInfos * pChangeInfo = Game . PlayerInfos . GetInfoByClientID ( idClient ) ;
if ( ! pChangeInfo | | ! idPlayer ) return true ;
// this must be processed as a request by the host
// now change it in its own request packet
C4ClientPlayerInfos LocalInfoRequest ( * pChangeInfo ) ;
C4PlayerInfo * pChangedInfo = LocalInfoRequest . GetPlayerInfoByID ( idPlayer ) ;
if ( ! pChangedInfo ) return true ;
pChangedInfo - > SetTeam ( pNewTeam - > GetID ( ) ) ;
// and request this update (host processes it directly)
2009-06-05 15:19:46 +00:00
: : Network . Players . RequestPlayerInfoUpdate ( LocalInfoRequest ) ;
2009-05-08 13:28:41 +00:00
// next update will change the combo box text
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : PlayerListItem : : Update ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
UpdateCollapsed ( ) ;
UpdateIcon ( GetPlayerInfo ( ) , GetJoinedInfo ( ) ) ;
UpdateTeam ( ) ;
C4PlayerInfo * pNfo = GetPlayerInfo ( ) ;
if ( pNfo )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
UpdateScoreLabel ( pNfo ) ;
// update name + color
StdStrBuf sShowName ( pNfo - > GetLobbyName ( ) ) ;
if ( pList - > IsEvaluation ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
bool fShowWinners = ( pList - > GetMode ( ) ! = PILBM_EvaluationNoWinners ) ;
bool fHasWon = fShowWinners & & pNfo - > HasTeamWon ( ) ;
// Append "winner" or "loser" to player name
if ( fShowWinners )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
sShowName . Take ( FormatString ( " %s (%s) " , sShowName . getData ( ) , LoadResStr ( fHasWon ? " IDS_CTL_WON " : " IDS_CTL_LOST " ) ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// evaluation: Golden color+background for winners; gray for losers or no winner show
if ( fHasWon )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pNameLabel - > SetColor ( C4GUI_WinningTextColor , false ) ;
dwBackground = C4GUI_WinningBackgroundColor ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pNameLabel - > SetColor ( C4GUI_LosingTextColor , false ) ;
dwBackground = C4GUI_LosingBackgroundColor ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// lobby: Label color by player color
pNameLabel - > SetColor ( pNfo - > GetLobbyColor ( ) ) ;
}
2010-03-28 18:58:01 +00:00
pNameLabel - > SetText ( sShowName . getData ( ) , false ) ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4PlayerInfo * C4PlayerInfoListBox : : PlayerListItem : : GetPlayerInfo ( ) const
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
return fFreeSavegamePlayer ? Game . RestorePlayerInfos . GetPlayerInfoByID ( idPlayer ) : Game . PlayerInfos . GetPlayerInfoByID ( idPlayer ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4PlayerInfo * C4PlayerInfoListBox : : PlayerListItem : : GetJoinedInfo ( ) const
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// safety
C4PlayerInfo * pInfo = GetPlayerInfo ( ) ;
2016-11-02 23:58:02 +00:00
if ( ! pInfo ) return nullptr ;
2009-05-08 13:28:41 +00:00
// is it a joined savegame player?
if ( fFreeSavegamePlayer )
// then this is the joined player
return pInfo ;
// otherwise, does it have a savegame association?
int32_t idSavegameInfo ;
2010-01-25 04:00:59 +00:00
if ( ( idSavegameInfo = pInfo - > GetAssociatedSavegamePlayerID ( ) ) )
2009-05-08 13:28:41 +00:00
// then return the respective info from savegame recreation list
return Game . RestorePlayerInfos . GetPlayerInfoByID ( idSavegameInfo ) ;
// not joined
2016-11-02 23:58:02 +00:00
return nullptr ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4PlayerInfoListBox : : PlayerListItem : : CanLocalChooseTeam ( ) const
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// never on savegame players
if ( fFreeSavegamePlayer | | GetJoinedInfo ( ) ) return false ;
// only host or own player
2009-06-05 15:19:46 +00:00
if ( ! : : Network . isHost ( ) & & ! IsLocalClientPlayer ( ) ) return false ;
2009-05-08 13:28:41 +00:00
// finally, only if team settings permit
return CanLocalChooseTeams ( idPlayer ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4PlayerInfoListBox : : PlayerListItem : : IsLocalClientPlayer ( ) const
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// check whether client is local
// if no client can be found, assume network disconnect and everythign local then
C4Network2Client * pClient = GetNetClient ( ) ;
return ! pClient | | pClient - > isLocal ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4Network2Client * C4PlayerInfoListBox : : PlayerListItem : : GetNetClient ( ) const
2010-03-28 18:58:01 +00:00
{
2009-06-05 15:19:46 +00:00
return : : Network . Clients . GetClientByID ( idClient ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// ----------- ClientListItem -----------------------------------------------------------------
C4PlayerInfoListBox : : ClientListItem : : ClientListItem ( C4PlayerInfoListBox * pForListBox , const C4ClientCore & rClientInfo , ListItem * pInsertBefore ) // ctor
2010-03-28 18:58:01 +00:00
: ListItem ( pForListBox ) , idClient ( rClientInfo . getID ( ) ) , dwClientClr ( 0xffffff ) , tLastSoundTime ( 0 )
{
2009-05-08 13:28:41 +00:00
// set current active-flag (not really needed until player info is retrieved)
fIsShownActive = rClientInfo . isActivated ( ) ;
// set ID
idListItemID . idType = ListItem : : ID : : PLI_CLIENT ;
idListItemID . id = idClient ;
// get height
2010-06-27 00:42:48 +00:00
int32_t iIconSize = : : GraphicsResource . TextFont . GetLineHeight ( ) ;
2009-05-08 13:28:41 +00:00
// create subcomponents
pStatusIcon = new C4GUI : : Icon ( C4Rect ( 0 , 0 , iIconSize , iIconSize ) , GetCurrentStatusIcon ( ) ) ;
2016-11-02 23:58:02 +00:00
pNameLabel = new C4GUI : : Label ( rClientInfo . getName ( ) , iIconSize + IconLabelSpacing , 0 , ALeft , dwClientClr | C4GUI_MessageFontAlpha , nullptr , true , false ) ;
pPingLabel = nullptr ;
C4GUI : : CallbackButton < ClientListItem , C4GUI : : IconButton > * btnAddPlayer = nullptr ;
2009-05-08 13:28:41 +00:00
if ( IsLocalClientPlayer ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// this computer: add player button
btnAddPlayer = new C4GUI : : CallbackButton < ClientListItem , C4GUI : : IconButton > ( C4GUI : : Ico_AddPlr , C4Rect ( 0 , 0 , iIconSize , iIconSize ) , ' P ' /* 2do TODO */ , & ClientListItem : : OnBtnAddPlr , this ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// calc own bounds
C4Rect rcOwnBounds = pNameLabel - > GetBounds ( ) ;
rcOwnBounds . Wdt + = rcOwnBounds . x ; rcOwnBounds . x = 0 ;
rcOwnBounds . Hgt + = rcOwnBounds . y ; rcOwnBounds . y = 0 ;
SetBounds ( rcOwnBounds ) ;
// add components
AddElement ( pStatusIcon ) ; AddElement ( pNameLabel ) ;
if ( btnAddPlayer ) AddElement ( btnAddPlayer ) ;
2010-04-01 21:08:06 +00:00
// tooltip (same for all components for now. separate tooltip for status icon later?)
2009-05-11 13:09:53 +00:00
SetToolTip ( FormatString ( " Client %s (%s) " , rClientInfo . getName ( ) , rClientInfo . getNick ( ) ) . getData ( ) ) ;
2009-05-08 13:28:41 +00:00
// insert into listbox at correct order
// (will eventually get resized horizontally and moved)
pForListBox - > InsertElement ( this , pInsertBefore ) ;
// after move: update add player button pos
if ( btnAddPlayer )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int32_t iHgt = GetClientRect ( ) . Hgt ;
btnAddPlayer - > GetBounds ( ) = GetToprightCornerRect ( iHgt , iHgt , 2 , 0 ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// context menu for list item
SetContextHandler ( new C4GUI : : CBContextHandler < ClientListItem > ( this , & ClientListItem : : OnContext ) ) ;
// update (also sets color)
Update ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : ClientListItem : : SetPing ( int32_t iToPing )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// no ping?
if ( iToPing = = - 1 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// remove any ping label
2016-11-02 23:58:02 +00:00
if ( pPingLabel ) { delete pPingLabel ; pPingLabel = nullptr ; }
2009-05-08 13:28:41 +00:00
return ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// get ping as text
2009-05-11 13:09:53 +00:00
StdStrBuf ping ;
ping . Format ( " %d ms " , iToPing ) ;
2009-05-08 13:28:41 +00:00
// create ping label if necessary
if ( ! pPingLabel )
2010-03-28 18:58:01 +00:00
{
2009-05-11 13:09:53 +00:00
pPingLabel = new C4GUI : : Label ( ping . getData ( ) , GetBounds ( ) . Wdt , 0 , ARight , C4GUI_MessageFontClr ) ;
2009-05-08 13:28:41 +00:00
pPingLabel - > SetToolTip ( LoadResStr ( " IDS_DLGTIP_PING " ) ) ;
AddElement ( pPingLabel ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
// or just set updated text
2009-05-11 13:09:53 +00:00
pPingLabel - > SetText ( ping . getData ( ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : ClientListItem : : UpdateInfo ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// update color (always, because it can change silently)
2009-06-05 15:19:46 +00:00
SetColor ( : : Network . Players . GetClientChatColor ( idClient , true ) ) ;
2009-05-08 13:28:41 +00:00
// update activation status
fIsShownActive = GetClient ( ) & & GetClient ( ) - > isActivated ( ) ;
// update status icon
SetStatus ( GetCurrentStatusIcon ( ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4Client * C4PlayerInfoListBox : : ClientListItem : : GetClient ( ) const
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// search (let's hope it exists)
return Game . Clients . getClientByID ( idClient ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4PlayerInfoListBox : : ClientListItem : : IsLocalClientPlayer ( ) const
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// check whether client is local
// if no client can be found, something is wrong - assume network disconnect and everything local then
C4Network2Client * pClient = GetNetClient ( ) ;
assert ( pClient ) ;
return ! pClient | | pClient - > isLocal ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4Network2Client * C4PlayerInfoListBox : : ClientListItem : : GetNetClient ( ) const
2010-03-28 18:58:01 +00:00
{
2009-06-05 15:19:46 +00:00
return : : Network . Clients . GetClientByID ( idClient ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4PlayerInfoListBox : : ClientListItem : : IsLocal ( ) const
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// it's local if client ID matches local ID
return idClient = = Game . Clients . getLocalID ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4GUI : : Icons C4PlayerInfoListBox : : ClientListItem : : GetCurrentStatusIcon ( )
2010-03-28 18:58:01 +00:00
{
2010-03-28 19:33:51 +00:00
if ( GetClient ( ) - > IsIgnored ( ) ) return C4GUI : : Ico_Ignored ;
2009-05-08 13:28:41 +00:00
// sound icon?
if ( tLastSoundTime )
2010-03-28 18:58:01 +00:00
{
2016-11-02 23:58:02 +00:00
time_t dt = time ( nullptr ) - tLastSoundTime ;
2009-05-08 13:28:41 +00:00
if ( dt > = SoundIconShowTime )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// stop showing sound icon
tLastSoundTime = 0 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// time not up yet: show sound icon
return C4GUI : : Ico_Sound ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// info present?
C4ClientPlayerInfos * pInfoPacket = Game . PlayerInfos . GetInfoByClientID ( idClient ) ;
if ( ! pInfoPacket | | ! GetClient ( ) )
// unknown status
return C4GUI : : Ico_UnknownClient ;
// host?
if ( GetClient ( ) - > isHost ( ) ) return C4GUI : : Ico_Host ;
// active client?
2015-11-19 03:49:59 +00:00
if ( GetClient ( ) - > isActivated ( ) )
{
if ( GetClient ( ) - > isLobbyReady ( ) )
{
return C4GUI : : Ico_Ready ;
}
else
{
return C4GUI : : Ico_Client ;
}
}
2009-05-08 13:28:41 +00:00
// observer
return C4GUI : : Ico_ObserverClient ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : ClientListItem : : UpdatePing ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// safety for removed clients
if ( ! GetClient ( ) ) return ;
// default value indicating no ping
int32_t iPing = - 1 ;
C4Network2Client * pClient = GetNetClient ( ) ;
C4Network2IOConnection * pConn ;
// must be a remote client
if ( pClient & & ! pClient - > isLocal ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// must have a connection
2010-01-25 04:00:59 +00:00
if ( ( pConn = pClient - > getMsgConn ( ) ) )
2009-05-08 13:28:41 +00:00
// get ping of that connection
iPing = pConn - > getLag ( ) ;
// check data connection if msg conn gave no value
// what's the meaning of those two connections anyway? o_O
if ( iPing < = 0 )
2010-01-25 04:00:59 +00:00
if ( ( pConn = pClient - > getDataConn ( ) ) )
2009-05-08 13:28:41 +00:00
iPing = pConn - > getLag ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// set that ping in label
SetPing ( iPing ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : ClientListItem : : SetSoundIcon ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// remember time for reset
2016-11-02 23:58:02 +00:00
tLastSoundTime = time ( nullptr ) ;
2009-05-08 13:28:41 +00:00
// force icon
SetStatus ( GetCurrentStatusIcon ( ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4GUI : : ContextMenu * C4PlayerInfoListBox : : ClientListItem : : OnContext ( C4GUI : : Element * pListItem , int32_t iX , int32_t iY )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// safety
2016-11-02 23:58:02 +00:00
if ( ! : : Network . isEnabled ( ) ) return nullptr ;
2009-05-08 13:28:41 +00:00
// get associated client
C4Client * pClient = GetClient ( ) ;
// create context menu
C4GUI : : ContextMenu * pMenu = new C4GUI : : ContextMenu ( ) ;
// host options
2009-06-05 15:19:46 +00:00
if ( : : Network . isHost ( ) & & GetNetClient ( ) )
2010-03-28 18:58:01 +00:00
{
StdCopyStrBuf strKickDesc ( LoadResStr ( " IDS_NET_KICKCLIENT_DESC " ) ) ;
2009-05-08 13:28:41 +00:00
pMenu - > AddItem ( LoadResStr ( " IDS_NET_KICKCLIENT " ) , strKickDesc . getData ( ) , C4GUI : : Ico_None ,
2010-03-28 18:58:01 +00:00
new C4GUI : : CBMenuHandler < ClientListItem > ( this , & ClientListItem : : OnCtxKick ) ) ;
StdCopyStrBuf strActivateDesc ( LoadResStr ( " IDS_NET_ACTIVATECLIENT_DESC " ) ) ;
2009-05-08 13:28:41 +00:00
pMenu - > AddItem ( LoadResStr ( pClient - > isActivated ( ) ? " IDS_NET_DEACTIVATECLIENT " : " IDS_NET_ACTIVATECLIENT " ) ,
2010-03-28 18:58:01 +00:00
strActivateDesc . getData ( ) , C4GUI : : Ico_None ,
new C4GUI : : CBMenuHandler < ClientListItem > ( this , & ClientListItem : : OnCtxActivate ) ) ;
}
2009-05-08 13:28:41 +00:00
// info
2010-03-28 18:58:01 +00:00
StdCopyStrBuf strClientInfoDesc ( LoadResStr ( " IDS_NET_CLIENTINFO_DESC " ) ) ;
2009-05-08 13:28:41 +00:00
pMenu - > AddItem ( LoadResStr ( " IDS_NET_CLIENTINFO " ) , strClientInfoDesc . getData ( ) , C4GUI : : Ico_None ,
2010-03-28 18:58:01 +00:00
new C4GUI : : CBMenuHandler < ClientListItem > ( this , & ClientListItem : : OnCtxInfo ) ) ;
2010-03-28 19:33:51 +00:00
//Ignore button
if ( ! pClient - > isLocal ( ) )
{
StdCopyStrBuf strNewColor ( LoadResStr ( pClient - > IsIgnored ( ) ? " IDS_NET_CLIENT_UNIGNORE " : " IDS_NET_CLIENT_IGNORE " ) ) ;
pMenu - > AddItem ( strNewColor . getData ( ) , FormatString ( LoadResStr ( " IDS_NET_CLIENT_IGNORE_DESC " ) , pClient - > getName ( ) ) . getData ( ) ,
2016-11-02 23:58:02 +00:00
C4GUI : : Ico_None , new C4GUI : : CBMenuHandler < ClientListItem > ( this , & ClientListItem : : OnCtxIgnore ) , nullptr ) ;
2010-03-28 19:33:51 +00:00
}
2009-05-08 13:28:41 +00:00
// open it
return pMenu ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2010-03-28 19:33:51 +00:00
void C4PlayerInfoListBox : : ClientListItem : : OnCtxIgnore ( C4GUI : : Element * pListItem )
{
GetClient ( ) - > ToggleIgnore ( ) ;
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : ClientListItem : : OnCtxKick ( C4GUI : : Element * pListItem )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// host only
2009-06-05 15:19:46 +00:00
if ( ! : : Network . isEnabled ( ) | | ! : : Network . isHost ( ) ) return ;
2009-05-08 13:28:41 +00:00
// add control
Game . Clients . CtrlRemove ( GetClient ( ) , LoadResStr ( " IDS_MSG_KICKFROMLOBBY " ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : ClientListItem : : OnCtxActivate ( C4GUI : : Element * pListItem )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// host only
C4Client * pClient = GetClient ( ) ;
2009-06-05 15:19:46 +00:00
if ( ! : : Network . isEnabled ( ) | | ! : : Network . isHost ( ) | | ! pClient ) return ;
2009-05-08 13:28:41 +00:00
// add control
2009-06-15 22:06:37 +00:00
: : Control . DoInput ( CID_ClientUpdate , new C4ControlClientUpdate ( idClient , CUT_Activate , ! pClient - > isActivated ( ) ) , CDT_Sync ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : ClientListItem : : OnCtxInfo ( C4GUI : : Element * pListItem )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// show client info dialog
2009-06-05 16:53:56 +00:00
: : pGUI - > ShowRemoveDlg ( new C4Network2ClientDlg ( idClient ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : ClientListItem : : OnBtnAddPlr ( C4GUI : : Control * btn )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// show player add dialog
GetScreen ( ) - > ShowRemoveDlg ( new C4PlayerSelDlg ( new C4FileSel_CBEx < C4GameLobby : : MainDlg > ( GetLobby ( ) , & C4GameLobby : : MainDlg : : OnClientAddPlayer , idClient ) ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// ----------- TeamListItem ---------------------------------------------
C4PlayerInfoListBox : : TeamListItem : : TeamListItem ( C4PlayerInfoListBox * pForListBox , int32_t idTeam , ListItem * pInsertBefore )
2010-03-28 18:58:01 +00:00
: ListItem ( pForListBox ) , idTeam ( idTeam )
{
2009-05-08 13:28:41 +00:00
bool fEvaluation = pList - > IsEvaluation ( ) ;
// get team data
const char * szTeamName ;
2016-11-02 23:58:02 +00:00
C4Team * pTeam = nullptr ;
2009-05-08 13:28:41 +00:00
if ( idTeam = = TEAMID_Unknown )
szTeamName = LoadResStr ( " IDS_MSG_RNDTEAM " ) ;
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pTeam = Game . Teams . GetTeamByID ( idTeam ) ; assert ( pTeam ) ;
if ( pTeam ) szTeamName = pTeam - > GetName ( ) ; else szTeamName = " INTERNAL TEAM ERROR " ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// set ID
idListItemID . idType = ListItem : : ID : : PLI_TEAM ;
idListItemID . id = idTeam ;
// get height
int32_t iIconSize ; CStdFont * pFont ;
if ( ! fEvaluation )
2010-03-28 18:58:01 +00:00
{
2010-06-27 00:42:48 +00:00
pFont = & : : GraphicsResource . TextFont ;
2009-05-08 13:28:41 +00:00
iIconSize = pFont - > GetLineHeight ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2010-06-27 00:42:48 +00:00
pFont = & : : GraphicsResource . TitleFont ;
2009-05-08 13:28:41 +00:00
iIconSize = C4SymbolSize ; // C4PictureSize doesn't fit...
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// create subcomponents
pIcon = new C4GUI : : Icon ( C4Rect ( 0 , 0 , iIconSize , iIconSize ) , C4GUI : : Ico_Team ) ;
pNameLabel = new C4GUI : : Label ( szTeamName , iIconSize + IconLabelSpacing , ( iIconSize - pFont - > GetLineHeight ( ) ) / 2 , ALeft , pList - > GetTextColor ( ) , pFont , false ) ;
if ( fEvaluation & & pTeam & & pTeam - > GetIconSpec ( ) & & * pTeam - > GetIconSpec ( ) )
2010-03-28 18:58:01 +00:00
{
2012-01-10 21:40:46 +00:00
C4FacetSurface fctSymbol ;
fctSymbol . Create ( C4SymbolSize , C4SymbolSize ) ;
2016-11-02 23:58:02 +00:00
Game . DrawTextSpecImage ( fctSymbol , pTeam - > GetIconSpec ( ) , nullptr , pTeam - > GetColor ( ) ) ;
2012-01-10 21:40:46 +00:00
pIcon - > GetMFacet ( ) . GrabFrom ( fctSymbol ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// calc own bounds
C4Rect rcOwnBounds = pNameLabel - > GetBounds ( ) ;
rcOwnBounds . Wdt + = rcOwnBounds . x ; rcOwnBounds . x = 0 ;
rcOwnBounds . Hgt + = rcOwnBounds . y ; rcOwnBounds . y = 0 ;
SetBounds ( rcOwnBounds ) ;
// add components
AddElement ( pIcon ) ; AddElement ( pNameLabel ) ;
// tooltip
SetToolTip ( FormatString ( LoadResStr ( " IDS_DESC_TEAM " ) , szTeamName ) . getData ( ) ) ;
// insert into listbox at correct order
// (will eventually get resized horizontally and moved)
pForListBox - > InsertElement ( this , pInsertBefore ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : TeamListItem : : MouseInput ( C4GUI : : CMouse & rMouse , int32_t iButton , int32_t iX , int32_t iY , DWORD dwKeyParam )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// double click on team to enter it with all local players
if ( iButton = = C4MC_Button_LeftDouble )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
MoveLocalPlayersIntoTeam ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
ListItem : : MouseInput ( rMouse , iButton , iX , iY , dwKeyParam ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : TeamListItem : : UpdateOwnPos ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// parent for client rect
typedef C4GUI : : Window ParentClass ;
ParentClass : : UpdateOwnPos ( ) ;
// evaluation: Center team label
if ( pList - > IsEvaluation ( ) )
2010-03-28 18:58:01 +00:00
{
2010-06-27 00:42:48 +00:00
int32_t iTotalWdt = pIcon - > GetBounds ( ) . Wdt + IconLabelSpacing + : : GraphicsResource . TitleFont . GetTextWidth ( pNameLabel - > GetText ( ) ) ;
2009-05-08 13:28:41 +00:00
C4GUI : : ComponentAligner caAll ( GetContainedClientRect ( ) , 0 , 0 ) ;
C4GUI : : ComponentAligner caBounds ( caAll . GetCentered ( iTotalWdt , caAll . GetInnerHeight ( ) ) , 0 , 0 ) ;
pIcon - > SetBounds ( caBounds . GetFromLeft ( pIcon - > GetBounds ( ) . Wdt , pIcon - > GetBounds ( ) . Hgt ) ) ;
2010-06-27 00:42:48 +00:00
pNameLabel - > SetBounds ( caBounds . GetCentered ( caBounds . GetInnerWidth ( ) , : : GraphicsResource . TitleFont . GetLineHeight ( ) ) ) ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : TeamListItem : : MoveLocalPlayersIntoTeam ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// check if changing teams is allowed
if ( ! CanLocalChooseTeams ( ) ) return ;
// safety: Clicked team must exist
if ( ! Game . Teams . GetTeamByID ( idTeam ) ) return ;
// get local client to change teams of
bool fAnyChange = false ;
C4ClientPlayerInfos * pChangeInfo = Game . PlayerInfos . GetInfoByClientID ( Game . Clients . getLocalID ( ) ) ;
if ( ! pChangeInfo ) return ;
// this must be processed as a request by the host
// now change it in its own request packet
C4ClientPlayerInfos LocalInfoRequest ( * pChangeInfo ) ;
C4PlayerInfo * pInfo ; int32_t i = 0 ;
2010-01-25 04:00:59 +00:00
while ( ( pInfo = LocalInfoRequest . GetPlayerInfo ( i + + ) ) )
2009-05-08 13:28:41 +00:00
if ( pInfo - > GetTeam ( ) ! = idTeam )
if ( pInfo - > GetType ( ) = = C4PT_User )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pInfo - > SetTeam ( idTeam ) ;
fAnyChange = true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
if ( ! fAnyChange ) return ;
// and request this update (host processes it directly)
2009-06-05 15:19:46 +00:00
: : Network . Players . RequestPlayerInfoUpdate ( LocalInfoRequest ) ;
2009-05-08 13:28:41 +00:00
// next update will move the player labels
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : TeamListItem : : Update ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// evaluation: update color by team winning status
if ( pList - > IsEvaluation ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4Team * pTeam = Game . Teams . GetTeamByID ( idTeam ) ;
if ( pTeam & & pTeam - > HasWon ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pNameLabel - > SetColor ( C4GUI_WinningTextColor , false ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pNameLabel - > SetColor ( C4GUI_LosingTextColor , false ) ;
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// ----------- FreeSavegamePlayersListItem ---------------------------------------------
C4PlayerInfoListBox : : FreeSavegamePlayersListItem : : FreeSavegamePlayersListItem ( C4PlayerInfoListBox * pForListBox , ListItem * pInsertBefore )
2010-03-28 18:58:01 +00:00
: ListItem ( pForListBox )
{
2009-05-08 13:28:41 +00:00
// set ID
idListItemID . idType = ListItem : : ID : : PLI_SAVEGAMEPLR ;
idListItemID . id = 0 ;
// get height
2010-06-27 00:42:48 +00:00
int32_t iIconSize = : : GraphicsResource . TextFont . GetLineHeight ( ) ;
2009-05-08 13:28:41 +00:00
// create subcomponents
pIcon = new C4GUI : : Icon ( C4Rect ( 0 , 0 , iIconSize , iIconSize ) , C4GUI : : Ico_SavegamePlayer ) ;
pNameLabel = new C4GUI : : Label ( LoadResStr ( " IDS_MSG_FREESAVEGAMEPLRS " ) , iIconSize + IconLabelSpacing , 0 , ALeft ) ;
// calc own bounds
C4Rect rcOwnBounds = pNameLabel - > GetBounds ( ) ;
rcOwnBounds . Wdt + = rcOwnBounds . x ; rcOwnBounds . x = 0 ;
rcOwnBounds . Hgt + = rcOwnBounds . y ; rcOwnBounds . y = 0 ;
SetBounds ( rcOwnBounds ) ;
// add components
AddElement ( pIcon ) ; AddElement ( pNameLabel ) ;
// tooltip
SetToolTip ( LoadResStr ( " IDS_DESC_UNASSOCIATEDSAVEGAMEPLAYE " ) ) ;
// insert into listbox at correct order
// (will eventually get resized horizontally and moved)
pForListBox - > InsertElement ( this , pInsertBefore ) ;
// initial update
Update ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : FreeSavegamePlayersListItem : : Update ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// 2do: none-label
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// ----------- ScriptPlayersListItem ---------------------------------------------
C4PlayerInfoListBox : : ScriptPlayersListItem : : ScriptPlayersListItem ( C4PlayerInfoListBox * pForListBox , ListItem * pInsertBefore )
2010-03-28 18:58:01 +00:00
: ListItem ( pForListBox )
{
2009-05-08 13:28:41 +00:00
// set ID
idListItemID . idType = ListItem : : ID : : PLI_SCRIPTPLR ;
idListItemID . id = 0 ;
// get height
2010-06-27 00:42:48 +00:00
int32_t iIconSize = : : GraphicsResource . TextFont . GetLineHeight ( ) ;
2009-05-08 13:28:41 +00:00
// create subcomponents
pIcon = new C4GUI : : Icon ( C4Rect ( 0 , 0 , iIconSize , iIconSize ) , C4GUI : : Ico_Record ) ;
pNameLabel = new C4GUI : : Label ( LoadResStr ( " IDS_CTL_SCRIPTPLAYERS " ) , iIconSize + IconLabelSpacing , 0 , ALeft ) ;
2016-11-02 23:58:02 +00:00
btnAddPlayer = nullptr ;
2009-06-15 22:06:37 +00:00
if ( : : Control . isCtrlHost ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
btnAddPlayer = new C4GUI : : CallbackButton < ScriptPlayersListItem , C4GUI : : IconButton > ( C4GUI : : Ico_AddPlr , C4Rect ( 0 , 0 , iIconSize , iIconSize ) , ' A ' /* 2do TODO */ , & ScriptPlayersListItem : : OnBtnAddPlr , this ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// calc own bounds
C4Rect rcOwnBounds = pNameLabel - > GetBounds ( ) ;
rcOwnBounds . Wdt + = rcOwnBounds . x ; rcOwnBounds . x = 0 ;
rcOwnBounds . Hgt + = rcOwnBounds . y ; rcOwnBounds . y = 0 ;
SetBounds ( rcOwnBounds ) ;
// add components
AddElement ( pIcon ) ; AddElement ( pNameLabel ) ;
if ( btnAddPlayer ) AddElement ( btnAddPlayer ) ;
// tooltip
SetToolTip ( LoadResStr ( " IDS_DESC_PLAYERSCONTROLLEDBYCOMPUT " ) ) ;
// insert into listbox at correct order
// (will eventually get resized horizontally and moved)
pForListBox - > InsertElement ( this , pInsertBefore ) ;
// after move: update add player button pos
if ( btnAddPlayer )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int32_t iHgt = GetClientRect ( ) . Hgt ;
btnAddPlayer - > GetBounds ( ) = GetToprightCornerRect ( iHgt , iHgt , 2 , 0 ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// initial update
Update ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : ScriptPlayersListItem : : Update ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// player join button: Visible if there's still some room for script players
if ( btnAddPlayer )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
bool fCanJoinScriptPlayers = ( Game . Teams . GetMaxScriptPlayers ( ) - Game . PlayerInfos . GetActiveScriptPlayerCount ( true , true ) > 0 ) ;
btnAddPlayer - > SetVisibility ( fCanJoinScriptPlayers ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : ScriptPlayersListItem : : OnBtnAddPlr ( C4GUI : : Control * btn )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// safety
int32_t iCurrScriptPlrCount = Game . PlayerInfos . GetActiveScriptPlayerCount ( true , true ) ;
bool fCanJoinScriptPlayers = ( Game . Teams . GetMaxScriptPlayers ( ) - iCurrScriptPlrCount > 0 ) ;
if ( ! fCanJoinScriptPlayers ) return ;
2009-06-15 22:06:37 +00:00
if ( ! : : Control . isCtrlHost ( ) ) return ;
2009-05-08 13:28:41 +00:00
// request a script player join
C4PlayerInfo * pScriptPlrInfo = new C4PlayerInfo ( ) ;
2010-01-25 03:14:52 +00:00
pScriptPlrInfo - > SetAsScriptPlayer ( Game . Teams . GetScriptPlayerName ( ) . getData ( ) , GenerateRandomPlayerColor ( iCurrScriptPlrCount ) , 0 , C4ID : : None ) ;
2016-11-02 23:58:02 +00:00
C4ClientPlayerInfos JoinPkt ( nullptr , true , pScriptPlrInfo ) ;
2009-05-08 13:28:41 +00:00
// add to queue!
Game . PlayerInfos . DoPlayerInfoUpdate ( & JoinPkt ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// ----------- ReplayPlayersListItem ---------------------------------------------
C4PlayerInfoListBox : : ReplayPlayersListItem : : ReplayPlayersListItem ( C4PlayerInfoListBox * pForListBox , ListItem * pInsertBefore )
2010-03-28 18:58:01 +00:00
: ListItem ( pForListBox )
{
2009-05-08 13:28:41 +00:00
// set ID
idListItemID . idType = ListItem : : ID : : PLI_REPLAY ;
idListItemID . id = 0 ;
// get height
2010-06-27 00:42:48 +00:00
int32_t iIconSize = : : GraphicsResource . TextFont . GetLineHeight ( ) ;
2009-05-08 13:28:41 +00:00
// create subcomponents
pIcon = new C4GUI : : Icon ( C4Rect ( 0 , 0 , iIconSize , iIconSize ) , C4GUI : : Ico_Record ) ;
pNameLabel = new C4GUI : : Label ( LoadResStr ( " IDS_MSG_REPLAYPLRS " ) , iIconSize + IconLabelSpacing , 0 , ALeft ) ;
// calc own bounds
C4Rect rcOwnBounds = pNameLabel - > GetBounds ( ) ;
rcOwnBounds . Wdt + = rcOwnBounds . x ; rcOwnBounds . x = 0 ;
rcOwnBounds . Hgt + = rcOwnBounds . y ; rcOwnBounds . y = 0 ;
SetBounds ( rcOwnBounds ) ;
// add components
AddElement ( pIcon ) ; AddElement ( pNameLabel ) ;
// tooltip
SetToolTip ( LoadResStr ( " IDS_MSG_REPLAYPLRS_DESC " ) ) ;
// insert into listbox at correct order
// (will eventually get resized horizontally and moved)
pForListBox - > InsertElement ( this , pInsertBefore ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// ------------------- C4PlayerInfoListBox ------------------------
C4PlayerInfoListBox : : C4PlayerInfoListBox ( const C4Rect & rcBounds , Mode eMode , int32_t iTeamFilter )
2016-11-02 23:58:02 +00:00
: C4GUI : : ListBox ( rcBounds ) , eMode ( eMode ) , iMaxUncollapsedPlayers ( 10 ) , fIsCollapsed ( false ) , iTeamFilter ( iTeamFilter ) , dwTextColor ( C4GUI_MessageFontClr ) , pCustomFont ( nullptr )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// update if client listbox selection changes
SetSelectionChangeCallbackFn ( new C4GUI : : CallbackHandler < C4PlayerInfoListBox > ( this , & C4PlayerInfoListBox : : OnPlrListSelChange ) ) ;
// initial update
Update ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : SetClientSoundIcon ( int32_t iForClientID )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// get client element
ListItem * pItem = GetPlayerListItem ( ListItem : : ID : : PLI_CLIENT , iForClientID ) ;
if ( pItem )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
ClientListItem * pClientItem = static_cast < ClientListItem * > ( pItem ) ;
pClientItem - > SetSoundIcon ( ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4PlayerInfoListBox : : ListItem * C4PlayerInfoListBox : : GetPlayerListItem ( ListItem : : ID : : IDType eType , int32_t id )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
ListItem : : ID idSearch ( eType , id ) ;
// search through listbox
for ( C4GUI : : Element * pEItem = GetFirst ( ) ; pEItem ; pEItem = pEItem - > GetNext ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// only playerlistitems in this box
ListItem * pItem = static_cast < ListItem * > ( pEItem ) ;
if ( pItem - > idListItemID = = idSearch ) return pItem ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// nothing found
2016-11-02 23:58:02 +00:00
return nullptr ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4PlayerInfoListBox : : PlrListItemUpdate ( ListItem : : ID : : IDType eType , int32_t id , class ListItem * * pEnsurePos )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
assert ( pEnsurePos ) ;
// search item
ListItem * pItem = GetPlayerListItem ( eType , id ) ;
if ( ! pItem ) return false ;
// ensure its position is correct
if ( pItem ! = * pEnsurePos )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
RemoveElement ( pItem ) ;
InsertElement ( pItem , * pEnsurePos ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// pos correct; advance past it
* pEnsurePos = static_cast < ListItem * > ( pItem - > GetNext ( ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// update item
pItem - > Update ( ) ;
// done, success
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// static safety var to prevent recusive updates
static bool fPlayerListUpdating = false ;
void C4PlayerInfoListBox : : Update ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( fPlayerListUpdating ) return ;
fPlayerListUpdating = true ;
// synchronize current list with what it should be
// call update on all other list items
ListItem * pCurrInList = static_cast < ListItem * > ( GetFirst ( ) ) ; // list item being compared with the searched item
// free savegame players first
UpdateSavegamePlayers ( & pCurrInList ) ;
// next comes the regular players, sorted either by clients or teams, or special sort for evaluation mode
switch ( eMode )
2010-03-28 18:58:01 +00:00
{
case PILBM_LobbyTeamSort :
// sort by team
if ( Game . Teams . CanLocalSeeTeam ( ) )
UpdatePlayersByTeam ( & pCurrInList ) ;
else
UpdatePlayersByRandomTeam ( & pCurrInList ) ;
break ;
case PILBM_LobbyClientSort :
// sort by client
// replay players first?
if ( Game . C4S . Head . Replay ) UpdateReplayPlayers ( & pCurrInList ) ;
// script controlled players from the main list
UpdateScriptPlayers ( & pCurrInList ) ;
// regular players
UpdatePlayersByClient ( & pCurrInList ) ;
break ;
case PILBM_Evaluation :
case PILBM_EvaluationNoWinners :
UpdatePlayersByEvaluation ( & pCurrInList , eMode = = PILBM_Evaluation ) ;
break ;
}
2009-05-08 13:28:41 +00:00
// finally: remove any remaining list items at the end
while ( pCurrInList )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
ListItem * pDel = pCurrInList ;
pCurrInList = static_cast < ListItem * > ( pCurrInList - > GetNext ( ) ) ;
delete pDel ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// update done
fPlayerListUpdating = false ;
// check whether view needs to be collapsed
if ( ! fIsCollapsed & & IsScrollingActive ( ) & & ! IsEvaluation ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// then collapse it, and update window
iMaxUncollapsedPlayers = Game . PlayerInfos . GetPlayerCount ( ) - 1 ;
fIsCollapsed = true ;
Update ( ) ; // recursive call!
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else if ( fIsCollapsed & & Game . PlayerInfos . GetPlayerCount ( ) < = iMaxUncollapsedPlayers )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// player count dropped below collapse-limit: uncollapse
// note that this may again cause a collapse after that update, if scrolling was still necessary
// however, it will then not recurse any further, because iMaxUncollapsedPlayers will have been updated
fIsCollapsed = false ;
Update ( ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : UpdateSavegamePlayers ( ListItem * * ppCurrInList )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// add unassociated savegame players (script players excluded)
if ( Game . RestorePlayerInfos . GetActivePlayerCount ( true ) - Game . RestorePlayerInfos . GetActiveScriptPlayerCount ( true , true ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// caption
if ( ! PlrListItemUpdate ( ListItem : : ID : : PLI_SAVEGAMEPLR , 0 , ppCurrInList ) )
new FreeSavegamePlayersListItem ( this , * ppCurrInList ) ;
// the players
bool fAnyPlayers = false ;
C4PlayerInfo * pInfo ; int32_t iInfoID = 0 ;
2010-01-25 04:00:59 +00:00
while ( ( pInfo = Game . RestorePlayerInfos . GetNextPlayerInfoByID ( iInfoID ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
iInfoID = pInfo - > GetID ( ) ;
// skip assigned
if ( Game . PlayerInfos . GetPlayerInfoBySavegameID ( iInfoID ) ) continue ;
// skip script controlled - those are put into the script controlled player list
if ( pInfo - > GetType ( ) = = C4PT_Script ) continue ;
// players are in the list
fAnyPlayers = true ;
// show them
if ( ! PlrListItemUpdate ( ListItem : : ID : : PLI_SAVEGAMEPLR , iInfoID , ppCurrInList ) )
new PlayerListItem ( this , - 1 , iInfoID , true , * ppCurrInList ) ;
}
2010-03-28 18:58:01 +00:00
// 2do: none-label
2015-08-29 12:33:00 +00:00
( void ) fAnyPlayers ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : UpdateReplayPlayers ( ListItem * * ppCurrInList )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// header
if ( ! PlrListItemUpdate ( ListItem : : ID : : PLI_REPLAY , 0 , ppCurrInList ) )
new ReplayPlayersListItem ( this , * ppCurrInList ) ;
// players
C4PlayerInfo * pInfo ; int32_t iInfoID = 0 ;
2010-01-25 04:00:59 +00:00
while ( ( pInfo = Game . PlayerInfos . GetNextPlayerInfoByID ( iInfoID ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( pInfo - > IsInvisible ( ) ) continue ;
iInfoID = pInfo - > GetID ( ) ;
// show them
if ( ! PlrListItemUpdate ( ListItem : : ID : : PLI_PLAYER , iInfoID , ppCurrInList ) )
new PlayerListItem ( this , - 1 , iInfoID , false , * ppCurrInList ) ;
}
2010-03-28 18:58:01 +00:00
// 2do: none-label
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : UpdateScriptPlayers ( ListItem * * ppCurrInList )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// script controlled players from the main list
// processing the restore list would be redundant, because all script players should have been taken over by a new script player join automatically
// also show the label if script players can be joined
if ( Game . Teams . GetMaxScriptPlayers ( ) | | Game . PlayerInfos . GetActiveScriptPlayerCount ( true , false ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// header
if ( ! PlrListItemUpdate ( ListItem : : ID : : PLI_SCRIPTPLR , 0 , ppCurrInList ) )
new ScriptPlayersListItem ( this , * ppCurrInList ) ;
// players
C4PlayerInfo * pInfo ; int32_t iClientIdx = 0 ; C4ClientPlayerInfos * pInfos ;
2010-01-25 04:00:59 +00:00
while ( ( pInfos = Game . PlayerInfos . GetIndexedInfo ( iClientIdx + + ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int32_t iInfoIdx = 0 ;
2010-01-25 04:00:59 +00:00
while ( ( pInfo = pInfos - > GetPlayerInfo ( iInfoIdx + + ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( pInfo - > GetType ( ) ! = C4PT_Script ) continue ;
if ( pInfo - > IsRemoved ( ) ) continue ;
if ( pInfo - > IsInvisible ( ) ) continue ;
// show them
int32_t iInfoID = pInfo - > GetID ( ) ;
if ( ! PlrListItemUpdate ( ListItem : : ID : : PLI_PLAYER , iInfoID , ppCurrInList ) )
new PlayerListItem ( this , pInfos - > GetClientID ( ) , iInfoID , false , * ppCurrInList ) ;
}
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : UpdatePlayersByTeam ( ListItem * * ppCurrInList )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// sort by team
C4Team * pTeam ; int32_t i = 0 ;
2010-01-25 04:00:59 +00:00
while ( ( pTeam = Game . Teams . GetTeamByIndex ( i + + ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// no empty teams that are not used
if ( Game . Teams . IsAutoGenerateTeams ( ) & & ! pTeam - > GetPlayerCount ( ) ) continue ;
// the team label
if ( ! PlrListItemUpdate ( ListItem : : ID : : PLI_TEAM , pTeam - > GetID ( ) , ppCurrInList ) )
new TeamListItem ( this , pTeam - > GetID ( ) , * ppCurrInList ) ;
// players for this team
int32_t idPlr , j = 0 ; int32_t idClient ; C4Client * pClient ; C4PlayerInfo * pPlrInfo ;
2010-01-25 04:00:59 +00:00
while ( ( idPlr = pTeam - > GetIndexedPlayer ( j + + ) ) )
if ( ( pPlrInfo = Game . PlayerInfos . GetPlayerInfoByID ( idPlr , & idClient ) ) )
2009-05-08 13:28:41 +00:00
if ( ! pPlrInfo - > IsInvisible ( ) )
if ( ( pClient = Game . Clients . getClientByID ( idClient ) ) & & pClient - > isActivated ( ) )
if ( ! PlrListItemUpdate ( ListItem : : ID : : PLI_PLAYER , idPlr , ppCurrInList ) )
new PlayerListItem ( this , idClient , idPlr , false , * ppCurrInList ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : UpdatePlayersByRandomTeam ( ListItem * * ppCurrInList )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// team sort but teams set to random and invisible: Show all players within one "Random Team"-label
bool fTeamLabelPut = false ;
2016-11-02 23:58:02 +00:00
C4Client * pClient = nullptr ;
2010-01-25 04:00:59 +00:00
while ( ( pClient = Game . Clients . getClient ( pClient ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// player infos for this client - not for deactivated, and never in replays
if ( Game . C4S . Head . Replay | | ! pClient - > isActivated ( ) ) continue ;
C4ClientPlayerInfos * pInfoPacket = Game . PlayerInfos . GetInfoByClientID ( pClient - > getID ( ) ) ;
if ( pInfoPacket )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4PlayerInfo * pPlrInfo ; int32_t i = 0 ;
2010-01-25 04:00:59 +00:00
while ( ( pPlrInfo = pInfoPacket - > GetPlayerInfo ( i + + ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( pPlrInfo - > IsInvisible ( ) ) continue ;
if ( ! fTeamLabelPut )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( ! PlrListItemUpdate ( ListItem : : ID : : PLI_TEAM , TEAMID_Unknown , ppCurrInList ) )
new TeamListItem ( this , TEAMID_Unknown , * ppCurrInList ) ;
fTeamLabelPut = true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
if ( ! PlrListItemUpdate ( ListItem : : ID : : PLI_PLAYER , pPlrInfo - > GetID ( ) , ppCurrInList ) )
new PlayerListItem ( this , pClient - > getID ( ) , pPlrInfo - > GetID ( ) , false , * ppCurrInList ) ;
}
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : UpdatePlayersByClient ( ListItem * * ppCurrInList )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// regular players
2016-11-02 23:58:02 +00:00
C4Client * pClient = nullptr ;
2010-01-25 04:00:59 +00:00
while ( ( pClient = Game . Clients . getClient ( pClient ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// the client label
if ( ! PlrListItemUpdate ( ListItem : : ID : : PLI_CLIENT , pClient - > getID ( ) , ppCurrInList ) )
new ClientListItem ( this , pClient - > getCore ( ) , * ppCurrInList ) ;
// player infos for this client - not for observers, and never in replays
// could also check for activated here. However, non-observers will usually be activated later and thus be using their players
if ( Game . C4S . Head . Replay | | pClient - > isObserver ( ) ) continue ;
C4ClientPlayerInfos * pInfoPacket = Game . PlayerInfos . GetInfoByClientID ( pClient - > getID ( ) ) ;
if ( pInfoPacket )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4PlayerInfo * pPlrInfo ; int32_t i = 0 ;
2010-01-25 04:00:59 +00:00
while ( ( pPlrInfo = pInfoPacket - > GetPlayerInfo ( i + + ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( pPlrInfo - > GetType ( ) = = C4PT_Script ) continue ;
if ( pPlrInfo - > IsRemoved ( ) ) continue ;
if ( pPlrInfo - > IsInvisible ( ) ) continue ;
if ( ! PlrListItemUpdate ( ListItem : : ID : : PLI_PLAYER , pPlrInfo - > GetID ( ) , ppCurrInList ) )
new PlayerListItem ( this , pClient - > getID ( ) , pPlrInfo - > GetID ( ) , false , * ppCurrInList ) ;
}
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : UpdatePlayersByEvaluation ( ListItem * * ppCurrInList , bool fShowWinners )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// if a team filter is provided, add team label first
if ( iTeamFilter )
if ( ! PlrListItemUpdate ( ListItem : : ID : : PLI_TEAM , iTeamFilter , ppCurrInList ) )
new TeamListItem ( this , iTeamFilter , * ppCurrInList ) ;
// Add by teams: In show-winner-mode winning teams first
// Otherwise, just add all
AddMode pShowWinnersAddModes [ ] = { AM_Winners , AM_Losers } ;
AddMode pHideWinnersAddModes [ ] = { AM_All } ;
AddMode * pAddModes ; int32_t iAddModeCount ;
if ( fShowWinners )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pAddModes = pShowWinnersAddModes ; iAddModeCount = 2 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pAddModes = pHideWinnersAddModes ; iAddModeCount = 1 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
for ( int32_t iAddMode = 0 ; iAddMode < iAddModeCount ; + + iAddMode )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
AddMode eAddMode = pAddModes [ iAddMode ] ;
if ( iTeamFilter )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Team filter mode: Add only players of specified team
UpdatePlayersByEvaluation ( ppCurrInList , Game . Teams . GetTeamByID ( iTeamFilter ) , eAddMode ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Normal mode: Add all teams of winning status
C4Team * pTeam ; int32_t i = 0 ;
2010-01-25 04:00:59 +00:00
while ( ( pTeam = Game . Teams . GetTeamByIndex ( i + + ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
UpdatePlayersByEvaluation ( ppCurrInList , pTeam , eAddMode ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Add teamless players of winning status
2016-11-02 23:58:02 +00:00
UpdatePlayersByEvaluation ( ppCurrInList , nullptr , eAddMode ) ;
2009-05-08 13:28:41 +00:00
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : UpdatePlayersByEvaluation ( ListItem * * ppCurrInList , C4Team * pTeam , C4PlayerInfoListBox : : AddMode eWinMode )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// check winning status of team first
if ( pTeam & & eWinMode ! = AM_All ) if ( pTeam - > HasWon ( ) ! = ( eWinMode = = AM_Winners ) ) return ;
// now add all matching players
int32_t iTeamID = pTeam ? pTeam - > GetID ( ) : 0 ;
C4ClientPlayerInfos * pInfoPacket ; int32_t iClient = 0 ;
2010-01-25 04:00:59 +00:00
while ( ( pInfoPacket = Game . PlayerInfos . GetIndexedInfo ( iClient + + ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4PlayerInfo * pPlrInfo ; int32_t i = 0 ;
2010-01-25 04:00:59 +00:00
while ( ( pPlrInfo = pInfoPacket - > GetPlayerInfo ( i + + ) ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( ! pPlrInfo - > HasJoined ( ) ) continue ;
if ( pPlrInfo - > GetTeam ( ) ! = iTeamID ) continue ;
if ( pPlrInfo - > IsInvisible ( ) ) continue ;
if ( ! pTeam & & eWinMode ! = AM_All & & pPlrInfo - > HasWon ( ) ! = ( eWinMode = = AM_Winners ) ) continue ;
if ( ! PlrListItemUpdate ( ListItem : : ID : : PLI_PLAYER , pPlrInfo - > GetID ( ) , ppCurrInList ) )
new PlayerListItem ( this , pInfoPacket - > GetClientID ( ) , pPlrInfo - > GetID ( ) , false , * ppCurrInList ) ;
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4PlayerInfoListBox : : IsPlayerItemCollapsed ( PlayerListItem * pItem )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// never if view is not collapsed
if ( ! fIsCollapsed ) return false ;
// collapsed if not selected
return GetSelectedItem ( ) ! = pItem ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : SetMode ( Mode eNewMode )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( eMode ! = eNewMode )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
eMode = eNewMode ;
Update ( ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4PlayerInfoListBox : : SetCustomFont ( CStdFont * pNewFont , uint32_t dwTextColor )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pCustomFont = pNewFont ;
this - > dwTextColor = dwTextColor ;
// update done later by caller anyway
2010-03-28 18:58:01 +00:00
}