about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarius "Teelevision" Neugebauer <marius@teele.eu>2014-03-30 04:05:57 +0200
committerMarius "Teelevision" Neugebauer <marius@teele.eu>2014-03-30 04:05:57 +0200
commite799504cb2655bb3aa3a25c2a69ddc80558f9e99 (patch)
treee9d3d8f63f4b50de198b5444f1d5111bc4391554
parent19a471a30c922ea3beffc7489fa05fe16d614f5b (diff)
downloadzcatch-e799504cb2655bb3aa3a25c2a69ddc80558f9e99.tar.gz
zcatch-e799504cb2655bb3aa3a25c2a69ddc80558f9e99.zip
reworked the catching, counting and color system
-rw-r--r--src/game/server/gamecontext.cpp91
-rw-r--r--src/game/server/gamemodes/zcatch.cpp95
-rw-r--r--src/game/server/gamemodes/zcatch.h2
-rw-r--r--src/game/server/player.cpp68
-rw-r--r--src/game/server/player.h22
5 files changed, 155 insertions, 123 deletions
diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp
index ba08cebb..6f983855 100644
--- a/src/game/server/gamecontext.cpp
+++ b/src/game/server/gamecontext.cpp
@@ -459,7 +459,7 @@ void CGameContext::OnTick()
 					/* zCatch - Allow voting from players in spectators (needed or the last 2 players ingame can kick the whole server),
 					 * but deny votes from players who are explicit in spec
 					*/
-					if(!m_apPlayers[i] || m_apPlayers[i]->m_SpecExplicit == 1 || aVoteChecked[i])	// don't count in votes by spectators
+					if(!m_apPlayers[i] || m_apPlayers[i]->m_SpecExplicit || aVoteChecked[i])	// don't count in votes by spectators
 						continue;
 
 					int ActVote = m_apPlayers[i]->m_Vote;
@@ -545,88 +545,56 @@ void CGameContext::OnClientPredictedInput(int ClientID, void *pInput)
 
 void CGameContext::OnClientEnter(int ClientID)
 {
+	CPlayer *p = m_apPlayers[ClientID];
 	//world.insert_entity(&players[client_id]);
-	m_apPlayers[ClientID]->Respawn();
+	p->Respawn();
 	
 	/* begin zCatch */
-	int LeaderID = -1;
-	int StartTeam = m_pController->ClampTeam(1);
+	CPlayer *leader = NULL;
 	
-	int Num = 0;
-
+	int NumReady = 0;
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
 		if(IsClientReady(i))
-			Num++;
+			NumReady++;
 	}
-	if(Num < 3)
-		m_pController->EndRound();
 
+	// sv_allow_join 1: Allow new players to join the game without need to wait for the next round
 	if(g_Config.m_SvAllowJoin == 1)
 	{
-		m_apPlayers[ClientID]->m_CaughtBy = CPlayer::ZCATCH_NOT_CAUGHT;
-		m_apPlayers[ClientID]->m_SpecExplicit = (Num < 3) ? 0 : 1;
-		StartTeam = (Num < 3) ? m_pController->ClampTeam(1) : TEAM_SPECTATORS;
+		p->m_SpecExplicit = (NumReady > 2);
+		p->SetTeamDirect(p->m_SpecExplicit ? TEAM_SPECTATORS : m_pController->ClampTeam(1));
 		SendBroadcast("You can join the game", ClientID);
 	}
