diff options
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | bam.lua | 2 | ||||
| -rw-r--r-- | src/game/server/entities/character.cpp | 33 | ||||
| -rw-r--r-- | src/game/server/gamecontext.cpp | 185 | ||||
| -rw-r--r-- | src/game/server/gamecontext.h | 6 | ||||
| -rw-r--r-- | src/game/server/gamecontroller.cpp | 58 | ||||
| -rw-r--r-- | src/game/server/gamecontroller.h | 6 | ||||
| -rw-r--r-- | src/game/server/gamemodes/zcatch.cpp | 167 | ||||
| -rw-r--r-- | src/game/server/gamemodes/zcatch.hpp | 26 | ||||
| -rw-r--r-- | src/game/server/player.cpp | 71 | ||||
| -rw-r--r-- | src/game/server/player.h | 14 | ||||
| -rw-r--r-- | src/game/variables.h | 8 |
12 files changed, 536 insertions, 43 deletions
diff --git a/.gitignore b/.gitignore index 75e610f5..75373487 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ teeworlds* teeworlds_srv* tileset_borderfix* versionsrv* + +zcatch_srv* +config.cfg diff --git a/bam.lua b/bam.lua index 5699251f..381980a3 100644 --- a/bam.lua +++ b/bam.lua @@ -242,7 +242,7 @@ function build(settings) engine, client, game_editor, zlib, pnglite, wavpack, client_link_other, client_osxlaunch) - server_exe = Link(server_settings, "teeworlds_srv", engine, server, + server_exe = Link(server_settings, "zcatch_srv", engine, server, game_shared, game_server, zlib, server_link_other) serverlaunch = {} diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 9e2033b2..899557f2 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -56,8 +56,25 @@ bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos) { m_EmoteStop = -1; m_LastAction = -1; - m_ActiveWeapon = WEAPON_GUN; - m_LastWeapon = WEAPON_HAMMER; + + /*zCatch */ + if(GameServer()->m_pController->IsZCatch() && g_Config.m_SvMode == 1) + { + m_ActiveWeapon = WEAPON_RIFLE; + m_LastWeapon = WEAPON_RIFLE; + } + else if(GameServer()->m_pController->IsZCatch() && g_Config.m_SvMode == 3) + { + m_ActiveWeapon = WEAPON_HAMMER; + m_LastWeapon = WEAPON_HAMMER; + } + else + { + m_ActiveWeapon = WEAPON_GUN; + m_LastWeapon = WEAPON_HAMMER; + } + /* end zCatch */ + m_QueuedWeapon = -1; m_pPlayer = pPlayer; @@ -444,7 +461,7 @@ void CCharacter::HandleWeapons() // ammo regen int AmmoRegenTime = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Ammoregentime; - if(AmmoRegenTime) + if(AmmoRegenTime && (m_ActiveWeapon == WEAPON_GUN || (GameServer()->m_pController->IsZCatch() && g_Config.m_SvMode == 2))) //zCatch { // If equipped and not active, regen ammo? if (m_ReloadTimer <= 0) @@ -725,8 +742,14 @@ bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon) m_DamageTaken = 0; GameServer()->CreateDamageInd(m_Pos, 0, Dmg); } - - if(Dmg) + /* zCatch*/ + if(GameServer()->m_pController->IsZCatch() && (g_Config.m_SvMode == 1 || g_Config.m_SvMode == 3)) + { + m_Health = 0; + m_Armor = 0; + } + /* end zCatch*/ + else if(Dmg) { if(m_Armor) { diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index a8b2f379..af3c672d 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -13,6 +13,7 @@ #include "gamemodes/tdm.h" #include "gamemodes/ctf.h" #include "gamemodes/mod.h" +#include "gamemodes/zcatch.hpp" enum { @@ -422,7 +423,10 @@ void CGameContext::OnTick() bool aVoteChecked[MAX_CLIENTS] = {0}; for(int i = 0; i < MAX_CLIENTS; i++) { - if(!m_apPlayers[i] || m_apPlayers[i]->GetTeam() == TEAM_SPECTATORS || aVoteChecked[i]) // don't count in votes by spectators + /* 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 continue; int ActVote = m_apPlayers[i]->m_Vote; @@ -508,6 +512,80 @@ void CGameContext::OnClientEnter(int ClientID) { //world.insert_entity(&players[client_id]); m_apPlayers[ClientID]->Respawn(); + + /* begin zCatch */ + int leader_id = -1; + int StartTeam = m_pController->ClampTeam(1); + + if(m_pController->IsZCatch()) + { + int num = 0; + + for(int i=0; i<MAX_CLIENTS; i++) + { + if(IsClientReady(i)) + num++; + } + if(num < 3) + m_pController->EndRound(); + + if(g_Config.m_SvAllowJoin == 0) + { + m_apPlayers[ClientID]->m_CatchedBy = ZCATCH_JOINED_NEW; + m_apPlayers[ClientID]->m_SpecExplicit = 0; + StartTeam = (num < 3) ? m_pController->ClampTeam(1) : TEAM_SPECTATORS; + } + else if(g_Config.m_SvAllowJoin == 1) + { + m_apPlayers[ClientID]->m_CatchedBy = ZCATCH_NOT_CATCHED; + m_apPlayers[ClientID]->m_SpecExplicit = (num < 3) ? 0 : 1; + StartTeam = (num < 3) ? m_pController->ClampTeam(1) : TEAM_SPECTATORS; + SendBroadcast("You can join the game", ClientID); + + } + else if(g_Config.m_SvAllowJoin == 2) + { + int num2 = 0, num_prev = 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_CatchedBy == i) + num2++; + } + if(num2 > num_prev) + { + leader_id = i; + num_prev = num2; + } + } + } + + if(leader_id > -1) + { + m_apPlayers[ClientID]->m_CatchedBy = leader_id; + m_apPlayers[ClientID]->m_SpecExplicit = 0; + m_apPlayers[ClientID]->m_SpectatorID = leader_id; + StartTeam = TEAM_SPECTATORS; + } + else + { + m_apPlayers[ClientID]->m_CatchedBy = ZCATCH_NOT_CATCHED; + m_apPlayers[ClientID]->m_SpecExplicit = 0; + } + } + 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())); SendChat(-1, CGameContext::CHAT_ALL, aBuf); @@ -516,6 +594,21 @@ void CGameContext::OnClientEnter(int ClientID) Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); m_VoteUpdate = true; + + /* zCatch begin */ + if(m_pController->IsZCatch()) + { + 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 && leader_id > -1) + { + char buf[128]; + str_format(buf, sizeof(buf), "You will join the game when %s dies", Server()->ClientName(leader_id)); + SendChatTarget(ClientID, buf); + } + } + /* zCatch end */ } void CGameContext::OnClientConnected(int ClientID) @@ -601,7 +694,45 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) pMessage++; } - SendChat(ClientID, Team, pMsg->m_pMessage); + /* begin zCatch*/ + if(!str_comp("/info", pMsg->m_pMessage) || !str_comp("/about", pMsg->m_pMessage)) + { + SendChatTarget(ClientID, " "); + SendChatTarget(ClientID, "zCatch v.0.4.1 by erd and Teetime. Type /cmdlist for all commands."); + } + else if(!str_comp("/cmdlist", pMsg->m_pMessage)) + { + SendChatTarget(ClientID, " "); + SendChatTarget(ClientID, "/info or /about - see information about author."); + SendChatTarget(ClientID, "/help - learn how to play."); + SendChatTarget(ClientID, "/follow 1 or /follow 0 - Enables/Disables following of the catcher."); + } + else if(!str_comp("/help", pMsg->m_pMessage)) + { + SendChatTarget(ClientID, " "); + SendChatTarget(ClientID, "The winner is the tee which is left over at the end."); + SendChatTarget(ClientID, "If you die, all players that you killed will respawn."); + SendChatTarget(ClientID, "So the only way to win is to kill every player without beeing killed."); + SendChatTarget(ClientID, "Have fun!"); + } + else if(!str_comp("/follow 0", pMsg->m_pMessage)) + { + pPlayer->m_PlayerWantToFollowCatcher = 0; + pPlayer->m_SpectatorID = SPEC_FREEVIEW; + SendChatTarget(ClientID, "Follow of catcher disabled."); + } + else if(!str_comp("/follow 1", pMsg->m_pMessage)) + { + pPlayer->m_PlayerWantToFollowCatcher = 1; + if(pPlayer->m_CatchedBy != ZCATCH_JOINED_NEW) // prevent freezing of client on the latest pos when sv_allow_join == 0 + pPlayer->m_SpectatorID = pPlayer->m_CatchedBy; + SendChatTarget(ClientID, "Follow of catcher enabled."); + } + else if(!str_comp_num("/", pMsg->m_pMessage, 1)) + SendChatTarget(ClientID, "Unknown command."); + else + SendChat(ClientID, Team, pMsg->m_pMessage); + /* end zCatch */ } else if(MsgID == NETMSGTYPE_CL_CALLVOTE) { @@ -610,7 +741,8 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) int64 Now = Server()->Tick(); pPlayer->m_LastVoteTry = Now; - if(pPlayer->GetTeam() == TEAM_SPECTATORS) + // zCatch - Only People who are explicit in Spectators can't vote! + if(pPlayer->m_SpecExplicit == 1) //zCatch { SendChatTarget(ClientID, "Spectators aren't allowed to start a vote."); return; @@ -673,7 +805,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]->GetTeam() != TEAM_SPECTATORS) + if(m_apPlayers[i] && m_apPlayers[i]->m_SpecExplicit != 1) // zCatch - Count all Players who are not explicit in spectator ++PlayerNum; if(PlayerNum < g_Config.m_SvVoteKickMin) @@ -787,7 +919,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) // Switch team on given client and kill/respawn him if(m_pController->CanJoinTeam(pMsg->m_Team, ClientID)) { - if(m_pController->CanChangeTeam(pPlayer, pMsg->m_Team)) + if(m_pController->CanChangeTeam(pPlayer, pMsg->m_Team) && !m_pController->IsZCatch()) //zCatch) { pPlayer->m_LastSetTeam = Server()->Tick(); if(pPlayer->GetTeam() == TEAM_SPECTATORS || pMsg->m_Team == TEAM_SPECTATORS) @@ -796,6 +928,27 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) (void)m_pController->CheckTeamBalance(); pPlayer->m_TeamChangeTick = Server()->Tick(); } + /* begin zCatch*/ + else if(m_pController->IsZCatch()) + { + if(pPlayer->m_CatchedBy >= 0) + { + char buf[256]; + str_format(buf, sizeof(buf), "You will join automatically when \"%s\" dies.", Server()->ClientName(pPlayer->m_CatchedBy)); + SendChatTarget(ClientID, buf); + return; + } + else if(pPlayer->m_CatchedBy == ZCATCH_NOT_CATCHED) + { + pPlayer->m_LastSetTeam = Server()->Tick(); + pPlayer->SetTeam(pMsg->m_Team); + } + else if(pPlayer->m_CatchedBy == ZCATCH_JOINED_NEW) + { + SendChatTarget(ClientID, "You will join automatically when the next round starts."); + } + } + /* end zCatch*/ else SendBroadcast("Teams must be balanced, please join other team", ClientID); } @@ -957,11 +1110,21 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) } else if (MsgID == NETMSGTYPE_CL_KILL && !m_World.m_Paused) { - if(pPlayer->m_LastKill && pPlayer->m_LastKill+Server()->TickSpeed()*3 > Server()->Tick()) - return; - - pPlayer->m_LastKill = Server()->Tick(); - pPlayer->KillCharacter(WEAPON_SELF); + /* begin zCatch*/ + if(pPlayer->m_LastKill && pPlayer->m_LastKill + Server()->TickSpeed()*15 > Server()->Tick()) + { + if((pPlayer->GetTeam() == TEAM_SPECTATORS) || (pPlayer->m_LastKillTry && pPlayer->m_LastKillTry+Server()->TickSpeed()*2 > Server()->Tick())) + return; + SendChatTarget(ClientID, "Only one kill in 15sec is allowed."); + pPlayer->m_LastKillTry = Server()->Tick(); + } + else + { + pPlayer->m_LastKill = Server()->Tick(); + pPlayer->KillCharacter(WEAPON_SELF); + pPlayer->m_Deaths++; + } + /* end zCatch*/ } } @@ -1360,6 +1523,8 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/) m_pController = new CGameControllerCTF(this); else if(str_comp(g_Config.m_SvGametype, "tdm") == 0) m_pController = new CGameControllerTDM(this); + else if(str_comp_nocase(g_Config.m_SvGametype, "zcatch") == 0) + m_pController = new CGameController_zCatch(this); else m_pController = new CGameControllerDM(this); diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 6288850d..2e36bbc7 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -128,6 +128,12 @@ public: CHAT_RED=0, CHAT_BLUE=1 }; + + enum + { + ZCATCH_JOINED_NEW = -2, + ZCATCH_NOT_CATCHED = -1, + }; // network void SendChatTarget(int To, const char *pText); diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index f0facb8c..56407a77 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -136,30 +136,35 @@ bool IGameController::OnEntity(int Index, vec2 Pos) m_aaSpawnPoints[1][m_aNumSpawnPoints[1]++] = Pos; else if(Index == ENTITY_SPAWN_BLUE) m_aaSpawnPoints[2][m_aNumSpawnPoints[2]++] = Pos; - else if(Index == ENTITY_ARMOR_1) - Type = POWERUP_ARMOR; - else if(Index == ENTITY_HEALTH_1) - Type = POWERUP_HEALTH; - else if(Index == ENTITY_WEAPON_SHOTGUN) - { - Type = POWERUP_WEAPON; - SubType = WEAPON_SHOTGUN; - } - else if(Index == ENTITY_WEAPON_GRENADE) - { - Type = POWERUP_WEAPON; - SubType = WEAPON_GRENADE; - } - else if(Index == ENTITY_WEAPON_RIFLE) - { - Type = POWERUP_WEAPON; - SubType = WEAPON_RIFLE; - } - else if(Index == ENTITY_POWERUP_NINJA && g_Config.m_SvPowerups) - { - Type = POWERUP_NINJA; - SubType = WEAPON_NINJA; - } + /* zCatch */ + else if(!GameServer()->m_pController->IsZCatch() || g_Config.m_SvMode == 0) + { + if(Index == ENTITY_ARMOR_1) + Type = POWERUP_ARMOR; + else if(Index == ENTITY_HEALTH_1) + Type = POWERUP_HEALTH; + else if(Index == ENTITY_WEAPON_SHOTGUN) + { + Type = POWERUP_WEAPON; + SubType = WEAPON_SHOTGUN; + } + else if(Index == ENTITY_WEAPON_GRENADE) + { + Type = POWERUP_WEAPON; + SubType = WEAPON_GRENADE; + } + else if(Index == ENTITY_WEAPON_RIFLE) + { + Type = POWERUP_WEAPON; + SubType = WEAPON_RIFLE; + } + else if(Index == ENTITY_POWERUP_NINJA && g_Config.m_SvPowerups) + { + Type = POWERUP_NINJA; + SubType = WEAPON_NINJA; + } + } + /* end zCatch*/ if(Type != -1) { @@ -171,6 +176,11 @@ bool IGameController::OnEntity(int Index, vec2 Pos) return false; } +bool IGameController::IsZCatch() +{ + return false; +} + void IGameController::EndRound() { if(m_Warmup) // game can't end when we are running warmup diff --git a/src/game/server/gamecontroller.h b/src/game/server/gamecontroller.h index 4706df48..914f7985 100644 --- a/src/game/server/gamecontroller.h +++ b/src/game/server/gamecontroller.h @@ -72,8 +72,8 @@ public: void DoWarmup(int Seconds); - void StartRound(); - void EndRound(); + virtual void StartRound(); + virtual void EndRound(); void ChangeMap(const char *pToMap); bool IsFriendlyFire(int ClientID1, int ClientID2); @@ -141,6 +141,8 @@ public: int ClampTeam(int Team); virtual void PostReset(); + + virtual bool IsZCatch(); }; #endif diff --git a/src/game/server/gamemodes/zcatch.cpp b/src/game/server/gamemodes/zcatch.cpp new file mode 100644 index 00000000..50618f67 --- /dev/null +++ b/src/game/server/gamemodes/zcatch.cpp @@ -0,0 +1,167 @@ +/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ +/* zCatch by erd_baer */ +#include <engine/server.h> +#include <engine/shared/config.h> +#include <game/server/entities/character.h> +#include <game/server/player.h> +#include <game/server/gamecontext.h> +#include "zcatch.hpp" + +CGameController_zCatch::CGameController_zCatch(class CGameContext *pGameServer) +: IGameController(pGameServer) +{ + m_pGameType = "zCatch"; +} + +void CGameController_zCatch::Tick() +{ + DoWincheck(); + IGameController::Tick(); +} +bool CGameController_zCatch::IsZCatch() +{ + return true; +} + +int CGameController_zCatch::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int WeaponID) +{ + int client_id = pVictim->GetPlayer()->GetCID(); + char buf[256]; + 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_CatchedBy = pKiller->GetCID(); + pVictim->GetPlayer()->SetTeamDirect(TEAM_SPECTATORS); + + if(pVictim->GetPlayer()->m_PlayerWantToFollowCatcher) + pVictim->GetPlayer()->m_SpectatorID = pKiller->GetCID(); // Let the victim follow his catcher + + str_format(buf, sizeof(buf), "Caught by \"%s\". You will join the game automatically when \"%s\" dies.", Server()->ClientName(pKiller->GetCID()), Server()->ClientName(pKiller->GetCID())); + GameServer()->SendChatTarget(client_id, buf); + } + } + + for(int i=0; i < MAX_CLIENTS; i++) + { + if(GameServer()->m_apPlayers[i]) + { + if(GameServer()->m_apPlayers[i]->m_CatchedBy == client_id) + { + GameServer()->m_apPlayers[i]->m_CatchedBy = ZCATCH_NOT_CATCHED; + GameServer()->m_apPlayers[i]->SetTeamDirect(GameServer()->m_pController->ClampTeam(1)); + + GameServer()->m_pController->OnPlayerInfoChange(GameServer()->m_apPlayers[i]); + if(pKiller != pVictim->GetPlayer()) + pKiller->m_Score++; + } + } + } + return 0; +} + +void CGameController_zCatch::StartRound() +{ + ResetGame(); + + m_RoundStartTick = Server()->Tick(); + m_SuddenDeath = 0; + m_GameOverTick = -1; + GameServer()->m_World.m_Paused = false; + m_aTeamscore[TEAM_RED] = 0; + m_aTeamscore[TEAM_BLUE] = 0; + m_UnbalancedTick = -1; + m_ForceBalanced = false; + 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]->m_CatchedBy == ZCATCH_JOINED_NEW) + GameServer()->m_apPlayers[i]->SetTeamDirect(GameServer()->m_pController->ClampTeam(1)); + + GameServer()->m_apPlayers[i]->m_CatchedBy = ZCATCH_NOT_CATCHED; + 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; + GameServer()->m_pController->OnPlayerInfoChange(GameServer()->m_apPlayers[i]); + } + } + char aBufMsg[256]; + str_format(aBufMsg, sizeof(aBufMsg), "start round type='%s' teamplay='%d'", m_pGameType, m_GameFlags&GAMEFLAG_TEAMS); + GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBufMsg); +} + +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 0: + pChr->GiveWeapon(WEAPON_HAMMER, -1); + pChr->GiveWeapon(WEAPON_GUN, 10); + break; + case 1: + pChr->GiveWeapon(WEAPON_RIFLE, -1); + break; + case 2: + pChr->GiveWeapon(WEAPON_HAMMER, -1); + pChr->GiveWeapon(WEAPON_GUN, 10); + pChr->GiveWeapon(WEAPON_GRENADE, 10); + pChr->GiveWeapon(WEAPON_SHOTGUN, 10); + pChr->GiveWeapon(WEAPON_RIFLE, -1); + break; + case 3: + pChr->GiveWeapon(WEAPON_HAMMER, -1); + break; + } +} +void CGameController_zCatch::EndRound() +{ + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(GameServer()->m_apPlayers[i]) + { + + if(GameServer()->m_apPlayers[i]->m_CatchedBy == ZCATCH_JOINED_NEW) //Neue Spieler joinen lassen + GameServer()->m_apPlayers[i]->m_SpecExplicit = 0; + + if(GameServer()->m_apPlayers[i]->m_SpecExplicit == 0) + { + GameServer()->m_apPlayers[i]->SetTeamDirect(GameServer()->m_pController->ClampTeam(1)); + GameServer()->m_pController->OnPlayerInfoChange(GameServer()->m_apPlayers[i]); + + if(GameServer()->m_apPlayers[i]->m_CatchedBy != ZCATCH_JOINED_NEW) + { + 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_CatchedBy = ZCATCH_NOT_CATCHED; //Set all players in server as non-catched + } + } + } + + 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; +} diff --git a/src/game/server/gamemodes/zcatch.hpp b/src/game/server/gamemodes/zcatch.hpp new file mode 100644 index 00000000..7d6836d2 --- /dev/null +++ b/src/game/server/gamemodes/zcatch.hpp @@ -0,0 +1,26 @@ +/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ +#ifndef GAME_SERVER_GAMEMODES_ZCATCH_H +#define GAME_SERVER_GAMEMODES_DM_H + +#include <game/server/gamecontroller.h> + +class CGameController_zCatch : public IGameController +{ + public: + CGameController_zCatch(class CGameContext *pGameServer); + virtual void Tick(); + virtual bool IsZCatch(); + + enum + { + ZCATCH_JOINED_NEW = -2, + ZCATCH_NOT_CATCHED = -1, + }; + + virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int WeaponID); + virtual void StartRound(); + virtual void OnCharacterSpawn(class CCharacter *pChr); + virtual void EndRound(); +}; + +#endif diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index 1f822524..7bac6454 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -21,6 +21,16 @@ CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, int Team) m_SpectatorID = SPEC_FREEVIEW; m_LastActionTick = Server()->Tick(); m_TeamChangeTick = Server()->Tick(); + + //zCatch + m_CatchedBy = -1; + m_SpecExplicit = 0; + m_Kills = 0; + m_Deaths = 0; + m_PlayerWantToFollowCatcher = g_Config.m_SvFollowCatcher; + m_LastKillTry = Server()->Tick(); + m_TicksSpec = 0; + m_TicksIngame = 0; } CPlayer::~CPlayer() @@ -38,6 +48,48 @@ void CPlayer::Tick() return; Server()->SetClientScore(m_ClientID, m_Score); + + /* begin zCatch*/ + int num = 0, num_spec = 0, num_SpecExplicit = 0; + + if(m_Team == TEAM_SPECTATORS) + m_TicksSpec++; + else + m_TicksIngame++; + + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(GameServer()->m_apPlayers[i]) + { + num++; + if(GameServer()->m_apPlayers[i]->m_Team == TEAM_SPECTATORS) + num_spec++; + if(GameServer()->m_apPlayers[i]->m_SpecExplicit == 1) + num_SpecExplicit++; + } + } + + if(num == 1) + { + //Do nothing + } + //solution for sv_allow_join == 0 and mapchange: + else if((g_Config.m_SvAllowJoin == 0) && (num_spec == num) && (num_spec != num_SpecExplicit)) + { + GameServer()->m_pController->EndRound(); + } + else if((num - num_spec == 1) && (num != num_spec) && (num - num_SpecExplicit != 1)) + { + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->m_Team != TEAM_SPECTATORS) + GameServer()->m_apPlayers[i]->m_Score += g_Config.m_SvBonus; + GameServer()->m_pController->EndRound(); + break; + } + } + + /* end zCatch*/ // do latency stuff { @@ -128,6 +180,20 @@ void CPlayer::Snap(int SnappingClient) if(m_ClientID == SnappingClient) pPlayerInfo->m_Local = 1; + + /* begin zCatch*/ + if(GameServer()->m_apPlayers[m_ClientID] && GameServer()->m_pController->IsZCatch() && 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_CatchedBy == m_ClientID) + num -= 10; + pClientInfo->m_ColorBody = num * 0x010000 + 0xff00; + pClientInfo->m_ColorFeet = num * 0x010000 + 0xff00; + pClientInfo->m_UseCustomColor = 1; + } + + /* end zCatch*/ if(m_ClientID == SnappingClient && m_Team == TEAM_SPECTATORS) { @@ -263,6 +329,11 @@ void CPlayer::SetTeam(int Team) } } +void CPlayer::SetTeamDirect(int Team) +{ + m_Team = Team; +} + void CPlayer::TryRespawn() { vec2 SpawnPos; diff --git a/src/game/server/player.h b/src/game/server/player.h index b8c4ce6c..05e52f05 100644 --- a/src/game/server/player.h +++ b/src/game/server/player.h @@ -21,6 +21,7 @@ public: void TryRespawn(); void Respawn(); void SetTeam(int Team); + void SetTeamDirect(int Team); //zCatch int GetTeam() const { return m_Team; }; int GetCID() const { return m_ClientID; }; @@ -95,7 +96,18 @@ public: int m_Min; int m_Max; } m_Latency; - + + //zCatch: + int m_CatchedBy; + int m_SpecExplicit; + int m_Deaths; + int m_Kills; + int m_LastKillTry; + bool m_PlayerWantToFollowCatcher; + + int m_TicksSpec; + int m_TicksIngame; + private: CCharacter *m_pCharacter; CGameContext *m_pGameServer; diff --git a/src/game/variables.h b/src/game/variables.h index 3af299cf..28d8ceea 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -88,3 +88,11 @@ MACRO_CONFIG_INT(SvVoteKickBantime, sv_vote_kick_bantime, 5, 0, 1440, CFGFLAG_SE MACRO_CONFIG_INT(DbgFocus, dbg_focus, 0, 0, 1, CFGFLAG_CLIENT, "") MACRO_CONFIG_INT(DbgTuning, dbg_tuning, 0, 0, 1, CFGFLAG_CLIENT, "") #endif + +//zCatch: +MACRO_CONFIG_INT(SvMode, sv_mode, 1, 0, 3, CFGFLAG_SERVER, "0 - Normal; 1 - Instagib; 2 - Rocket area; 3 - Hammerparty") +MACRO_CONFIG_INT(SvAllowJoin, sv_allow_join, 2, 0, 2, CFGFLAG_SERVER, "Allow new Players to join without waiting for the next round") +//0 - Wait for next round; 1 = Allowed to join; 2 = Will join when person with the most kills die +MACRO_CONFIG_INT(SvColorIndicator, sv_color_indicator, 1, 0, 1, CFGFLAG_SERVER, "Color tees apropriate to the number of currently catched players") +MACRO_CONFIG_INT(SvBonus, sv_bonus, 0, 0, 10000, CFGFLAG_SERVER, "Give the last player extra points") +MACRO_CONFIG_INT(SvFollowCatcher, sv_follow_catcher, 1, 0, 1, CFGFLAG_SERVER, "If a victim should follow his catcher") \ No newline at end of file |