about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/client/components/menus.h2
-rw-r--r--src/game/client/components/menus_ingame.cpp30
-rw-r--r--src/game/client/components/voting.cpp16
-rw-r--r--src/game/client/components/voting.h1
-rw-r--r--src/game/server/gamecontext.cpp36
-rw-r--r--src/game/variables.h1
6 files changed, 81 insertions, 5 deletions
diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h
index 3cdfe3f0..a9921655 100644
--- a/src/game/client/components/menus.h
+++ b/src/game/client/components/menus.h
@@ -217,7 +217,7 @@ class CMenus : public CComponent
 	void RenderGame(CUIRect MainView);
 	void RenderServerInfo(CUIRect MainView);
 	void RenderServerControl(CUIRect MainView);
-	void RenderServerControlKick(CUIRect MainView);
+	void RenderServerControlKick(CUIRect MainView, bool FilterSpectators);
 	void RenderServerControlServer(CUIRect MainView);
 	
 	// found in menus_browser.cpp
diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp
index 06da001a..4b593989 100644
--- a/src/game/client/components/menus_ingame.cpp
+++ b/src/game/client/components/menus_ingame.cpp
@@ -345,7 +345,7 @@ void CMenus::RenderServerControlServer(CUIRect MainView)
 	m_CallvoteSelectedOption = UiDoListboxEnd(&s_ScrollValue, 0);
 }
 
-void CMenus::RenderServerControlKick(CUIRect MainView)
+void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators)
 {
 	int NumOptions = 0;
 	int Selected = -1;
@@ -354,6 +354,8 @@ void CMenus::RenderServerControlKick(CUIRect MainView)
 	{
 		if(!m_pClient->m_Snap.m_paPlayerInfos[i] || i == m_pClient->m_Snap.m_LocalClientID)
 			continue;
+		if(FilterSpectators && m_pClient->m_Snap.m_paPlayerInfos[i]->m_Team == TEAM_SPECTATORS)
+			continue;
 		if(m_CallvoteSelectedPlayer == i)
 			Selected = NumOptions;
 		aPlayerIDs[NumOptions++] = i;
@@ -400,7 +402,8 @@ void CMenus::RenderServerControl(CUIRect MainView)
 	
 	const char *paTabs[] = {
 		Localize("Settings"),
-		Localize("Kick")};
+		Localize("Kick"),
+		Localize("Spectate")};
 	int aNumTabs = (int)(sizeof(paTabs)/sizeof(*paTabs));
 	
 	for(int i = 0; i < aNumTabs; i++)
@@ -424,8 +427,9 @@ void CMenus::RenderServerControl(CUIRect MainView)
 	if(s_ControlPage == 0)
 		RenderServerControlServer(MainView);
 	else if(s_ControlPage == 1)
-		RenderServerControlKick(MainView);
-		
+		RenderServerControlKick(MainView, false);
+	else if(s_ControlPage == 2)
+		RenderServerControlKick(MainView, true);		
 
 	{
 		CUIRect Button;
@@ -445,6 +449,15 @@ void CMenus::RenderServerControl(CUIRect MainView)
 					SetActive(false);
 				}
 			}
+			else if(s_ControlPage == 2)
+			{
+				if(m_CallvoteSelectedPlayer >= 0 && m_CallvoteSelectedPlayer < MAX_CLIENTS &&
+					m_pClient->m_Snap.m_paPlayerInfos[m_CallvoteSelectedPlayer])
+				{
+					m_pClient->m_pVoting->CallvoteSpectate(m_CallvoteSelectedPlayer, m_aCallvoteReason);
+					SetActive(false);
+				}
+			}
 			m_aCallvoteReason[0] = 0;
 		}
 		
@@ -479,6 +492,15 @@ void CMenus::RenderServerControl(CUIRect MainView)
 						SetActive(false);
 					}
 				}
+				else if(s_ControlPage == 2)
+				{
+					if(m_CallvoteSelectedPlayer >= 0 && m_CallvoteSelectedPlayer < MAX_CLIENTS &&
+						m_pClient->m_Snap.m_paPlayerInfos[m_CallvoteSelectedPlayer])
+					{
+						m_pClient->m_pVoting->CallvoteSpectate(m_CallvoteSelectedPlayer, m_aCallvoteReason, true);
+						SetActive(false);
+					}
+				}
 				m_aCallvoteReason[0] = 0;
 			}
 		}
diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp
index 6e00a5d5..d8c87855 100644
--- a/src/game/client/components/voting.cpp
+++ b/src/game/client/components/voting.cpp
@@ -31,6 +31,22 @@ void CVoting::Callvote(const char *pType, const char *pValue, const char *pReaso
 	Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
 }
 