+	// sv_allow_join 2: The player will join when the player with the most kills dies
 	else if(g_Config.m_SvAllowJoin == 2)
 	{
-		int Num2 = 0, PrevNum = 0;
-
 		for(int i = 0; i < MAX_CLIENTS; i++)
-		{
-			if(m_apPlayers[i])
-			{
-				Num2 = 0;
-				for(int j = 0; j < MAX_CLIENTS; j++)
-					if(m_apPlayers[j] && m_apPlayers[j]->m_CaughtBy == i)
-						Num2++;
-
-				if(Num2 > PrevNum)
-				{
-					LeaderID = i;
-					PrevNum = Num2;
-				}
-			}
-		}
-
-		if(LeaderID > -1)
-		{
-			m_apPlayers[ClientID]->m_CaughtBy = LeaderID;
-			m_apPlayers[ClientID]->m_SpecExplicit = 0;
-			m_apPlayers[ClientID]->m_SpectatorID = LeaderID;
-			StartTeam = TEAM_SPECTATORS;
-		}
+			if(m_apPlayers[i] && ((leader && m_apPlayers[i]->m_zCatchNumKillsInARow > leader->m_zCatchNumKillsInARow) || (!leader && m_apPlayers[i]->m_zCatchNumKillsInARow)))
+				leader = m_apPlayers[i];
+		if(leader)
+			leader->AddZCatchVictim(ClientID);
 		else
-		{
-			m_apPlayers[ClientID]->m_CaughtBy = CPlayer::ZCATCH_NOT_CAUGHT;
-			m_apPlayers[ClientID]->m_SpecExplicit = 0;
-		}
+			p->m_SpecExplicit = false;
 	}
-	else
-		StartTeam = m_pController->GetAutoTeam(ClientID);
-	
-	m_apPlayers[ClientID]->SetTeamDirect(StartTeam);
 	
 	/* end zCatch */
 	
 	char aBuf[512];
-	str_format(aBuf, sizeof(aBuf), "'%s' entered and joined the %s", Server()->ClientName(ClientID), m_pController->GetTeamName(m_apPlayers[ClientID]->GetTeam()));
+	str_format(aBuf, sizeof(aBuf), "'%s' entered and joined the %s", Server()->ClientName(ClientID), m_pController->GetTeamName(p->GetTeam()));
 	SendChat(-1, CGameContext::CHAT_ALL, aBuf);
 
-	str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' team=%d", ClientID, Server()->ClientName(ClientID), m_apPlayers[ClientID]->GetTeam());
+	str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' team=%d", ClientID, Server()->ClientName(ClientID), p->GetTeam());
 	Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
 
 	m_VoteUpdate = true;
 	
 	/* zCatch begin */
-	SendChatTarget(ClientID, "Welcome to zCatch!");
-	SendChatTarget(ClientID, "type /cmdlist to get all commands");
-	SendChatTarget(ClientID, "type /help for instructions");
-	if(g_Config.m_SvAllowJoin == 2 && LeaderID > -1)
+	SendChatTarget(ClientID, "Welcome to zCatch! Type /info for more.");
+	if(g_Config.m_SvAllowJoin == 2 && leader)
 	{
 		char buf[128];
-		str_format(buf, sizeof(buf), "You will join the game when %s dies", Server()->ClientName(LeaderID));
+		str_format(buf, sizeof(buf), "You will join the game when '%s' dies", Server()->ClientName(leader->GetCID()));
 		SendChatTarget(ClientID, buf);
 	}
 	/* zCatch end */
