2011-12-25 13:33:05 +00:00
/* (c) Shereef Marzouk. See "licence DDRace.txt" and the readme.txt in the root of the distribution for more information. */
2010-08-28 13:47:52 +00:00
# include "teams.h"
2019-06-25 19:03:15 +00:00
# include "score.h"
2010-11-06 22:54:35 +00:00
# include <engine/shared/config.h>
2010-08-28 13:47:52 +00:00
2011-12-25 13:51:04 +00:00
CGameTeams : : CGameTeams ( CGameContext * pGameContext ) :
m_pGameContext ( pGameContext )
2011-01-06 05:30:19 +00:00
{
2010-09-24 13:37:13 +00:00
Reset ( ) ;
}
2011-01-06 05:30:19 +00:00
void CGameTeams : : Reset ( )
{
2010-09-24 13:37:13 +00:00
m_Core . Reset ( ) ;
2013-12-28 15:09:03 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; + + i )
2011-01-06 05:30:19 +00:00
{
2011-02-02 10:49:19 +00:00
m_TeamState [ i ] = TEAMSTATE_EMPTY ;
2010-08-28 13:47:52 +00:00
m_TeeFinished [ i ] = false ;
2010-11-06 22:54:35 +00:00
m_MembersCount [ i ] = 0 ;
2010-12-19 03:48:16 +00:00
m_LastChat [ i ] = 0 ;
2013-11-15 23:44:49 +00:00
m_TeamLocked [ i ] = false ;
2014-12-17 19:38:05 +00:00
m_IsSaving [ i ] = false ;
2017-04-23 20:50:07 +00:00
m_Invited [ i ] = 0 ;
2020-05-22 21:59:47 +00:00
m_Practice [ i ] = false ;
2010-08-28 13:47:52 +00:00
}
}
2011-02-02 10:49:19 +00:00
void CGameTeams : : OnCharacterStart ( int ClientID )
{
2010-08-28 20:53:42 +00:00
int Tick = Server ( ) - > Tick ( ) ;
2011-03-16 13:14:25 +00:00
CCharacter * pStartingChar = Character ( ClientID ) ;
2019-04-06 15:22:15 +00:00
if ( ! pStartingChar )
2010-12-19 03:48:16 +00:00
return ;
2019-04-06 15:22:15 +00:00
if ( m_Core . Team ( ClientID ) ! = TEAM_FLOCK & & pStartingChar - > m_DDRaceState = = DDRACE_FINISHED )
2013-08-14 18:12:53 +00:00
return ;
2019-04-06 15:22:15 +00:00
if ( m_Core . Team ( ClientID ) = = TEAM_FLOCK
2011-12-25 13:51:04 +00:00
| | m_Core . Team ( ClientID ) = = TEAM_SUPER )
2010-12-19 03:48:16 +00:00
{
2011-03-16 13:14:25 +00:00
pStartingChar - > m_DDRaceState = DDRACE_STARTED ;
pStartingChar - > m_StartTime = Tick ;
2019-04-06 15:22:15 +00:00
return ;
2011-02-14 21:34:46 +00:00
}
2019-04-06 15:22:15 +00:00
bool Waiting = false ;
for ( int i = 0 ; i < MAX_CLIENTS ; + + i )
2010-12-19 03:48:16 +00:00
{
2019-04-06 15:22:15 +00:00
if ( m_Core . Team ( ClientID ) ! = m_Core . Team ( i ) )
continue ;
CPlayer * pPlayer = GetPlayer ( i ) ;
if ( ! pPlayer | | ! pPlayer - > IsPlaying ( ) )
continue ;
if ( GetDDRaceState ( pPlayer ) ! = DDRACE_FINISHED )
continue ;
2013-11-15 23:44:49 +00:00
2019-04-06 15:22:15 +00:00
Waiting = true ;
pStartingChar - > m_DDRaceState = DDRACE_NONE ;
2010-12-19 03:48:16 +00:00
2019-04-06 15:22:15 +00:00
if ( m_LastChat [ ClientID ] + Server ( ) - > TickSpeed ( )
+ g_Config . m_SvChatDelay < Tick )
2010-12-19 03:48:16 +00:00
{
2019-04-06 15:22:15 +00:00
char aBuf [ 128 ] ;
str_format (
aBuf ,
sizeof ( aBuf ) ,
" %s has finished and didn't go through start yet, wait for him or join another team. " ,
Server ( ) - > ClientName ( i ) ) ;
GameServer ( ) - > SendChatTarget ( ClientID , aBuf ) ;
m_LastChat [ ClientID ] = Tick ;
}
if ( m_LastChat [ i ] + Server ( ) - > TickSpeed ( )
+ g_Config . m_SvChatDelay < Tick )
{
char aBuf [ 128 ] ;
2017-07-29 21:11:33 +00:00
str_format (
aBuf ,
sizeof ( aBuf ) ,
2019-04-06 15:22:15 +00:00
" %s wants to start a new round, kill or walk to start. " ,
Server ( ) - > ClientName ( ClientID ) ) ;
GameServer ( ) - > SendChatTarget ( i , aBuf ) ;
m_LastChat [ i ] = Tick ;
}
}
if ( m_TeamState [ m_Core . Team ( ClientID ) ] < TEAMSTATE_STARTED & & ! Waiting )
{
ChangeTeamState ( m_Core . Team ( ClientID ) , TEAMSTATE_STARTED ) ;
2017-07-29 21:11:33 +00:00
2020-05-23 19:53:12 +00:00
int NumPlayers = Count ( m_Core . Team ( ClientID ) ) ;
2019-04-06 15:22:15 +00:00
char aBuf [ 512 ] ;
str_format (
aBuf ,
sizeof ( aBuf ) ,
2020-05-23 19:53:12 +00:00
" Team %d started with %d player%s: " ,
2019-04-06 15:22:15 +00:00
m_Core . Team ( ClientID ) ,
2020-05-23 19:53:12 +00:00
NumPlayers ,
NumPlayers = = 1 ? " " : " s " ) ;
2017-07-29 21:11:33 +00:00
2019-04-06 15:22:15 +00:00
bool First = true ;
for ( int i = 0 ; i < MAX_CLIENTS ; + + i )
{
if ( m_Core . Team ( ClientID ) = = m_Core . Team ( i ) )
2010-12-19 03:48:16 +00:00
{
2019-04-06 15:22:15 +00:00
CPlayer * pPlayer = GetPlayer ( i ) ;
// TODO: THE PROBLEM IS THAT THERE IS NO CHARACTER SO START TIME CAN'T BE SET!
if ( pPlayer & & ( pPlayer - > IsPlaying ( ) | | TeamLocked ( m_Core . Team ( ClientID ) ) ) )
2010-12-19 03:48:16 +00:00
{
2019-04-06 15:22:15 +00:00
SetDDRaceState ( pPlayer , DDRACE_STARTED ) ;
SetStartTime ( pPlayer , Tick ) ;
2017-07-29 21:11:33 +00:00
2019-04-06 15:22:15 +00:00
if ( First )
First = false ;
else
str_append ( aBuf , " , " , sizeof ( aBuf ) ) ;
2017-07-29 21:11:33 +00:00
2019-04-06 15:22:15 +00:00
str_append ( aBuf , GameServer ( ) - > Server ( ) - > ClientName ( i ) , sizeof ( aBuf ) ) ;
2017-07-29 21:11:33 +00:00
}
}
2019-04-06 15:22:15 +00:00
}
2017-07-29 21:11:33 +00:00
2019-04-06 15:22:15 +00:00
if ( g_Config . m_SvTeam < 3 & & g_Config . m_SvTeamMaxSize ! = 2 & & g_Config . m_SvPauseable )
{
for ( int i = 0 ; i < MAX_CLIENTS ; + + i )
2017-07-29 21:11:33 +00:00
{
2019-04-06 15:22:15 +00:00
CPlayer * pPlayer = GetPlayer ( i ) ;
if ( m_Core . Team ( ClientID ) = = m_Core . Team ( i ) & & pPlayer & & ( pPlayer - > IsPlaying ( ) | | TeamLocked ( m_Core . Team ( ClientID ) ) ) )
2017-07-29 21:13:04 +00:00
{
2019-04-06 15:22:15 +00:00
GameServer ( ) - > SendChatTarget ( i , aBuf ) ;
2010-08-28 20:53:42 +00:00
}
2010-08-28 13:47:52 +00:00
}
}
}
}
2011-02-02 10:49:19 +00:00
void CGameTeams : : OnCharacterFinish ( int ClientID )
2011-01-06 05:30:19 +00:00
{
2011-12-25 13:51:04 +00:00
if ( m_Core . Team ( ClientID ) = = TEAM_FLOCK
| | m_Core . Team ( ClientID ) = = TEAM_SUPER )
2010-12-19 03:48:16 +00:00
{
2011-06-06 19:24:27 +00:00
CPlayer * pPlayer = GetPlayer ( ClientID ) ;
2011-12-25 13:51:04 +00:00
if ( pPlayer & & pPlayer - > IsPlaying ( ) )
2019-01-10 08:32:23 +00:00
{
float Time = ( float ) ( Server ( ) - > Tick ( ) - GetStartTime ( pPlayer ) )
/ ( ( float ) Server ( ) - > TickSpeed ( ) ) ;
if ( Time < 0.000001f )
return ;
2019-04-02 17:53:37 +00:00
char aTimestamp [ TIMESTAMP_STR_LENGTH ] ;
str_timestamp_format ( aTimestamp , sizeof ( aTimestamp ) , FORMAT_SPACE ) ; // 2019-04-02 19:41:58
OnFinish ( pPlayer , Time , aTimestamp ) ;
2019-01-10 08:32:23 +00:00
}
2010-12-19 03:48:16 +00:00
}
else
{
2011-02-02 10:49:19 +00:00
m_TeeFinished [ ClientID ] = true ;
2013-07-21 06:46:52 +00:00
2014-09-26 01:42:49 +00:00
CheckTeamFinished ( m_Core . Team ( ClientID ) ) ;
}
}
2013-07-21 06:46:52 +00:00
2014-09-26 01:42:49 +00:00
void CGameTeams : : CheckTeamFinished ( int Team )
{
if ( TeamFinished ( Team ) )
{
CPlayer * TeamPlayers [ MAX_CLIENTS ] ;
unsigned int PlayersCount = 0 ;
for ( int i = 0 ; i < MAX_CLIENTS ; + + i )
{
if ( Team = = m_Core . Team ( i ) )
2010-12-19 03:48:16 +00:00
{
2014-09-26 01:42:49 +00:00
CPlayer * pPlayer = GetPlayer ( i ) ;
if ( pPlayer & & pPlayer - > IsPlaying ( ) )
2010-12-19 03:48:16 +00:00
{
2014-09-26 01:42:49 +00:00
m_TeeFinished [ i ] = false ;
2013-07-21 06:46:52 +00:00
2014-09-26 01:42:49 +00:00
TeamPlayers [ PlayersCount + + ] = pPlayer ;
2010-08-28 20:53:42 +00:00
}
}
2010-08-28 13:47:52 +00:00
}
2014-09-26 01:42:49 +00:00
2014-09-26 10:43:56 +00:00
if ( PlayersCount > 0 )
2014-09-26 11:03:01 +00:00
{
2019-01-10 08:32:23 +00:00
float Time = ( float ) ( Server ( ) - > Tick ( ) - GetStartTime ( TeamPlayers [ 0 ] ) )
/ ( ( float ) Server ( ) - > TickSpeed ( ) ) ;
if ( Time < 0.000001f )
2020-05-22 21:59:47 +00:00
{
return ;
}
if ( m_Practice [ Team ] )
{
ChangeTeamState ( Team , TEAMSTATE_FINISHED ) ;
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) ,
" Your team would've finished in: %d minute(s) %5.2f second(s). Since you had practice mode enabled your rank doesn't count. " ,
( int ) Time / 60 , Time - ( ( int ) Time / 60 * 60 ) ) ;
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
{
if ( m_Core . Team ( i ) = = Team & & GameServer ( ) - > m_apPlayers [ i ] )
{
GameServer ( ) - > SendChatTarget ( i , aBuf ) ;
}
}
for ( unsigned int i = 0 ; i < PlayersCount ; + + i )
{
SetDDRaceState ( TeamPlayers [ i ] , DDRACE_FINISHED ) ;
}
2019-01-10 08:32:23 +00:00
return ;
2020-05-22 21:59:47 +00:00
}
2019-04-02 17:53:37 +00:00
char aTimestamp [ TIMESTAMP_STR_LENGTH ] ;
str_timestamp_format ( aTimestamp , sizeof ( aTimestamp ) , FORMAT_SPACE ) ; // 2019-04-02 19:41:58
2019-01-10 08:32:23 +00:00
2019-01-10 20:11:23 +00:00
for ( unsigned int i = 0 ; i < PlayersCount ; + + i )
2019-04-02 17:53:37 +00:00
OnFinish ( TeamPlayers [ i ] , Time , aTimestamp ) ;
2014-09-26 11:03:01 +00:00
ChangeTeamState ( Team , TEAMSTATE_FINISHED ) ; //TODO: Make it better
//ChangeTeamState(Team, TEAMSTATE_OPEN);
2019-04-02 17:53:37 +00:00
OnTeamFinish ( TeamPlayers , PlayersCount , Time , aTimestamp ) ;
2014-09-26 11:03:01 +00:00
}
2010-08-28 13:47:52 +00:00
}
}
2011-03-16 13:14:25 +00:00
bool CGameTeams : : SetCharacterTeam ( int ClientID , int Team )
2011-02-14 18:36:30 +00:00
{
2011-03-16 13:14:25 +00:00
//Check on wrong parameters. +1 for TEAM_SUPER
2011-12-25 13:51:04 +00:00
if ( ClientID < 0 | | ClientID > = MAX_CLIENTS | | Team < 0
| | Team > = MAX_CLIENTS + 1 )
2011-03-16 13:14:25 +00:00
return false ;
//You can join to TEAM_SUPER at any time, but any other group you cannot if it started
2011-12-25 13:51:04 +00:00
if ( Team ! = TEAM_SUPER & & m_TeamState [ Team ] > TEAMSTATE_OPEN )
2011-03-16 13:14:25 +00:00
return false ;
//No need to switch team if you there
2011-12-25 13:51:04 +00:00
if ( m_Core . Team ( ClientID ) = = Team )
2011-03-16 13:14:25 +00:00
return false ;
2014-01-10 23:13:35 +00:00
if ( ! Character ( ClientID ) )
return false ;
2011-03-16 13:14:25 +00:00
//You cannot be in TEAM_SUPER if you not super
2011-12-25 13:51:04 +00:00
if ( Team = = TEAM_SUPER & & ! Character ( ClientID ) - > m_Super )
return false ;
2011-03-16 13:14:25 +00:00
//if you begin race
2013-10-07 12:09:30 +00:00
if ( Character ( ClientID ) - > m_DDRaceState ! = DDRACE_NONE & & Team ! = TEAM_SUPER )
return false ;
2020-05-28 09:38:51 +00:00
//No cheating through noob filter with practice and then leaving team
if ( m_Practice [ m_Core . Team ( ClientID ) ] )
return false ;
2013-10-07 12:09:30 +00:00
2020-05-27 18:09:45 +00:00
//you can not join a team which is currently in the process of saving,
//because the save-process can fail and then the team is reset into the game
if ( Team ! = TEAM_SUPER & & m_IsSaving [ Team ] )
return false ;
2011-02-02 10:49:19 +00:00
SetForceCharacterTeam ( ClientID , Team ) ;
2011-12-25 13:51:04 +00:00
2011-03-16 13:14:25 +00:00
//GameServer()->CreatePlayerSpawn(Character(id)->m_Core.m_Pos, TeamMask());
return true ;
2010-09-22 10:43:59 +00:00
}
2011-02-02 10:49:19 +00:00
void CGameTeams : : SetForceCharacterTeam ( int ClientID , int Team )
2014-01-11 14:19:34 +00:00
{
2014-01-24 14:12:46 +00:00
int OldTeam = m_Core . Team ( ClientID ) ;
2014-09-26 21:47:25 +00:00
if ( Team ! = m_Core . Team ( ClientID ) )
ForceLeaveTeam ( ClientID ) ;
2014-09-29 17:32:43 +00:00
else
{
m_TeeFinished [ ClientID ] = false ;
if ( Count ( m_Core . Team ( ClientID ) ) > 0 )
m_MembersCount [ m_Core . Team ( ClientID ) ] - - ;
}
2014-01-11 14:19:34 +00:00
2020-05-30 22:34:29 +00:00
SetForceCharacterNewTeam ( ClientID , Team ) ;
if ( OldTeam ! = Team )
{
for ( int LoopClientID = 0 ; LoopClientID < MAX_CLIENTS ; + + LoopClientID )
if ( GetPlayer ( LoopClientID ) )
SendTeamsState ( LoopClientID ) ;
if ( GetPlayer ( ClientID ) )
GetPlayer ( ClientID ) - > m_VotedForPractice = false ;
}
}
void CGameTeams : : SetForceCharacterNewTeam ( int ClientID , int Team )
{
2014-01-11 14:19:34 +00:00
m_Core . Team ( ClientID , Team ) ;
2014-09-29 17:32:43 +00:00
if ( m_Core . Team ( ClientID ) ! = TEAM_SUPER )
2014-01-11 14:19:34 +00:00
m_MembersCount [ m_Core . Team ( ClientID ) ] + + ;
2014-03-10 12:39:50 +00:00
if ( Team ! = TEAM_SUPER & & ( m_TeamState [ Team ] = = TEAMSTATE_EMPTY | | m_TeamLocked [ Team ] ) )
2014-01-11 14:19:34 +00:00
{
2014-03-12 18:36:25 +00:00
if ( ! m_TeamLocked [ Team ] )
ChangeTeamState ( Team , TEAMSTATE_OPEN ) ;
2014-01-11 14:19:34 +00:00
if ( GameServer ( ) - > Collision ( ) - > m_NumSwitchers > 0 ) {
for ( int i = 0 ; i < GameServer ( ) - > Collision ( ) - > m_NumSwitchers + 1 ; + + i )
{
2015-07-22 21:31:50 +00:00
GameServer ( ) - > Collision ( ) - > m_pSwitchers [ i ] . m_Status [ Team ] = GameServer ( ) - > Collision ( ) - > m_pSwitchers [ i ] . m_Initial ;
2014-01-11 14:19:34 +00:00
GameServer ( ) - > Collision ( ) - > m_pSwitchers [ i ] . m_EndTick [ Team ] = 0 ;
GameServer ( ) - > Collision ( ) - > m_pSwitchers [ i ] . m_Type [ Team ] = TILE_SWITCHOPEN ;
}
}
}
}
void CGameTeams : : ForceLeaveTeam ( int ClientID )
2011-01-06 05:30:19 +00:00
{
2011-02-02 10:49:19 +00:00
m_TeeFinished [ ClientID ] = false ;
2014-01-11 14:19:34 +00:00
2011-12-25 13:51:04 +00:00
if ( m_Core . Team ( ClientID ) ! = TEAM_FLOCK
& & m_Core . Team ( ClientID ) ! = TEAM_SUPER
& & m_TeamState [ m_Core . Team ( ClientID ) ] ! = TEAMSTATE_EMPTY )
2011-01-06 05:30:19 +00:00
{
2010-08-28 20:53:42 +00:00
bool NoOneInOldTeam = true ;
2011-12-25 13:51:04 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; + + i )
if ( i ! = ClientID & & m_Core . Team ( ClientID ) = = m_Core . Team ( i ) )
2011-01-06 05:30:19 +00:00
{
2011-12-25 13:51:04 +00:00
NoOneInOldTeam = false ; //all good exists someone in old team
2010-08-28 20:53:42 +00:00
break ;
2011-06-06 19:24:27 +00:00
}
2011-12-25 13:51:04 +00:00
if ( NoOneInOldTeam )
2013-11-15 23:44:49 +00:00
{
2011-03-16 13:14:25 +00:00
m_TeamState [ m_Core . Team ( ClientID ) ] = TEAMSTATE_EMPTY ;
2013-11-15 23:44:49 +00:00
// unlock team when last player leaves
SetTeamLock ( m_Core . Team ( ClientID ) , false ) ;
2017-04-24 09:54:28 +00:00
ResetInvited ( m_Core . Team ( ClientID ) ) ;
2020-05-22 21:59:47 +00:00
m_Practice [ m_Core . Team ( ClientID ) ] = false ;
2013-11-15 23:44:49 +00:00
}
2010-08-28 13:47:52 +00:00
}
2014-01-11 14:19:34 +00:00
2011-12-25 13:51:04 +00:00
if ( Count ( m_Core . Team ( ClientID ) ) > 0 )
m_MembersCount [ m_Core . Team ( ClientID ) ] - - ;
2011-02-02 10:49:19 +00:00
}
2010-11-06 22:54:35 +00:00
2011-02-02 10:49:19 +00:00
int CGameTeams : : Count ( int Team ) const
2011-01-06 05:30:19 +00:00
{
2011-12-25 13:51:04 +00:00
if ( Team = = TEAM_SUPER )
2011-02-02 10:49:19 +00:00
return - 1 ;
return m_MembersCount [ Team ] ;
2010-08-28 13:47:52 +00:00
}
2011-03-16 13:14:25 +00:00
void CGameTeams : : ChangeTeamState ( int Team , int State )
{
2011-12-25 13:19:03 +00:00
int OldState = m_TeamState [ Team ] ;
2011-03-16 13:14:25 +00:00
m_TeamState [ Team ] = State ;
2011-12-25 13:19:03 +00:00
onChangeTeamState ( Team , State , OldState ) ;
}
void CGameTeams : : onChangeTeamState ( int Team , int State , int OldState )
{
2011-12-25 13:51:04 +00:00
if ( OldState ! = State & & State = = TEAMSTATE_STARTED )
2011-12-25 13:19:03 +00:00
{
// OnTeamStateStarting
}
2011-12-25 13:51:04 +00:00
if ( OldState ! = State & & State = = TEAMSTATE_FINISHED )
2011-12-25 13:19:03 +00:00
{
// OnTeamStateFinishing
}
2011-03-16 13:14:25 +00:00
}
2011-01-06 05:30:19 +00:00
bool CGameTeams : : TeamFinished ( int Team )
{
2011-12-25 13:51:04 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; + + i )
if ( m_Core . Team ( i ) = = Team & & ! m_TeeFinished [ i ] )
2011-03-16 13:14:25 +00:00
return false ;
2010-08-28 13:47:52 +00:00
return true ;
2010-09-08 16:22:11 +00:00
}
2013-12-31 05:13:57 +00:00
int64_t CGameTeams : : TeamMask ( int Team , int ExceptID , int Asker )
2011-01-06 05:30:19 +00:00
{
2014-01-22 14:47:01 +00:00
int64_t Mask = 0 ;
2014-01-20 19:12:03 +00:00
2011-12-25 13:51:04 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; + + i )
2014-01-20 19:12:03 +00:00
{
if ( i = = ExceptID )
continue ; // Explicitly excluded
if ( ! GetPlayer ( i ) )
continue ; // Player doesn't exist
2017-04-08 22:20:41 +00:00
if ( ! ( GetPlayer ( i ) - > GetTeam ( ) = = - 1 | | GetPlayer ( i ) - > IsPaused ( ) ) )
2014-01-20 19:12:03 +00:00
{ // Not spectator
if ( i ! = Asker )
{ // Actions of other players
if ( ! Character ( i ) )
continue ; // Player is currently dead
2014-02-19 21:30:57 +00:00
if ( ! GetPlayer ( i ) - > m_ShowOthers )
{
2014-01-24 21:27:34 +00:00
if ( m_Core . GetSolo ( Asker ) )
continue ; // When in solo part don't show others
if ( m_Core . GetSolo ( i ) )
continue ; // When in solo part don't show others
if ( m_Core . Team ( i ) ! = Team & & m_Core . Team ( i ) ! = TEAM_SUPER )
continue ; // In different teams
} // ShowOthers
2014-01-20 19:12:03 +00:00
} // See everything of yourself
}
else if ( GetPlayer ( i ) - > m_SpectatorID ! = SPEC_FREEVIEW )
{ // Spectating specific player
2014-01-22 20:48:13 +00:00
if ( GetPlayer ( i ) - > m_SpectatorID ! = Asker )
2014-01-20 19:12:03 +00:00
{ // Actions of other players
2014-01-24 21:27:34 +00:00
if ( ! Character ( GetPlayer ( i ) - > m_SpectatorID ) )
continue ; // Player is currently dead
2014-02-19 21:30:57 +00:00
if ( ! GetPlayer ( i ) - > m_ShowOthers )
{
2014-01-24 21:27:34 +00:00
if ( m_Core . GetSolo ( Asker ) )
continue ; // When in solo part don't show others
if ( m_Core . GetSolo ( GetPlayer ( i ) - > m_SpectatorID ) )
continue ; // When in solo part don't show others
if ( m_Core . Team ( GetPlayer ( i ) - > m_SpectatorID ) ! = Team & & m_Core . Team ( GetPlayer ( i ) - > m_SpectatorID ) ! = TEAM_SUPER )
continue ; // In different teams
} // ShowOthers
2014-01-20 19:12:03 +00:00
} // See everything of player you're spectating
2014-08-09 17:53:38 +00:00
}
else
{ // Freeview
if ( GetPlayer ( i ) - > m_SpecTeam )
{ // Show only players in own team when spectating
if ( m_Core . Team ( i ) ! = Team & & m_Core . Team ( i ) ! = TEAM_SUPER )
continue ; // in different teams
}
}
2014-01-20 19:12:03 +00:00
Mask | = 1LL < < i ;
}
2010-09-08 16:22:11 +00:00
return Mask ;
}
2010-10-24 10:47:25 +00:00
2011-02-02 10:49:19 +00:00
void CGameTeams : : SendTeamsState ( int ClientID )
2011-01-06 05:30:19 +00:00
{
2014-01-22 00:39:18 +00:00
if ( g_Config . m_SvTeam = = 3 )
return ;
2020-05-22 15:58:41 +00:00
if ( ! m_pGameContext - > m_apPlayers [ ClientID ] | | m_pGameContext - > m_apPlayers [ ClientID ] - > GetClientVersion ( ) < = VERSION_DDRACE )
2014-01-22 14:29:30 +00:00
return ;
2014-01-21 23:08:30 +00:00
CMsgPacker Msg ( NETMSGTYPE_SV_TEAMSSTATE ) ;
2014-01-31 20:21:50 +00:00
for ( unsigned i = 0 ; i < MAX_CLIENTS ; i + + )
Msg . AddInt ( m_Core . Team ( i ) ) ;
2014-01-21 23:08:30 +00:00
Server ( ) - > SendMsg ( & Msg , MSGFLAG_VITAL , ClientID ) ;
2010-10-24 10:47:25 +00:00
}
2011-06-06 19:24:27 +00:00
int CGameTeams : : GetDDRaceState ( CPlayer * Player )
{
2011-12-25 13:51:04 +00:00
if ( ! Player )
2011-06-06 19:24:27 +00:00
return DDRACE_NONE ;
CCharacter * pChar = Player - > GetCharacter ( ) ;
2011-12-25 13:51:04 +00:00
if ( pChar )
2011-06-06 19:24:27 +00:00
return pChar - > m_DDRaceState ;
return DDRACE_NONE ;
}
void CGameTeams : : SetDDRaceState ( CPlayer * Player , int DDRaceState )
{
2011-12-25 13:51:04 +00:00
if ( ! Player )
2011-06-06 19:24:27 +00:00
return ;
CCharacter * pChar = Player - > GetCharacter ( ) ;
2011-12-25 13:51:04 +00:00
if ( pChar )
2011-06-06 19:24:27 +00:00
pChar - > m_DDRaceState = DDRaceState ;
}
int CGameTeams : : GetStartTime ( CPlayer * Player )
{
2011-12-25 13:51:04 +00:00
if ( ! Player )
2011-06-06 19:24:27 +00:00
return 0 ;
CCharacter * pChar = Player - > GetCharacter ( ) ;
2011-12-25 13:51:04 +00:00
if ( pChar )
2011-06-06 19:24:27 +00:00
return pChar - > m_StartTime ;
return 0 ;
}
void CGameTeams : : SetStartTime ( CPlayer * Player , int StartTime )
{
2011-12-25 13:51:04 +00:00
if ( ! Player )
2011-06-06 19:24:27 +00:00
return ;
CCharacter * pChar = Player - > GetCharacter ( ) ;
2011-12-25 13:51:04 +00:00
if ( pChar )
2011-06-06 19:24:27 +00:00
pChar - > m_StartTime = StartTime ;
}
void CGameTeams : : SetCpActive ( CPlayer * Player , int CpActive )
{
2011-12-25 13:51:04 +00:00
if ( ! Player )
2011-06-06 19:24:27 +00:00
return ;
CCharacter * pChar = Player - > GetCharacter ( ) ;
2011-12-25 13:51:04 +00:00
if ( pChar )
2011-06-06 19:24:27 +00:00
pChar - > m_CpActive = CpActive ;
}
float * CGameTeams : : GetCpCurrent ( CPlayer * Player )
{
2011-12-25 13:51:04 +00:00
if ( ! Player )
2011-06-06 19:24:27 +00:00
return NULL ;
CCharacter * pChar = Player - > GetCharacter ( ) ;
2011-12-25 13:51:04 +00:00
if ( pChar )
2011-06-06 19:24:27 +00:00
return pChar - > m_CpCurrent ;
return NULL ;
}
2019-04-02 17:53:37 +00:00
void CGameTeams : : OnTeamFinish ( CPlayer * * Players , unsigned int Size , float Time , const char * pTimestamp )
2013-07-21 06:46:52 +00:00
{
bool CallSaveScore = false ;
# if defined(CONF_SQL)
CallSaveScore = g_Config . m_SvUseSQL ;
# endif
2013-07-22 22:15:50 +00:00
int PlayerCIDs [ MAX_CLIENTS ] ;
2013-07-21 06:46:52 +00:00
for ( unsigned int i = 0 ; i < Size ; i + + )
{
PlayerCIDs [ i ] = Players [ i ] - > GetCID ( ) ;
2014-07-07 23:58:27 +00:00
2014-07-19 15:11:00 +00:00
if ( g_Config . m_SvRejoinTeam0 & & g_Config . m_SvTeam ! = 3 & & ( m_Core . Team ( Players [ i ] - > GetCID ( ) ) > = TEAM_SUPER | | ! m_TeamLocked [ m_Core . Team ( Players [ i ] - > GetCID ( ) ) ] ) )
2014-08-01 14:00:04 +00:00
{
2014-07-07 23:58:27 +00:00
SetForceCharacterTeam ( Players [ i ] - > GetCID ( ) , 0 ) ;
2014-08-01 14:00:04 +00:00
char aBuf [ 512 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " %s joined team 0 " ,
GameServer ( ) - > Server ( ) - > ClientName ( Players [ i ] - > GetCID ( ) ) ) ;
GameServer ( ) - > SendChat ( - 1 , CGameContext : : CHAT_ALL , aBuf ) ;
}
2013-07-21 06:46:52 +00:00
}
2013-12-10 17:45:28 +00:00
if ( CallSaveScore & & Size > = 2 )
2019-04-02 17:53:37 +00:00
GameServer ( ) - > Score ( ) - > SaveTeamScore ( PlayerCIDs , Size , Time , pTimestamp ) ;
2013-07-21 06:46:52 +00:00
}
2019-04-02 17:53:37 +00:00
void CGameTeams : : OnFinish ( CPlayer * Player , float Time , const char * pTimestamp )
2011-06-06 19:24:27 +00:00
{
2011-12-25 13:51:04 +00:00
if ( ! Player | | ! Player - > IsPlaying ( ) )
2011-06-06 19:24:27 +00:00
return ;
//TODO:DDRace:btd: this ugly
CPlayerData * pData = GameServer ( ) - > Score ( ) - > PlayerData ( Player - > GetCID ( ) ) ;
char aBuf [ 128 ] ;
2011-12-25 13:51:04 +00:00
SetCpActive ( Player , - 2 ) ;
str_format ( aBuf , sizeof ( aBuf ) ,
" %s finished in: %d minute(s) %5.2f second(s) " ,
2017-03-21 10:24:44 +00:00
Server ( ) - > ClientName ( Player - > GetCID ( ) ) , ( int ) Time / 60 ,
Time - ( ( int ) Time / 60 * 60 ) ) ;
2014-02-19 02:47:15 +00:00
if ( g_Config . m_SvHideScore | | ! g_Config . m_SvSaveWorseScores )
2011-12-25 13:51:04 +00:00
GameServer ( ) - > SendChatTarget ( Player - > GetCID ( ) , aBuf ) ;
else
GameServer ( ) - > SendChat ( - 1 , CGameContext : : CHAT_ALL , aBuf ) ;
2017-03-21 10:24:44 +00:00
float Diff = fabs ( Time - pData - > m_BestTime ) ;
2013-12-09 16:24:02 +00:00
2017-03-21 10:24:44 +00:00
if ( Time - pData - > m_BestTime < 0 )
2011-12-25 13:51:04 +00:00
{
// new record \o/
2017-03-21 10:24:44 +00:00
Server ( ) - > SaveDemo ( Player - > GetCID ( ) , Time ) ;
2014-09-26 00:05:22 +00:00
2017-03-21 10:24:44 +00:00
if ( Diff > = 60 )
2013-12-09 16:24:02 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " New record: %d minute(s) %5.2f second(s) better. " ,
2017-03-21 10:24:44 +00:00
( int ) Diff / 60 , Diff - ( ( int ) Diff / 60 * 60 ) ) ;
2013-12-09 16:24:02 +00:00
else
str_format ( aBuf , sizeof ( aBuf ) , " New record: %5.2f second(s) better. " ,
2017-03-21 10:24:44 +00:00
Diff ) ;
2014-02-19 02:47:15 +00:00
if ( g_Config . m_SvHideScore | | ! g_Config . m_SvSaveWorseScores )
2011-06-06 19:24:27 +00:00
GameServer ( ) - > SendChatTarget ( Player - > GetCID ( ) , aBuf ) ;
else
GameServer ( ) - > SendChat ( - 1 , CGameContext : : CHAT_ALL , aBuf ) ;
2011-12-25 13:51:04 +00:00
}
else if ( pData - > m_BestTime ! = 0 ) // tee has already finished?
{
2014-09-26 00:05:22 +00:00
Server ( ) - > StopRecord ( Player - > GetCID ( ) ) ;
2019-07-08 21:08:42 +00:00
if ( Diff < = 0.005f )
2011-06-06 19:24:27 +00:00
{
2011-12-25 13:51:04 +00:00
GameServer ( ) - > SendChatTarget ( Player - > GetCID ( ) ,
" You finished with your best time. " ) ;
2011-06-06 19:24:27 +00:00
}
2011-12-25 13:51:04 +00:00
else
2011-06-06 19:24:27 +00:00
{
2017-03-21 10:24:44 +00:00
if ( Diff > = 60 )
2013-12-09 16:24:02 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " %d minute(s) %5.2f second(s) worse, better luck next time. " ,
2017-03-21 10:24:44 +00:00
( int ) Diff / 60 , Diff - ( ( int ) Diff / 60 * 60 ) ) ;
2013-12-09 16:24:02 +00:00
else
str_format ( aBuf , sizeof ( aBuf ) ,
" %5.2f second(s) worse, better luck next time. " ,
2017-03-21 10:24:44 +00:00
Diff ) ;
2011-12-25 13:51:04 +00:00
GameServer ( ) - > SendChatTarget ( Player - > GetCID ( ) , aBuf ) ; //this is private, sent only to the tee
2011-06-06 19:24:27 +00:00
}
2011-12-25 13:51:04 +00:00
}
2014-09-26 00:05:22 +00:00
else
{
2017-03-21 10:24:44 +00:00
Server ( ) - > SaveDemo ( Player - > GetCID ( ) , Time ) ;
2014-09-26 00:05:22 +00:00
}
2011-06-06 19:24:27 +00:00
2011-12-25 13:51:04 +00:00
bool CallSaveScore = false ;
# if defined(CONF_SQL)
2014-02-18 21:08:43 +00:00
CallSaveScore = g_Config . m_SvUseSQL & & g_Config . m_SvSaveWorseScores ;
2011-12-25 13:51:04 +00:00
# endif
2011-06-06 19:24:27 +00:00
2017-03-21 10:24:44 +00:00
if ( ! pData - > m_BestTime | | Time < pData - > m_BestTime )
2011-12-25 13:51:04 +00:00
{
// update the score
2017-03-21 10:24:44 +00:00
pData - > Set ( Time , GetCpCurrent ( Player ) ) ;
2011-12-25 13:51:04 +00:00
CallSaveScore = true ;
}
2011-06-06 19:24:27 +00:00
2011-12-25 13:51:04 +00:00
if ( CallSaveScore )
2018-07-25 08:29:05 +00:00
if ( g_Config . m_SvNamelessScore | | ! str_startswith ( Server ( ) - > ClientName ( Player - > GetCID ( ) ) , " nameless tee " ) )
2019-04-02 17:53:37 +00:00
GameServer ( ) - > Score ( ) - > SaveScore ( Player - > GetCID ( ) , Time , pTimestamp ,
2018-12-17 13:55:58 +00:00
GetCpCurrent ( Player ) , Player - > m_NotEligibleForFinish ) ;
2011-06-06 19:24:27 +00:00
2011-12-25 13:51:04 +00:00
bool NeedToSendNewRecord = false ;
// update server best time
if ( GameServer ( ) - > m_pController - > m_CurrentRecord = = 0
2017-03-21 10:24:44 +00:00
| | Time < GameServer ( ) - > m_pController - > m_CurrentRecord )
2011-12-25 13:51:04 +00:00
{
// check for nameless
2018-07-25 08:29:05 +00:00
if ( g_Config . m_SvNamelessScore | | ! str_startswith ( Server ( ) - > ClientName ( Player - > GetCID ( ) ) , " nameless tee " ) )
2011-06-06 19:24:27 +00:00
{
2017-03-21 10:24:44 +00:00
GameServer ( ) - > m_pController - > m_CurrentRecord = Time ;
2011-12-25 13:51:04 +00:00
//dbg_msg("character", "Finish");
NeedToSendNewRecord = true ;
2011-06-06 19:24:27 +00:00
}
2011-12-25 13:51:04 +00:00
}
2011-06-06 19:24:27 +00:00
2011-12-25 13:51:04 +00:00
SetDDRaceState ( Player , DDRACE_FINISHED ) ;
// set player score
2017-03-21 10:24:44 +00:00
if ( ! pData - > m_CurrentTime | | pData - > m_CurrentTime > Time )
2011-12-25 13:51:04 +00:00
{
2017-03-21 10:24:44 +00:00
pData - > m_CurrentTime = Time ;
2011-12-25 13:51:04 +00:00
NeedToSendNewRecord = true ;
}
2011-06-06 19:24:27 +00:00
2020-05-22 15:58:41 +00:00
if ( NeedToSendNewRecord & & Player - > GetClientVersion ( ) > = VERSION_DDRACE )
2011-12-25 13:51:04 +00:00
{
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
{
if ( GameServer ( ) - > m_apPlayers [ i ]
2020-05-22 15:58:41 +00:00
& & GameServer ( ) - > m_apPlayers [ i ] - > GetClientVersion ( ) > = VERSION_DDRACE )
2011-06-06 19:24:27 +00:00
{
2011-12-25 13:51:04 +00:00
GameServer ( ) - > SendRecord ( i ) ;
2011-06-06 19:24:27 +00:00
}
}
2011-12-25 13:51:04 +00:00
}
2011-06-06 19:24:27 +00:00
2020-05-22 15:58:41 +00:00
if ( Player - > GetClientVersion ( ) > = VERSION_DDRACE )
2011-12-25 13:51:04 +00:00
{
CNetMsg_Sv_DDRaceTime Msg ;
2017-03-21 10:24:44 +00:00
Msg . m_Time = ( int ) ( Time * 100.0f ) ;
2011-12-25 13:51:04 +00:00
Msg . m_Check = 0 ;
Msg . m_Finish = 1 ;
2011-06-06 19:24:27 +00:00
2011-12-25 13:51:04 +00:00
if ( pData - > m_BestTime )
{
2017-03-21 10:24:44 +00:00
float Diff = ( Time - pData - > m_BestTime ) * 100 ;
Msg . m_Check = ( int ) Diff ;
2011-06-06 19:24:27 +00:00
}
2011-12-25 13:51:04 +00:00
Server ( ) - > SendPackMsg ( & Msg , MSGFLAG_VITAL , Player - > GetCID ( ) ) ;
}
2017-03-21 10:24:44 +00:00
int TTime = 0 - ( int ) Time ;
2017-07-05 21:01:57 +00:00
if ( Player - > m_Score < TTime | | ! Player - > m_HasFinishScore )
2017-07-23 19:33:55 +00:00
{
2011-12-25 13:51:04 +00:00
Player - > m_Score = TTime ;
2017-07-23 19:33:55 +00:00
Player - > m_HasFinishScore = true ;
}
2011-06-06 19:24:27 +00:00
}
2013-02-01 11:08:23 +00:00
void CGameTeams : : OnCharacterSpawn ( int ClientID )
{
m_Core . SetSolo ( ClientID , false ) ;
2013-11-15 23:44:49 +00:00
2014-02-03 14:46:30 +00:00
if ( m_Core . Team ( ClientID ) > = TEAM_SUPER | | ! m_TeamLocked [ m_Core . Team ( ClientID ) ] )
2020-05-30 22:34:29 +00:00
// Important to only set a new team here, don't remove from an existing
// team since a newly joined player does by definition not have an old team
// to remove from. Doing so would destroy the count in m_MembersCount.
SetForceCharacterNewTeam ( ClientID , 0 ) ;
2013-02-01 11:08:23 +00:00
}
2014-04-12 10:08:20 +00:00
void CGameTeams : : OnCharacterDeath ( int ClientID , int Weapon )
2013-02-01 11:08:23 +00:00
{
m_Core . SetSolo ( ClientID , false ) ;
2013-11-15 23:44:49 +00:00
2014-04-12 10:08:20 +00:00
int Team = m_Core . Team ( ClientID ) ;
bool Locked = TeamLocked ( Team ) & & Weapon ! = WEAPON_GAME ;
2018-03-06 13:08:04 +00:00
if ( ! Locked )
2014-09-26 01:42:49 +00:00
{
2013-11-15 23:44:49 +00:00
SetForceCharacterTeam ( ClientID , 0 ) ;
2014-09-26 01:42:49 +00:00
CheckTeamFinished ( Team ) ;
}
2014-02-08 13:33:42 +00:00
else
{
SetForceCharacterTeam ( ClientID , Team ) ;
2018-03-06 13:08:04 +00:00
if ( GetTeamState ( Team ) ! = TEAMSTATE_OPEN )
2015-11-12 17:59:58 +00:00
{
ChangeTeamState ( Team , CGameTeams : : TEAMSTATE_OPEN ) ;
char aBuf [ 512 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " Everyone in your locked team was killed because '%s' %s. " , Server ( ) - > ClientName ( ClientID ) , Weapon = = WEAPON_SELF ? " killed " : " died " ) ;
2020-05-27 21:36:58 +00:00
m_Practice [ Team ] = false ;
2018-03-06 13:08:04 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
2017-05-20 23:20:04 +00:00
if ( m_Core . Team ( i ) = = Team & & GameServer ( ) - > m_apPlayers [ i ] )
2015-11-12 17:59:58 +00:00
{
2020-05-27 21:36:58 +00:00
GameServer ( ) - > m_apPlayers [ i ] - > m_VotedForPractice = false ;
2017-05-20 23:20:04 +00:00
if ( i ! = ClientID )
{
GameServer ( ) - > m_apPlayers [ i ] - > KillCharacter ( WEAPON_SELF ) ;
if ( Weapon = = WEAPON_SELF )
GameServer ( ) - > m_apPlayers [ i ] - > Respawn ( true ) ; // spawn the rest of team with weak hook on the killer
}
2018-03-06 13:08:04 +00:00
if ( m_MembersCount [ Team ] > 1 )
GameServer ( ) - > SendChatTarget ( i , aBuf ) ;
2015-11-12 17:59:58 +00:00
}
}
2014-02-08 13:33:42 +00:00
}
2013-11-15 23:44:49 +00:00
}
void CGameTeams : : SetTeamLock ( int Team , bool Lock )
{
2016-03-07 17:04:59 +00:00
if ( Team > TEAM_FLOCK & & Team < TEAM_SUPER )
m_TeamLocked [ Team ] = Lock ;
2017-04-23 20:50:07 +00:00
}
void CGameTeams : : ResetInvited ( int Team )
{
m_Invited [ Team ] = 0 ;
}
void CGameTeams : : SetClientInvited ( int Team , int ClientID , bool Invited )
{
if ( Team > TEAM_FLOCK & & Team < TEAM_SUPER )
{
if ( Invited )
m_Invited [ Team ] | = 1ULL < < ClientID ;
else
m_Invited [ Team ] & = ~ ( 1ULL < < ClientID ) ;
}
2013-02-01 11:08:23 +00:00
}
2014-07-26 12:46:31 +00:00
2014-10-21 12:27:10 +00:00
void CGameTeams : : KillSavedTeam ( int Team )
2014-07-26 12:46:31 +00:00
{
2014-10-21 12:27:10 +00:00
// Set so that no finish is accidentally given to some of the players
ChangeTeamState ( Team , CGameTeams : : TEAMSTATE_OPEN ) ;
2014-10-21 12:57:58 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
2015-08-22 13:16:14 +00:00
{
2014-10-21 12:57:58 +00:00
if ( m_Core . Team ( i ) = = Team & & GameServer ( ) - > m_apPlayers [ i ] )
2015-08-22 13:16:14 +00:00
{
// Set so that no finish is accidentally given to some of the players
GameServer ( ) - > m_apPlayers [ i ] - > GetCharacter ( ) - > m_DDRaceState = DDRACE_NONE ;
2014-10-21 12:57:58 +00:00
m_TeeFinished [ i ] = false ;
2015-08-22 13:16:14 +00:00
}
}
2014-10-21 12:57:58 +00:00
2014-07-26 12:46:31 +00:00
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
if ( m_Core . Team ( i ) = = Team & & GameServer ( ) - > m_apPlayers [ i ] )
2014-12-07 02:42:43 +00:00
GameServer ( ) - > m_apPlayers [ i ] - > ThreadKillCharacter ( - 2 ) ;
2014-07-26 12:46:31 +00:00
2014-08-31 12:12:15 +00:00
ChangeTeamState ( Team , CGameTeams : : TEAMSTATE_EMPTY ) ;
2014-09-06 19:08:21 +00:00
// unlock team when last player leaves
2014-09-06 23:03:55 +00:00
SetTeamLock ( Team , false ) ;
2017-04-24 09:54:28 +00:00
ResetInvited ( Team ) ;
2020-05-27 15:58:08 +00:00
m_Practice [ Team ] = false ;
2014-07-26 12:46:31 +00:00
}