diff options
Diffstat (limited to 'src/game/server/gamemodes')
| -rw-r--r-- | src/game/server/gamemodes/zcatch.cpp | 252 | ||||
| -rw-r--r-- | src/game/server/gamemodes/zcatch.h | 30 |
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 |