@@ -663,6 +631,9 @@ void CGameContext::OnClientConnected(int ClientID)
 
 void CGameContext::OnClientDrop(int ClientID, const char *pReason)
 {
+	if(m_apPlayers[ClientID]->m_CaughtBy > CPlayer::ZCATCH_NOT_CAUGHT)
+		m_apPlayers[m_apPlayers[ClientID]->m_CaughtBy]->ReleaseZCatchVictim(ClientID);
+	
 	AbortVoteKickOnDisconnect(ClientID);
 	m_apPlayers[ClientID]->OnDisconnect(pReason);
 	delete m_apPlayers[ClientID];
@@ -763,7 +734,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
 		int64 Now = Server()->Tick();
 		pPlayer->m_LastVoteTry = Now;
 		// zCatch - Only People who are explicit in Spectators can't vote!
-		if(pPlayer->m_SpecExplicit == 1) //zCatch
+		if(pPlayer->m_SpecExplicit) //zCatch
 		{
 			SendChatTarget(ClientID, "Spectators aren't allowed to start a vote.");
 			return;
@@ -840,7 +811,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
 			{
 				int PlayerNum = 0;
 				for(int i = 0; i < MAX_CLIENTS; ++i)
-					if(m_apPlayers[i] && m_apPlayers[i]->m_SpecExplicit != 1) // zCatch - Count all Players who are not explicit in spectator
+					if(m_apPlayers[i] && !m_apPlayers[i]->m_SpecExplicit) // zCatch - Count all Players who are not explicit in spectator
 						++PlayerNum;
 
 				if(PlayerNum < g_Config.m_SvVoteKickMin)
@@ -1149,11 +1120,21 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
 		{
 			SendChatTarget(ClientID, "You can't kill yourself while you're frozen.");
 		}
+		else if(pPlayer->HasZCatchVictims())
+		{
+			int lastVictim = pPlayer->LastZCatchVictim();
+			pPlayer->ReleaseZCatchVictim(CPlayer::ZCATCH_RELEASE_ALL, 1);
+			char aBuf[128];
+			str_format(aBuf, sizeof(aBuf), "You released '%s'. (%d left)", Server()->ClientName(lastVictim), pPlayer->m_zCatchNumVictims);
+			SendChatTarget(ClientID, aBuf);
+			str_format(aBuf, sizeof(aBuf), "You were released by '%s'.", Server()->ClientName(ClientID));
+			SendChatTarget(lastVictim, aBuf);
+			return;
+		}
 		else
 		{
 			pPlayer->m_LastKill = Server()->Tick();
 			pPlayer->KillCharacter(WEAPON_SELF);
-			pPlayer->m_Deaths++;
 			return;
 		}
 		pPlayer->m_LastKillTry = Server()->Tick();
diff --git a/src/game/server/gamemodes/zcatch.cpp b/src/game/server/gamemodes/zcatch.cpp
index bb6f9ec3..dadfd19b 100644
--- a/src/game/server/gamemodes/zcatch.cpp
+++ b/src/game/server/gamemodes/zcatch.cpp
@@ -20,8 +20,6 @@ CGameController_zCatch::CGameController_zCatch(class CGameContext *pGameServer)
 void CGameController_zCatch::Tick()
 {
 	IGameController::Tick();
-	if(m_GameOverTick == -1)
-		CalcPlayerColor();
 
 	if(m_OldMode != g_Config.m_SvMode)
 	{
@@ -43,23 +41,31 @@ void CGameController_zCatch::DoWincheck()
 				Players++;
 				if(GameServer()->m_apPlayers[i]->GetTeam() == TEAM_SPECTATORS)
 					Players_Spec++;
-				if(GameServer()->m_apPlayers[i]->m_SpecExplicit == 1)
+				if(GameServer()->m_apPlayers[i]->m_SpecExplicit)
 					Players_SpecExplicit++;
 			}
 		}
+		int Players_Ingame = Players - Players_SpecExplicit;
 
-		if(Players == 1)
+		if(Players_Ingame <= 1)
 		{
 			//Do nothing
 		}
-		else if((Players - Players_Spec == 1) && (Players != Players_Spec) && (Players - Players_SpecExplicit != 1))
+		else if((Players - Players_Spec) == 1)
 		{
 			for(int i = 0; i < MAX_CLIENTS; i++)
 			{
 				if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
+				{
 					GameServer()->m_apPlayers[i]->m_Score += g_Config.m_SvBonus;
+					if(Players_Ingame <= 4)
+						GameServer()->m_apPlayers[i]->ReleaseZCatchVictim(CPlayer::ZCATCH_RELEASE_ALL);
+				}
 			}
-			EndRound();
+			if(Players_Ingame <= 4)
+				GameServer()->SendChatTarget(-1, "Too less players to end round. All players have been released.");
+			else
+				EndRound();
 		}
 
 		IGameController::DoWincheck(); //do also usual wincheck
@@ -71,66 +77,50 @@ int CGameController_zCatch::OnCharacterDeath(class CCharacter *pVictim, class CP
 	if(!pKiller)
 		return 0;
 
-	int VictimID = pVictim->GetPlayer()->GetCID();
-
-	if(pKiller != pVictim->GetPlayer())
+	CPlayer *victim = pVictim->GetPlayer();
+	if(pKiller != victim)
 	{
-		pKiller->m_Kills++;
-		pVictim->GetPlayer()->m_Deaths++;
-
-		pKiller->m_Score++;
-
+		pKiller->m_Score += victim->m_zCatchNumKillsInARow + 1;
+		++pKiller->m_Kills;
+		++victim->m_Deaths;
 		/* Check if the killer is already killed and in spectator (victim may died through wallshot) */
 		if(pKiller->GetTeam() != TEAM_SPECTATORS)
 		{
-			pVictim->GetPlayer()->m_CaughtBy = pKiller->GetCID();
-			pVictim->GetPlayer()->SetTeamDirect(TEAM_SPECTATORS);
-
-			pVictim->GetPlayer()->m_SpectatorID = pKiller->GetCID(); // Let the victim follow his catcher
-
+			++pKiller->m_zCatchNumKillsInARow;
+			pKiller->AddZCatchVictim(victim->GetCID());
 			char aBuf[256];
-			str_format(aBuf, sizeof(aBuf), "Caught by \"%s\". You will join the game automatically when \"%s\" dies.", Server()->ClientName(pKiller->GetCID()), Server()->ClientName(pKiller->GetCID()));
-			GameServer()->SendChatTarget(VictimID, aBuf);
+			str_format(aBuf, sizeof(aBuf), "You are caught until '%s' dies.", Server()->ClientName(pKiller->GetCID()));
+			GameServer()->SendChatTarget(victim->GetCID(), aBuf);
 		}
 	}
 	else
 	{
-		//Punish selfkill/death
+		// selfkill/death
 		if(WeaponID == WEAPON_SELF || WeaponID == WEAPON_WORLD)
-			pVictim->GetPlayer()->m_Score -= g_Config.m_SvKillPenalty;
-	}
-
-	for(int i = 0; i < MAX_CLIENTS; i++)
-	{
-		if(GameServer()->m_apPlayers[i])
 		{
-			if(GameServer()->m_apPlayers[i]->m_CaughtBy == VictimID)
-			{
-				GameServer()->m_apPlayers[i]->m_CaughtBy = CPlayer::ZCATCH_NOT_CAUGHT;
-				GameServer()->m_apPlayers[i]->SetTeamDirect(GameServer()->m_pController->ClampTeam(1));
-
-				if(pKiller != pVictim->GetPlayer())
-					pKiller->m_Score++;
-			}
+			victim->m_Score -= g_Config.m_SvKillPenalty;
+			++victim->m_Deaths;
 		}
 	}
 
+	// release all the victim's victims
+	victim->ReleaseZCatchVictim(CPlayer::ZCATCH_RELEASE_ALL);
+	victim->m_zCatchNumKillsInARow = 0;
+
 	// Update colors
-	OnPlayerInfoChange(pVictim->GetPlayer());
+	OnPlayerInfoChange(victim);
+	OnPlayerInfoChange(pKiller);
 
 	return 0;
 }
 
 void CGameController_zCatch::OnPlayerInfoChange(class CPlayer *pP)
 {
-	if(g_Config.m_SvColorIndicator)
+	if(g_Config.m_SvColorIndicator && pP->m_zCatchNumKillsInARow <= 20)
 	{
-		int Num = 161;
-		for(int i = 0; i < MAX_CLIENTS; i++)
-			if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->m_CaughtBy == pP->GetCID())
-				Num -= 10;
+		int Num = max(0, 160 - pP->m_zCatchNumKillsInARow * 10);
 		pP->m_TeeInfos.m_ColorBody = Num * 0x010000 + 0xff00;
-		pP->m_TeeInfos.m_ColorFeet = Num * 0x010000 + 0xff00;
+		pP->m_TeeInfos.m_ColorFeet = pP->m_zCatchNumKillsInARow == 20 ? 0x40ff00 : pP->m_TeeInfos.m_ColorBody;
 		pP->m_TeeInfos.m_UseCustomColor = 1;
 	}
 }
@@ -143,7 +133,6 @@ void CGameController_zCatch::StartRound()
 	{
 		if(GameServer()->m_apPlayers[i])
 		{
-			GameServer()->m_apPlayers[i]->m_CaughtBy = CPlayer::ZCATCH_NOT_CAUGHT;
 			GameServer()->m_apPlayers[i]->m_Kills = 0;
 			GameServer()->m_apPlayers[i]->m_Deaths = 0;
 			GameServer()->m_apPlayers[i]->m_TicksSpec = 0;
@@ -194,7 +183,7 @@ void CGameController_zCatch::EndRound()
 		if(GameServer()->m_apPlayers[i])
 		{
 
-			if(GameServer()->m_apPlayers[i]->m_SpecExplicit == 0)
+			if(!GameServer()->m_apPlayers[i]->m_SpecExplicit)
 			{
 				GameServer()->m_apPlayers[i]->SetTeamDirect(GameServer()->m_pController->ClampTeam(1));
 
@@ -208,7 +197,9 @@ void CGameController_zCatch::EndRound()
 					str_format(aBuf, sizeof(aBuf), "Spec: %.2f%% | Ingame: %.2f%%", (double) TimeInSpec, (double) (100.0 - TimeInSpec));
 					GameServer()->SendChatTarget(i, aBuf);
 				}
-				GameServer()->m_apPlayers[i]->m_CaughtBy = CPlayer::ZCATCH_NOT_CAUGHT; //Set all players in server as non-caught
+				// release all players
+				GameServer()->m_apPlayers[i]->ReleaseZCatchVictim(CPlayer::ZCATCH_RELEASE_ALL);
+				GameServer()->m_apPlayers[i]->m_zCatchNumKillsInARow = 0;
 			}
 		}
 	}
@@ -239,15 +230,3 @@ bool CGameController_zCatch::OnEntity(int Index, vec2 Pos)
 
 	return false;
 }
-
-void CGameController_zCatch::CalcPlayerColor()
-{
-	for(int i = 0; i < MAX_CLIENTS; i++)
-	{
-		CPlayer *pP = GameServer()->m_apPlayers[i];
-		if(!pP)
-			continue;
-		if(pP->GetTeam() != TEAM_SPECTATORS)
-			OnPlayerInfoChange(pP);
-	}
-}
diff --git a/src/game/server/gamemodes/zcatch.h b/src/game/server/gamemodes/zcatch.h
index af776644..4f110a03 100644
--- a/src/game/server/gamemodes/zcatch.h
+++ b/src/game/server/gamemodes/zcatch.h
@@ -23,8 +23,6 @@ public:
 	virtual bool OnEntity(int Index, vec2 Pos);
 	virtual bool CanChangeTeam(CPlayer *pPlayer, int JoinTeam);
 	virtual void EndRound();
-
-	void CalcPlayerColor();
 };
 
 #endif
diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp
index 7e07c07f..d3e00f9c 100644
--- a/src/game/server/player.cpp
+++ b/src/game/server/player.cpp
@@ -23,18 +23,25 @@ CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, int Team)
 	m_TeamChangeTick = Server()->Tick();
 	
 	//zCatch
-	m_CaughtBy = -1;
-	m_SpecExplicit = 0;
+	m_CaughtBy = ZCATCH_NOT_CAUGHT;
+	m_SpecExplicit = false;
 	m_Kills = 0;
 	m_Deaths = 0;
 	m_LastKillTry = Server()->Tick();
 	m_TicksSpec = 0;
 	m_TicksIngame = 0;
 	m_ChatTicks = 0;
+	
+	// zCatch/TeeVi
+	m_ZCatchVictims = NULL;
+	m_zCatchNumVictims = 0;
+	m_zCatchNumKillsInARow = 0;
 }
 
 CPlayer::~CPlayer()
 {
+	ReleaseZCatchVictim(ZCATCH_RELEASE_ALL);
+	
 	delete m_pCharacter;
 	m_pCharacter = 0;
 }
@@ -295,8 +302,6 @@ void CPlayer::SetTeam(int Team, bool DoChatMsg)
 	str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' m_Team=%d", m_ClientID, Server()->ClientName(m_ClientID), m_Team);
 	GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
 