+void CVoting::CallvoteSpectate(int ClientID, const char *pReason, bool ForceVote)
+{
+	if(ForceVote)
+	{
+		char aBuf[128];
+		str_format(aBuf, sizeof(aBuf), "set_team %d -1", ClientID);
+		Client()->Rcon(aBuf);
+	}
+	else
+	{
+		char aBuf[32];
+		str_format(aBuf, sizeof(aBuf), "%d", ClientID);
+		Callvote("spectate", aBuf, pReason);
+	}
+}
+
 void CVoting::CallvoteKick(int ClientID, const char *pReason, bool ForceVote)
 {
 	if(ForceVote)
diff --git a/src/game/client/components/voting.h b/src/game/client/components/voting.h
index 92e4b395..9e7da2dc 100644
--- a/src/game/client/components/voting.h
+++ b/src/game/client/components/voting.h
@@ -45,6 +45,7 @@ public:
 	
 	void RenderBars(CUIRect Bars, bool Text);
 	
+	void CallvoteSpectate(int ClientID, const char *pReason, bool ForceVote = false);
 	void CallvoteKick(int ClientID, const char *pReason, bool ForceVote = false);
 	void CallvoteOption(int Option, const char *pReason, bool ForceVote = false);
 	
diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp
index 8b492ec0..8245d508 100644
--- a/src/game/server/gamecontext.cpp
+++ b/src/game/server/gamecontext.cpp
@@ -711,6 +711,30 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
 				str_format(aCmd, sizeof(aCmd), "ban %s %d Banned by vote", aBuf, g_Config.m_SvVoteKickBantime);
 			}
 		}
+		else if(str_comp_nocase(pMsg->m_Type, "spectate") == 0)
+		{
+			if(!g_Config.m_SvVoteSpectate)
+			{
+				SendChatTarget(ClientID, "Server does not allow voting to move players to spectators");
+				return;
+			}
+			
+			int SpectateID = str_toint(pMsg->m_Value);
+			if(SpectateID < 0 || SpectateID >= MAX_CLIENTS || !m_apPlayers[SpectateID] || m_apPlayers[SpectateID]->GetTeam() == TEAM_SPECTATORS)
+			{
+				SendChatTarget(ClientID, "Invalid client id to move");
+				return;
+			}
+			if(SpectateID == ClientID)
+			{
+				SendChatTarget(ClientID, "You cant move yourself");
+				return;
+			}
+			
+			str_format(aChatmsg, sizeof(aChatmsg), "'%s' called for vote to move '%s' to spectators (%s)", Server()->ClientName(ClientID), Server()->ClientName(SpectateID), pReason);
+			str_format(aDesc, sizeof(aDesc), "move '%s' to spectators", Server()->ClientName(SpectateID));
+			str_format(aCmd, sizeof(aCmd), "set_team %d -1", SpectateID);
+		}
 		
 		if(aCmd[0])
 		{
@@ -1133,6 +1157,18 @@ void CGameContext::ConForceVote(IConsole::IResult *pResult, void *pUserData)
 			pSelf->Console()->ExecuteLine(aBuf);
 		}
 	}
+	else if(str_comp_nocase(pType, "spectate") == 0)
+	{
+		int SpectateID = str_toint(pValue);
+		if(SpectateID < 0 || SpectateID >= MAX_CLIENTS || !pSelf->m_apPlayers[SpectateID] || pSelf->m_apPlayers[SpectateID]->GetTeam() == TEAM_SPECTATORS)
+		{
+			pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "Invalid client id to move");
+			return;
+		}
+		
+		str_format(aBuf, sizeof(aBuf), "set_team %d -1", SpectateID);
+		pSelf->Console()->ExecuteLine(aBuf);
+	}
 }
 
 void CGameContext::ConClearVotes(IConsole::IResult *pResult, void *pUserData)
diff --git a/src/game/variables.h b/src/game/variables.h
index a0ac64c4..ce8e6ccb 100644
--- a/src/game/variables.h
+++ b/src/game/variables.h
@@ -69,6 +69,7 @@ MACRO_CONFIG_INT(SvTeambalanceTime, sv_teambalance_time, 1, 0, 1000, CFGFLAG_SER
 MACRO_CONFIG_INT(SvInactiveKickTime, sv_inactivekick_time, 3, 0, 1000, CFGFLAG_SERVER, "How many minutes to wait before taking care of inactive players")
 MACRO_CONFIG_INT(SvInactiveKick, sv_inactivekick, 1, 0, 2, CFGFLAG_SERVER, "How to deal with inactive players (0=move to spectator, 1=move to free spectator slot/kick, 2=kick)")
 
+MACRO_CONFIG_INT(SvVoteSpectate, sv_vote_spectate, 1, 0, 1, CFGFLAG_SERVER, "Allow voting to move players to spectators")
 MACRO_CONFIG_INT(SvVoteKick, sv_vote_kick, 1, 0, 1, CFGFLAG_SERVER, "Allow voting to kick players")
 MACRO_CONFIG_INT(SvVoteKickMin, sv_vote_kick_min, 0, 0, MAX_CLIENTS, CFGFLAG_SERVER, "Minimum number of players required to start a kick vote")
 MACRO_CONFIG_INT(SvVoteKickBantime, sv_vote_kick_bantime, 5, 0, 1440, CFGFLAG_SERVER, "The time to ban a player if kicked by vote. 0 makes it just use kick")