about summary refs log tree commit diff
path: root/src/game/server/gamemodes
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/server/gamemodes')
-rw-r--r--src/game/server/gamemodes/zcatch.cpp252
-rw-r--r--src/game/server/gamemodes/zcatch.h30
2 files changed, 282 insertions, 0 deletions
diff --git a/src/game/server/gamemodes/zcatch.cpp b/src/game/server/gamemodes/zcatch.cpp
new file mode 100644
index 00000000..9bf12374
--- /dev/null
+++ b/src/game/server/gamemodes/zcatch.cpp
@@ -0,0 +1,252 @@
+/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
+/* If you are missing that file, acquire a complete release at teeworlds.com.                */
+/* zCatch by erd and Teetime                                                                 */
+
+#include <engine/shared/config.h>
+#include <game/server/gamecontext.h>
+#include <game/server/gamecontroller.h>
+#include <game/server/entities/character.h>
+#include <game/server/player.h>
+#include "zcatch.h"
+
+CGameController_zCatch::CGameController_zCatch(class CGameContext *pGameServer) :
+		IGameController(pGameServer)
+{
+	m_pGameType = "zCatch";
+	m_OldMode = g_Config.m_SvMode;
+}
+
+void CGameController_zCatch::Tick()
+{
+	IGameController::Tick();
+	if(m_GameOverTick == -1)
+		CalcPlayerColor();
+
+	if(m_OldMode != g_Config.m_SvMode)
+	{
+		Server()->MapReload();
+		m_OldMode = g_Config.m_SvMode;
+	}
+}
+
+void CGameController_zCatch::DoWincheck()
+{
+	if(m_GameOverTick == -1)
+	{
+		int Players = 0, Players_Spec = 0, Players_SpecExplicit = 0;
+
+		for(int i = 0; i < MAX_CLIENTS; i++)
+		{
+			if(GameServer()->m_apPlayers[i])
+			{
+				Players++;
+				if(GameServer()->m_apPlayers[i]->GetTeam() == TEAM_SPECTATORS)
+					Players_Spec++;
+				if(GameServer()->m_apPlayers[i]->m_SpecExplicit == 1)
+					Players_SpecExplicit++;
+			}
+		}
+
+		if(Players == 1)
+		{
+			//Do nothing
+		}
+		else if((Players - Players_Spec == 1) && (Players != Players_Spec) && (Players - Players_SpecExplicit != 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;
+			}
+			EndRound();
+		}
+
+		IGameController::DoWincheck(); //do also usual wincheck
+	}
+}
+
+int CGameController_zCatch::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int WeaponID)
+{
+	if(!pKiller)
+		return 0;
+
+	int VictimID = pVictim->GetPlayer()->GetCID();
+
+	if(pKiller != pVictim->GetPlayer())
+	{
+		pKiller->m_Kills++;
+		pVictim->GetPlayer()->m_Deaths++;
+
+		pKiller->m_Score++;
+
+		/* 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
+
+			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);
+		}
+	}
+	else
+	{
+		//Punish 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++;
+			}
+		}
+	}
+
+	// Update colors
+	OnPlayerInfoChange(pVictim->GetPlayer());
+
+	return 0;
+}
+
+void CGameController_zCatch::OnPlayerInfoChange(class CPlayer *pP)
+{
+	if(g_Config.m_SvColorIndicator)
+	{
+		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;
+		pP->m_TeeInfos.m_ColorBody = Num * 0x010000 + 0xff00;
+		pP->m_TeeInfos.m_ColorFeet = Num * 0x010000 + 0xff00;
+		pP->m_TeeInfos.m_UseCustomColor = 1;
+	}
+}
+
+void CGameController_zCatch::StartRound()
+{
+	IGameController::StartRound();
+
+	for(int i = 0; i < MAX_CLIENTS; i++)
+	{
+		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;
+			GameServer()->m_apPlayers[i]->m_TicksIngame = 0;
+		}
+	}
+}
+
+void CGameController_zCatch::OnCharacterSpawn(class CCharacter *pChr)
+{
+	// default health and armor
+	pChr->IncreaseHealth(10);
+	if(g_Config.m_SvMode == 2)
+		pChr->IncreaseArmor(10);
+
+	// give default weapons
+	switch(g_Config.m_SvMode)
+	{
+	case 1: /* Instagib - Only Riffle */
+		pChr->GiveWeapon(WEAPON_RIFLE, -1);
+		break;
+	case 2: /* All Weapons */
+		pChr->GiveWeapon(WEAPON_HAMMER, -1);
+		pChr->GiveWeapon(WEAPON_GUN, g_Config.m_SvWeaponsAmmo);
+		pChr->GiveWeapon(WEAPON_GRENADE, g_Config.m_SvWeaponsAmmo);
+		pChr->GiveWeapon(WEAPON_SHOTGUN, g_Config.m_SvWeaponsAmmo);
+		pChr->GiveWeapon(WEAPON_RIFLE, g_Config.m_SvWeaponsAmmo);
+		break;
+	case 3: /* Hammer */
+		pChr->GiveWeapon(WEAPON_HAMMER, -1);
+		break;
+	case 4: /* Grenade */
+		pChr->GiveWeapon(WEAPON_GRENADE, g_Config.m_SvGrenadeEndlessAmmo ? -1 : g_Config.m_SvWeaponsAmmo);
+		break;
+	case 5: /* Ninja */
+		pChr->GiveNinja();
+		break;
+	}
+
+	//Update color of spawning tees
+	OnPlayerInfoChange(pChr->GetPlayer());
+}
+
+void CGameController_zCatch::EndRound()
+{
+	for(int i = 0; i < MAX_CLIENTS; i++)
+	{
+		if(GameServer()->m_apPlayers[i])
+		{
+
+			if(GameServer()->m_apPlayers[i]->m_SpecExplicit == 0)
+			{
+				GameServer()->m_apPlayers[i]->SetTeamDirect(GameServer()->m_pController->ClampTeam(1));
+
+				char aBuf[128];
+				str_format(aBuf, sizeof(aBuf), "Kills: %d | Deaths: %d", GameServer()->m_apPlayers[i]->m_Kills, GameServer()->m_apPlayers[i]->m_Deaths);
+				GameServer()->SendChatTarget(i, aBuf);
+
+				if(GameServer()->m_apPlayers[i]->m_TicksSpec != 0 || GameServer()->m_apPlayers[i]->m_TicksIngame != 0)
+				{
+					double TimeInSpec = (GameServer()->m_apPlayers[i]->m_TicksSpec * 100.0) / (GameServer()->m_apPlayers[i]->m_TicksIngame + GameServer()->m_apPlayers[i]->m_TicksSpec);
+					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
+			}
+		}
+	}
+
+	if(m_Warmup) // game can't end when we are running warmup
+		return;
+
+	GameServer()->m_World.m_Paused = true;
+	m_GameOverTick = Server()->Tick();
+	m_SuddenDeath = 0;
+}
+
+bool CGameController_zCatch::CanChangeTeam(CPlayer *pPlayer, int JoinTeam)
+{
+	if(pPlayer->m_CaughtBy >= 0)
+		return false;
+	return true;
+}
+
+bool CGameController_zCatch::OnEntity(int Index, vec2 Pos)
+{
+	if(Index == ENTITY_SPAWN)
+		m_aaSpawnPoints[0][m_aNumSpawnPoints[0]++] = Pos;
+	else if(Index == ENTITY_SPAWN_RED)
+		m_aaSpawnPoints[1][m_aNumSpawnPoints[1]++] = Pos;
+	else if(Index == ENTITY_SPAWN_BLUE)
+		m_aaSpawnPoints[2][m_aNumSpawnPoints[2]++] = 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
new file mode 100644
index 00000000..af776644
--- /dev/null
+++ b/src/game/server/gamemodes/zcatch.h
@@ -0,0 +1,30 @@
+/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
+/* If you are missing that file, acquire a complete release at teeworlds.com.                */
+/* zCatch by erd and Teetime                                                                 */
+
+#ifndef GAME_SERVER_GAMEMODES_ZCATCH_H
+#define GAME_SERVER_GAMEMODES_ZCATCH_H
+
+#include <game/server/gamecontroller.h>
+
+class CGameController_zCatch: public IGameController
+{
+	int m_OldMode;
+
+public:
+	CGameController_zCatch(class CGameContext *pGameServer);
+	virtual void Tick();
+	virtual void DoWincheck();
+
+	virtual void StartRound();
+	virtual void OnCharacterSpawn(class CCharacter *pChr);
+	virtual void OnPlayerInfoChange(class CPlayer *pP);
+	virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int WeaponID);
+	virtual bool OnEntity(int Index, vec2 Pos);
+	virtual bool CanChangeTeam(CPlayer *pPlayer, int JoinTeam);
+	virtual void EndRound();
+
+	void CalcPlayerColor();
+};
+
+#endif