-	GameServer()->m_pController->OnPlayerInfoChange(GameServer()->m_apPlayers[m_ClientID]);
-
 	if(Team == TEAM_SPECTATORS)
 	{
 		// update spectator modes
@@ -305,10 +310,10 @@ void CPlayer::SetTeam(int Team, bool DoChatMsg)
 			if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->m_SpectatorID == m_ClientID)
 				GameServer()->m_apPlayers[i]->m_SpectatorID = SPEC_FREEVIEW;
 		}
-		m_SpecExplicit = 1;
+		m_SpecExplicit = true;
 	}
 	else
-		m_SpecExplicit = 0;
+		m_SpecExplicit = false;
 }
 
 void CPlayer::SetTeamDirect(int Team)
@@ -377,3 +382,54 @@ int CPlayer::Anticamper()
 	}
 	return 0;
 }
+
+// catch another player
+void CPlayer::AddZCatchVictim(int ClientID)
+{
+	CPlayer *victim = GameServer()->m_apPlayers[ClientID];
+	if(victim)
+	{
+		// add to list of victims
+		CZCatchVictim *v = new CZCatchVictim;
+		v->ClientID = ClientID;
+		v->prev = m_ZCatchVictims;
+		m_ZCatchVictims = v;
+		++m_zCatchNumVictims;
+		// set victim's status
+		victim->m_CaughtBy = m_ClientID;
+		victim->m_SpecExplicit = false;
+		victim->SetTeamDirect(TEAM_SPECTATORS);
+		victim->m_SpectatorID = m_ClientID;
+	}
+}
+
+// release one or more of the victims
+void CPlayer::ReleaseZCatchVictim(int ClientID, int limit)
+{
+	CZCatchVictim **v = &m_ZCatchVictims;
+	CZCatchVictim *tmp;
+	CPlayer *victim;
+	int count = 0;
+	while(*v != NULL)
+	{
+		if(ClientID == ZCATCH_RELEASE_ALL || (*v)->ClientID == ClientID)
+		{
+			victim = GameServer()->m_apPlayers[(*v)->ClientID];
+			if(victim)
+			{
+				victim->m_CaughtBy = ZCATCH_NOT_CAUGHT;
+				victim->SetTeamDirect(GameServer()->m_pController->ClampTeam(1));
+				victim->m_SpectatorID = SPEC_FREEVIEW;
+			}
+			// delete from list
+			tmp = (*v)->prev;
+			delete *v;
+			*v = tmp;
+			--m_zCatchNumVictims;
+			if (limit && ++count >= limit)
+				return;
+		}
+		else
+			v = &(*v)->prev;
+	}
+}
diff --git a/src/game/server/player.h b/src/game/server/player.h
index a19209a8..51deaa5e 100644
--- a/src/game/server/player.h
+++ b/src/game/server/player.h
@@ -98,9 +98,8 @@ public:
 	} m_Latency;
 	
 	//zCatch:
-	enum { ZCATCH_NOT_CAUGHT = -1 };
 	int m_CaughtBy;
-	int m_SpecExplicit;
+	bool m_SpecExplicit;
 	int m_Deaths;
 	int m_Kills;
 	int m_LastKillTry;
@@ -114,6 +113,25 @@ public:
 	int m_CampTick;
 	vec2 m_CampPos;
 	
+	// zCatch/TeeVi
+	enum
+	{
+		ZCATCH_NOT_CAUGHT = -1,
+		ZCATCH_RELEASE_ALL = -1
+	};
+	struct CZCatchVictim
+	{
+		int ClientID;
+		CZCatchVictim *prev;
+	};
+	CZCatchVictim *m_ZCatchVictims;
+	int m_zCatchNumVictims;
+	int m_zCatchNumKillsInARow;
+	void AddZCatchVictim(int ClientID);
+	void ReleaseZCatchVictim(int ClientID, int limit = 0);
+	bool HasZCatchVictims() { return (m_ZCatchVictims != NULL); }
+	int LastZCatchVictim() { return HasZCatchVictims() ? m_ZCatchVictims->ClientID : -1; }
+	
 private:
 	CCharacter *m_pCharacter;
 	CGameContext *m_pGameServer;