/* (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 #include #include #include #include #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); } }