2010-11-20 10:37:14 +00:00
|
|
|
/* (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. */
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <engine/shared/config.h>
|
|
|
|
#include <game/mapitems.h>
|
2008-08-14 18:42:47 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <game/generated/protocol.h>
|
2007-10-05 00:05:21 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include "entities/pickup.h"
|
|
|
|
#include "gamecontroller.h"
|
|
|
|
#include "gamecontext.h"
|
2008-08-14 18:25:44 +00:00
|
|
|
|
2008-08-27 20:04:07 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
IGameController::IGameController(class CGameContext *pGameServer)
|
2008-08-27 20:04:07 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_pGameServer = pGameServer;
|
|
|
|
m_pServer = m_pGameServer->Server();
|
|
|
|
m_pGameType = "unknown";
|
2008-08-31 14:37:35 +00:00
|
|
|
|
2008-08-27 20:04:07 +00:00
|
|
|
//
|
2010-05-29 07:25:38 +00:00
|
|
|
DoWarmup(g_Config.m_SvWarmup);
|
|
|
|
m_GameOverTick = -1;
|
|
|
|
m_SuddenDeath = 0;
|
|
|
|
m_RoundStartTick = Server()->Tick();
|
|
|
|
m_RoundCount = 0;
|
|
|
|
m_GameFlags = 0;
|
2011-01-03 11:50:38 +00:00
|
|
|
m_aTeamscore[TEAM_RED] = 0;
|
|
|
|
m_aTeamscore[TEAM_BLUE] = 0;
|
2010-05-29 07:25:38 +00:00
|
|
|
m_aMapWish[0] = 0;
|
|
|
|
|
|
|
|
m_UnbalancedTick = -1;
|
|
|
|
m_ForceBalanced = false;
|
|
|
|
|
|
|
|
m_aNumSpawnPoints[0] = 0;
|
|
|
|
m_aNumSpawnPoints[1] = 0;
|
|
|
|
m_aNumSpawnPoints[2] = 0;
|
2008-08-27 20:04:07 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
IGameController::~IGameController()
|
2008-10-02 14:44:35 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
float IGameController::EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
float Score = 0.0f;
|
2011-01-19 17:27:50 +00:00
|
|
|
CCharacter *pC = static_cast<CCharacter *>(GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER));
|
2010-05-29 07:25:38 +00:00
|
|
|
for(; pC; pC = (CCharacter *)pC->TypeNext())
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
|
|
|
// team mates are not as dangerous as enemies
|
2010-05-29 07:25:38 +00:00
|
|
|
float Scoremod = 1.0f;
|
|
|
|
if(pEval->m_FriendlyTeam != -1 && pC->GetPlayer()->GetTeam() == pEval->m_FriendlyTeam)
|
|
|
|
Scoremod = 0.5f;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
float d = distance(Pos, pC->m_Pos);
|
2011-01-17 14:55:23 +00:00
|
|
|
Score += Scoremod * (d == 0 ? 1000000000.0f : 1.0f/d);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
return Score;
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void IGameController::EvaluateSpawnType(CSpawnEval *pEval, int T)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
|
|
|
// get spawn point
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int i = 0; i < m_aNumSpawnPoints[T]; i++)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2011-02-10 11:05:55 +00:00
|
|
|
// check if the position is occupado
|
|
|
|
if(GameServer()->m_World.FindEntities(m_aaSpawnPoints[T][i], 64, 0, 1, CGameWorld::ENTTYPE_CHARACTER))
|
|
|
|
continue;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 P = m_aaSpawnPoints[T][i];
|
|
|
|
float S = EvaluateSpawnPos(pEval, P);
|
|
|
|
if(!pEval->m_Got || pEval->m_Score > S)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
pEval->m_Got = true;
|
|
|
|
pEval->m_Score = S;
|
|
|
|
pEval->m_Pos = P;
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-10 11:05:55 +00:00
|
|
|
bool IGameController::CanSpawn(int Team, vec2 *pOutPos)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CSpawnEval Eval;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2008-11-21 14:18:55 +00:00
|
|
|
// spectators can't spawn
|
2011-02-10 11:05:55 +00:00
|
|
|
if(Team == TEAM_SPECTATORS)
|
2008-11-21 14:18:55 +00:00
|
|
|
return false;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(IsTeamplay())
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2011-02-10 11:05:55 +00:00
|
|
|
Eval.m_FriendlyTeam = Team;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2011-02-10 11:05:55 +00:00
|
|
|
// first try own team spawn, then normal spawn and then enemy
|
|
|
|
EvaluateSpawnType(&Eval, 1+(Team&1));
|
2010-05-29 07:25:38 +00:00
|
|
|
if(!Eval.m_Got)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
EvaluateSpawnType(&Eval, 0);
|
|
|
|
if(!Eval.m_Got)
|
2011-02-10 11:05:55 +00:00
|
|
|
EvaluateSpawnType(&Eval, 1+((Team+1)&1));
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
EvaluateSpawnType(&Eval, 0);
|
|
|
|
EvaluateSpawnType(&Eval, 1);
|
|
|
|
EvaluateSpawnType(&Eval, 2);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
*pOutPos = Eval.m_Pos;
|
|
|
|
return Eval.m_Got;
|
2007-10-05 00:05:21 +00:00
|
|
|
}
|
|
|
|
|
2008-08-27 20:04:07 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
bool IGameController::OnEntity(int Index, vec2 Pos)
|
2008-01-13 11:43:43 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int Type = -1;
|
|
|
|
int SubType = 0;
|
2008-01-13 11:43:43 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
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;
|
|
|
|
else if(Index == ENTITY_ARMOR_1)
|
|
|
|
Type = POWERUP_ARMOR;
|
|
|
|
else if(Index == ENTITY_HEALTH_1)
|
|
|
|
Type = POWERUP_HEALTH;
|
|
|
|
else if(Index == ENTITY_WEAPON_SHOTGUN)
|
2008-01-13 11:43:43 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Type = POWERUP_WEAPON;
|
|
|
|
SubType = WEAPON_SHOTGUN;
|
2008-01-13 11:43:43 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(Index == ENTITY_WEAPON_GRENADE)
|
2008-01-13 11:43:43 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Type = POWERUP_WEAPON;
|
|
|
|
SubType = WEAPON_GRENADE;
|
2008-01-13 11:43:43 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(Index == ENTITY_WEAPON_RIFLE)
|
2008-03-21 19:05:35 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Type = POWERUP_WEAPON;
|
|
|
|
SubType = WEAPON_RIFLE;
|
2008-03-21 19:05:35 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(Index == ENTITY_POWERUP_NINJA && g_Config.m_SvPowerups)
|
2008-01-13 11:43:43 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Type = POWERUP_NINJA;
|
|
|
|
SubType = WEAPON_NINJA;
|
2008-01-13 11:43:43 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Type != -1)
|
2008-01-13 11:43:43 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CPickup *pPickup = new CPickup(&GameServer()->m_World, Type, SubType);
|
|
|
|
pPickup->m_Pos = Pos;
|
2008-01-13 11:43:43 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void IGameController::EndRound()
|
2007-10-05 00:05:21 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_Warmup) // game can't end when we are running warmup
|
2007-10-06 17:36:24 +00:00
|
|
|
return;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
GameServer()->m_World.m_Paused = true;
|
|
|
|
m_GameOverTick = Server()->Tick();
|
|
|
|
m_SuddenDeath = 0;
|
2007-10-05 00:05:21 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void IGameController::ResetGame()
|
2007-10-05 00:05:21 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
GameServer()->m_World.m_ResetRequested = true;
|
2008-07-06 11:21:21 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
const char *IGameController::GetTeamName(int Team)
|
2008-07-06 11:21:21 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(IsTeamplay())
|
2008-07-06 11:21:21 +00:00
|
|
|
{
|
2011-01-03 11:50:38 +00:00
|
|
|
if(Team == TEAM_RED)
|
2008-07-06 11:21:21 +00:00
|
|
|
return "red team";
|
2011-01-03 11:50:38 +00:00
|
|
|
else if(Team == TEAM_BLUE)
|
2008-07-06 11:21:21 +00:00
|
|
|
return "blue team";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Team == 0)
|
2008-07-06 11:21:21 +00:00
|
|
|
return "game";
|
|
|
|
}
|
|
|
|
|
|
|
|
return "spectators";
|
2007-10-05 00:05:21 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
static bool IsSeparator(char c) { return c == ';' || c == ' ' || c == ',' || c == '\t'; }
|
2007-10-05 00:05:21 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void IGameController::StartRound()
|
2007-10-05 00:05:21 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
ResetGame();
|
|
|
|
|
|
|
|
m_RoundStartTick = Server()->Tick();
|
|
|
|
m_SuddenDeath = 0;
|
|
|
|
m_GameOverTick = -1;
|
|
|
|
GameServer()->m_World.m_Paused = false;
|
2011-01-03 11:50:38 +00:00
|
|
|
m_aTeamscore[TEAM_RED] = 0;
|
|
|
|
m_aTeamscore[TEAM_BLUE] = 0;
|
2010-05-29 07:25:38 +00:00
|
|
|
m_ForceBalanced = false;
|
2010-08-17 22:06:00 +00:00
|
|
|
char aBuf[256];
|
|
|
|
str_format(aBuf, sizeof(aBuf), "start round type='%s' teamplay='%d'", m_pGameType, m_GameFlags&GAMEFLAG_TEAMS);
|
|
|
|
GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
|
2007-10-05 00:05:21 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void IGameController::ChangeMap(const char *pToMap)
|
2008-10-22 14:31:46 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
str_copy(m_aMapWish, pToMap, sizeof(m_aMapWish));
|
|
|
|
EndRound();
|
2008-10-22 14:31:46 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void IGameController::CycleMap()
|
2007-10-05 00:05:21 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_aMapWish[0] != 0)
|
2008-10-22 14:31:46 +00:00
|
|
|
{
|
2010-08-17 22:06:00 +00:00
|
|
|
char aBuf[256];
|
|
|
|
str_format(aBuf, sizeof(aBuf), "rotating map to %s", m_aMapWish);
|
|
|
|
GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
|
2010-05-29 07:25:38 +00:00
|
|
|
str_copy(g_Config.m_SvMap, m_aMapWish, sizeof(g_Config.m_SvMap));
|
|
|
|
m_aMapWish[0] = 0;
|
|
|
|
m_RoundCount = 0;
|
2008-10-22 14:31:46 +00:00
|
|
|
return;
|
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
if(!str_length(g_Config.m_SvMaprotation))
|
2007-10-05 00:05:21 +00:00
|
|
|
return;
|
2008-03-01 20:21:34 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_RoundCount < g_Config.m_SvRoundsPerMap-1)
|
2008-03-29 21:46:38 +00:00
|
|
|
return;
|
|
|
|
|
2007-10-05 00:05:21 +00:00
|
|
|
// handle maprotation
|
2010-05-29 07:25:38 +00:00
|
|
|
const char *pMapRotation = g_Config.m_SvMaprotation;
|
|
|
|
const char *pCurrentMap = g_Config.m_SvMap;
|
2008-03-01 20:21:34 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int CurrentMapLen = str_length(pCurrentMap);
|
|
|
|
const char *pNextMap = pMapRotation;
|
|
|
|
while(*pNextMap)
|
2007-10-05 00:05:21 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int WordLen = 0;
|
|
|
|
while(pNextMap[WordLen] && !IsSeparator(pNextMap[WordLen]))
|
|
|
|
WordLen++;
|
2007-10-05 00:05:21 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(WordLen == CurrentMapLen && str_comp_num(pNextMap, pCurrentMap, CurrentMapLen) == 0)
|
2008-03-01 20:21:34 +00:00
|
|
|
{
|
|
|
|
// map found
|
2010-05-29 07:25:38 +00:00
|
|
|
pNextMap += CurrentMapLen;
|
|
|
|
while(*pNextMap && IsSeparator(*pNextMap))
|
|
|
|
pNextMap++;
|
2008-03-01 20:21:34 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
pNextMap++;
|
2008-03-01 20:21:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// restart rotation
|
2010-05-29 07:25:38 +00:00
|
|
|
if(pNextMap[0] == 0)
|
|
|
|
pNextMap = pMapRotation;
|
2008-03-01 20:21:34 +00:00
|
|
|
|
|
|
|
// cut out the next map
|
2010-08-17 22:06:00 +00:00
|
|
|
char aBuf[512];
|
2008-03-01 20:21:34 +00:00
|
|
|
for(int i = 0; i < 512; i++)
|
2007-10-05 00:05:21 +00:00
|
|
|
{
|
2010-08-17 22:06:00 +00:00
|
|
|
aBuf[i] = pNextMap[i];
|
2010-05-29 07:25:38 +00:00
|
|
|
if(IsSeparator(pNextMap[i]) || pNextMap[i] == 0)
|
2007-10-05 00:05:21 +00:00
|
|
|
{
|
2010-08-17 22:06:00 +00:00
|
|
|
aBuf[i] = 0;
|
2007-10-05 00:05:21 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-01 20:21:34 +00:00
|
|
|
// skip spaces
|
|
|
|
int i = 0;
|
2010-08-17 22:06:00 +00:00
|
|
|
while(IsSeparator(aBuf[i]))
|
2007-10-05 00:05:21 +00:00
|
|
|
i++;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
m_RoundCount = 0;
|
2009-01-13 17:58:16 +00:00
|
|
|
|
2010-08-17 22:06:00 +00:00
|
|
|
char aBufMsg[256];
|
|
|
|
str_format(aBufMsg, sizeof(aBufMsg), "rotating map to %s", &aBuf[i]);
|
|
|
|
GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
|
|
|
|
str_copy(g_Config.m_SvMap, &aBuf[i], sizeof(g_Config.m_SvMap));
|
2007-10-05 00:05:21 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void IGameController::PostReset()
|
2007-10-05 00:05:21 +00:00
|
|
|
{
|
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(GameServer()->m_apPlayers[i])
|
2008-10-25 08:36:55 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
GameServer()->m_apPlayers[i]->Respawn();
|
|
|
|
GameServer()->m_apPlayers[i]->m_Score = 0;
|
2010-05-31 20:35:47 +00:00
|
|
|
GameServer()->m_apPlayers[i]->m_ScoreStartTick = Server()->Tick();
|
2010-06-20 12:35:50 +00:00
|
|
|
GameServer()->m_apPlayers[i]->m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
|
2008-10-25 08:36:55 +00:00
|
|
|
}
|
2007-10-05 00:05:21 +00:00
|
|
|
}
|
|
|
|
}
|
2007-11-18 14:24:34 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void IGameController::OnPlayerInfoChange(class CPlayer *pP)
|
2007-11-18 14:24:34 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
const int aTeamColors[2] = {65387, 10223467};
|
|
|
|
if(IsTeamplay())
|
2007-11-18 14:24:34 +00:00
|
|
|
{
|
2011-01-03 11:50:38 +00:00
|
|
|
if(pP->GetTeam() >= TEAM_RED && pP->GetTeam() <= TEAM_BLUE)
|
2007-11-18 14:24:34 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
pP->m_TeeInfos.m_UseCustomColor = 1;
|
|
|
|
pP->m_TeeInfos.m_ColorBody = aTeamColors[pP->GetTeam()];
|
|
|
|
pP->m_TeeInfos.m_ColorFeet = aTeamColors[pP->GetTeam()];
|
2007-11-18 14:24:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int IGameController::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon)
|
2007-10-05 00:05:21 +00:00
|
|
|
{
|
|
|
|
// do scoreing
|
2010-06-03 21:08:05 +00:00
|
|
|
if(!pKiller || Weapon == WEAPON_GAME)
|
2007-11-18 23:29:34 +00:00
|
|
|
return 0;
|
2010-05-29 07:25:38 +00:00
|
|
|
if(pKiller == pVictim->GetPlayer())
|
|
|
|
pVictim->GetPlayer()->m_Score--; // suicide
|
2007-10-05 00:05:21 +00:00
|
|
|
else
|
2007-12-11 21:19:52 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(IsTeamplay() && pVictim->GetPlayer()->GetTeam() == pKiller->GetTeam())
|
|
|
|
pKiller->m_Score--; // teamkill
|
2007-12-11 21:19:52 +00:00
|
|
|
else
|
2010-05-29 07:25:38 +00:00
|
|
|
pKiller->m_Score++; // normal kill
|
2007-12-11 21:19:52 +00:00
|
|
|
}
|
2007-11-18 23:29:34 +00:00
|
|
|
return 0;
|
2007-10-05 00:05:21 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void IGameController::OnCharacterSpawn(class CCharacter *pChr)
|
2008-08-27 20:04:07 +00:00
|
|
|
{
|
2008-08-27 20:17:04 +00:00
|
|
|
// default health
|
2010-05-29 07:25:38 +00:00
|
|
|
pChr->IncreaseHealth(10);
|
2008-08-27 20:17:04 +00:00
|
|
|
|
2008-08-27 20:04:07 +00:00
|
|
|
// give default weapons
|
2010-05-29 07:25:38 +00:00
|
|
|
pChr->GiveWeapon(WEAPON_HAMMER, -1);
|
|
|
|
pChr->GiveWeapon(WEAPON_GUN, 10);
|
2008-08-27 20:04:07 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void IGameController::DoWarmup(int Seconds)
|
2007-10-06 17:36:24 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Seconds < 0)
|
|
|
|
m_Warmup = 0;
|
|
|
|
else
|
|
|
|
m_Warmup = Seconds*Server()->TickSpeed();
|
2007-10-06 17:36:24 +00:00
|
|
|
}
|
|
|
|
|
2011-02-12 10:40:36 +00:00
|
|
|
bool IGameController::IsFriendlyFire(int ClientID1, int ClientID2)
|
2007-12-10 20:53:37 +00:00
|
|
|
{
|
2011-02-12 10:40:36 +00:00
|
|
|
if(ClientID1 == ClientID2)
|
2007-12-10 20:53:37 +00:00
|
|
|
return false;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(IsTeamplay())
|
2007-12-10 20:53:37 +00:00
|
|
|
{
|
2011-02-12 10:40:36 +00:00
|
|
|
if(!GameServer()->m_apPlayers[ClientID1] || !GameServer()->m_apPlayers[ClientID2])
|
2008-12-19 08:26:58 +00:00
|
|
|
return false;
|
|
|
|
|
2011-02-12 10:40:36 +00:00
|
|
|
if(GameServer()->m_apPlayers[ClientID1]->GetTeam() == GameServer()->m_apPlayers[ClientID2]->GetTeam())
|
2007-12-10 20:53:37 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2007-10-05 00:05:21 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
bool IGameController::IsForceBalanced()
|
2008-09-07 08:57:59 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_ForceBalanced)
|
2008-09-07 08:57:59 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_ForceBalanced = false;
|
2008-09-07 08:57:59 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-02-12 10:40:36 +00:00
|
|
|
bool IGameController::CanBeMovedOnBalance(int ClientID)
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void IGameController::Tick()
|
2007-10-05 00:05:21 +00:00
|
|
|
{
|
2007-10-06 17:36:24 +00:00
|
|
|
// do warmup
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_Warmup)
|
2007-10-06 17:36:24 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Warmup--;
|
|
|
|
if(!m_Warmup)
|
|
|
|
StartRound();
|
2007-10-06 17:36:24 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_GameOverTick != -1)
|
2007-10-05 00:05:21 +00:00
|
|
|
{
|
|
|
|
// game over.. wait for restart
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Server()->Tick() > m_GameOverTick+Server()->TickSpeed()*10)
|
2007-10-05 00:05:21 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CycleMap();
|
|
|
|
StartRound();
|
|
|
|
m_RoundCount++;
|
2007-10-05 00:05:21 +00:00
|
|
|
}
|
|
|
|
}
|
2007-11-27 19:51:48 +00:00
|
|
|
|
2008-10-19 16:51:16 +00:00
|
|
|
// do team-balancing
|
2010-05-29 07:25:38 +00:00
|
|
|
if (IsTeamplay() && m_UnbalancedTick != -1 && Server()->Tick() > m_UnbalancedTick+g_Config.m_SvTeambalanceTime*Server()->TickSpeed()*60)
|
2008-09-07 08:10:56 +00:00
|
|
|
{
|
2010-08-17 22:06:00 +00:00
|
|
|
GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", "Balancing teams");
|
2008-09-07 08:10:56 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int aT[2] = {0,0};
|
2010-05-31 20:35:47 +00:00
|
|
|
float aTScore[2] = {0,0};
|
|
|
|
float aPScore[MAX_CLIENTS] = {0.0f};
|
2008-09-07 08:10:56 +00:00
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
2011-01-03 11:50:38 +00:00
|
|
|
if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
|
2008-10-19 16:14:12 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
aT[GameServer()->m_apPlayers[i]->GetTeam()]++;
|
2010-05-31 20:35:47 +00:00
|
|
|
aPScore[i] = GameServer()->m_apPlayers[i]->m_Score*Server()->TickSpeed()*60.0f/
|
|
|
|
(Server()->Tick()-GameServer()->m_apPlayers[i]->m_ScoreStartTick);
|
|
|
|
aTScore[GameServer()->m_apPlayers[i]->GetTeam()] += aPScore[i];
|
2008-10-19 16:14:12 +00:00
|
|
|
}
|
2008-09-07 08:10:56 +00:00
|
|
|
}
|
|
|
|
|
2008-10-19 18:38:23 +00:00
|
|
|
// are teams unbalanced?
|
2010-05-29 07:25:38 +00:00
|
|
|
if(absolute(aT[0]-aT[1]) >= 2)
|
2008-09-07 08:10:56 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int M = (aT[0] > aT[1]) ? 0 : 1;
|
|
|
|
int NumBalance = absolute(aT[0]-aT[1]) / 2;
|
2008-10-19 18:38:23 +00:00
|
|
|
|
|
|
|
do
|
2008-09-07 08:10:56 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CPlayer *pP = 0;
|
2010-08-16 00:21:18 +00:00
|
|
|
float PD = aTScore[M];
|
2008-10-19 18:38:23 +00:00
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
2008-09-07 08:10:56 +00:00
|
|
|
{
|
2010-05-31 20:35:47 +00:00
|
|
|
if(!GameServer()->m_apPlayers[i] || !CanBeMovedOnBalance(i))
|
2008-10-19 18:38:23 +00:00
|
|
|
continue;
|
|
|
|
// remember the player who would cause lowest score-difference
|
2010-05-31 20:35:47 +00:00
|
|
|
if(GameServer()->m_apPlayers[i]->GetTeam() == M && (!pP || absolute((aTScore[M^1]+aPScore[i]) - (aTScore[M]-aPScore[i])) < PD))
|
2008-10-19 18:38:23 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
pP = GameServer()->m_apPlayers[i];
|
2010-05-31 20:35:47 +00:00
|
|
|
PD = absolute((aTScore[M^1]+aPScore[i]) - (aTScore[M]-aPScore[i]));
|
2008-10-19 18:38:23 +00:00
|
|
|
}
|
2008-09-07 08:10:56 +00:00
|
|
|
}
|
2008-10-19 18:38:23 +00:00
|
|
|
|
2010-06-06 22:08:40 +00:00
|
|
|
// move the player to the other team
|
2010-10-09 17:14:42 +00:00
|
|
|
int Temp = pP->m_LastActionTick;
|
2010-05-29 07:25:38 +00:00
|
|
|
pP->SetTeam(M^1);
|
2010-10-09 17:14:42 +00:00
|
|
|
pP->m_LastActionTick = Temp;
|
2008-10-19 18:38:23 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
pP->Respawn();
|
|
|
|
pP->m_ForceBalanced = true;
|
|
|
|
} while (--NumBalance);
|
2008-09-07 08:10:56 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
m_ForceBalanced = true;
|
2008-10-19 18:38:23 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
m_UnbalancedTick = -1;
|
2008-09-07 08:10:56 +00:00
|
|
|
}
|
2010-10-09 17:14:42 +00:00
|
|
|
|
|
|
|
// check for inactive players
|
|
|
|
if(g_Config.m_SvInactiveKickTime > 0)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < MAX_CLIENTS; ++i)
|
|
|
|
{
|
2011-01-03 11:50:38 +00:00
|
|
|
if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS && !Server()->IsAuthed(i))
|
2010-10-09 17:14:42 +00:00
|
|
|
{
|
|
|
|
if(Server()->Tick() > GameServer()->m_apPlayers[i]->m_LastActionTick+g_Config.m_SvInactiveKickTime*Server()->TickSpeed()*60)
|
|
|
|
{
|
|
|
|
switch(g_Config.m_SvInactiveKick)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
{
|
|
|
|
// move player to spectator
|
2011-01-03 11:50:38 +00:00
|
|
|
GameServer()->m_apPlayers[i]->SetTeam(TEAM_SPECTATORS);
|
2010-10-09 17:14:42 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
// move player to spectator if the reserved slots aren't filled yet, kick him otherwise
|
|
|
|
int Spectators = 0;
|
|
|
|
for(int j = 0; j < MAX_CLIENTS; ++j)
|
2011-01-03 11:50:38 +00:00
|
|
|
if(GameServer()->m_apPlayers[j] && GameServer()->m_apPlayers[j]->GetTeam() == TEAM_SPECTATORS)
|
2010-10-09 17:14:42 +00:00
|
|
|
++Spectators;
|
|
|
|
if(Spectators >= g_Config.m_SvSpectatorSlots)
|
2010-11-16 23:44:04 +00:00
|
|
|
Server()->Kick(i, "Kicked for inactivity");
|
2010-10-09 17:14:42 +00:00
|
|
|
else
|
2011-01-03 11:50:38 +00:00
|
|
|
GameServer()->m_apPlayers[i]->SetTeam(TEAM_SPECTATORS);
|
2010-10-09 17:14:42 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
// kick the player
|
|
|
|
Server()->Kick(i, "Kicked for inactivity");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-11-27 19:51:48 +00:00
|
|
|
|
|
|
|
// update browse info
|
2010-05-29 07:25:38 +00:00
|
|
|
int Prog = -1;
|
|
|
|
if(g_Config.m_SvTimelimit > 0)
|
|
|
|
Prog = max(Prog, (Server()->Tick()-m_RoundStartTick) * 100 / (g_Config.m_SvTimelimit*Server()->TickSpeed()*60));
|
2007-11-27 19:51:48 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(g_Config.m_SvScorelimit)
|
2007-11-27 19:51:48 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(IsTeamplay())
|
2007-11-27 19:51:48 +00:00
|
|
|
{
|
2011-01-03 11:50:38 +00:00
|
|
|
Prog = max(Prog, (m_aTeamscore[TEAM_RED]*100)/g_Config.m_SvScorelimit);
|
|
|
|
Prog = max(Prog, (m_aTeamscore[TEAM_BLUE]*100)/g_Config.m_SvScorelimit);
|
2007-11-27 19:51:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(GameServer()->m_apPlayers[i])
|
|
|
|
Prog = max(Prog, (GameServer()->m_apPlayers[i]->m_Score*100)/g_Config.m_SvScorelimit);
|
2007-11-27 19:51:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_Warmup)
|
|
|
|
Prog = -1;
|
2007-12-18 23:21:57 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
Server()->SetBrowseInfo(m_pGameType, Prog);
|
2007-10-05 00:05:21 +00:00
|
|
|
}
|
|
|
|
|
2008-08-31 14:37:35 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
bool IGameController::IsTeamplay() const
|
2008-08-31 14:37:35 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
return m_GameFlags&GAMEFLAG_TEAMS;
|
2008-08-31 14:37:35 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void IGameController::Snap(int SnappingClient)
|
2007-10-05 00:05:21 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetObj_Game *pGameObj = (CNetObj_Game *)Server()->SnapNewItem(NETOBJTYPE_GAME, 0, sizeof(CNetObj_Game));
|
2010-12-16 02:29:08 +00:00
|
|
|
if(!pGameObj)
|
|
|
|
return;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
pGameObj->m_Paused = GameServer()->m_World.m_Paused;
|
|
|
|
pGameObj->m_GameOver = m_GameOverTick==-1?0:1;
|
|
|
|
pGameObj->m_SuddenDeath = m_SuddenDeath;
|
2007-10-05 00:05:21 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
pGameObj->m_ScoreLimit = g_Config.m_SvScorelimit;
|
|
|
|
pGameObj->m_TimeLimit = g_Config.m_SvTimelimit;
|
|
|
|
pGameObj->m_RoundStartTick = m_RoundStartTick;
|
|
|
|
pGameObj->m_Flags = m_GameFlags;
|
2007-10-05 00:05:21 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
pGameObj->m_Warmup = m_Warmup;
|
2007-10-06 17:36:24 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
pGameObj->m_RoundNum = (str_length(g_Config.m_SvMaprotation) && g_Config.m_SvRoundsPerMap) ? g_Config.m_SvRoundsPerMap : 0;
|
|
|
|
pGameObj->m_RoundCurrent = m_RoundCount+1;
|
2008-09-07 15:07:08 +00:00
|
|
|
|
2008-10-06 18:05:01 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(SnappingClient == -1)
|
2008-10-06 18:05:01 +00:00
|
|
|
{
|
|
|
|
// we are recording a demo, just set the scores
|
2011-01-03 11:50:38 +00:00
|
|
|
pGameObj->m_TeamscoreRed = m_aTeamscore[TEAM_RED];
|
|
|
|
pGameObj->m_TeamscoreBlue = m_aTeamscore[TEAM_BLUE];
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// TODO: this little hack should be removed
|
2011-01-03 11:50:38 +00:00
|
|
|
pGameObj->m_TeamscoreRed = IsTeamplay() ? m_aTeamscore[TEAM_RED] : GameServer()->m_apPlayers[SnappingClient]->m_Score;
|
|
|
|
pGameObj->m_TeamscoreBlue = m_aTeamscore[TEAM_BLUE];
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
2007-10-05 00:05:21 +00:00
|
|
|
}
|
|
|
|
|
2011-02-12 10:40:36 +00:00
|
|
|
int IGameController::GetAutoTeam(int NotThisID)
|
2007-10-05 00:05:21 +00:00
|
|
|
{
|
2008-12-19 08:26:58 +00:00
|
|
|
// this will force the auto balancer to work overtime aswell
|
2010-05-29 07:25:38 +00:00
|
|
|
if(g_Config.m_DbgStress)
|
2008-12-19 08:26:58 +00:00
|
|
|
return 0;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int aNumplayers[2] = {0,0};
|
2007-10-05 00:05:21 +00:00
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
2011-02-12 10:40:36 +00:00
|
|
|
if(GameServer()->m_apPlayers[i] && i != NotThisID)
|
2007-10-05 00:05:21 +00:00
|
|
|
{
|
2011-01-03 11:50:38 +00:00
|
|
|
if(GameServer()->m_apPlayers[i]->GetTeam() >= TEAM_RED && GameServer()->m_apPlayers[i]->GetTeam() <= TEAM_BLUE)
|
2010-05-29 07:25:38 +00:00
|
|
|
aNumplayers[GameServer()->m_apPlayers[i]->GetTeam()]++;
|
2007-10-05 00:05:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int Team = 0;
|
|
|
|
if(IsTeamplay())
|
2011-01-03 11:50:38 +00:00
|
|
|
Team = aNumplayers[TEAM_RED] > aNumplayers[TEAM_BLUE] ? TEAM_BLUE : TEAM_RED;
|
2008-03-23 14:59:58 +00:00
|
|
|
|
2011-02-12 10:40:36 +00:00
|
|
|
if(CanJoinTeam(Team, NotThisID))
|
2010-05-29 07:25:38 +00:00
|
|
|
return Team;
|
2008-03-23 14:59:58 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-02-12 10:40:36 +00:00
|
|
|
bool IGameController::CanJoinTeam(int Team, int NotThisID)
|
2008-03-23 14:59:58 +00:00
|
|
|
{
|
2011-02-12 10:40:36 +00:00
|
|
|
if(Team == TEAM_SPECTATORS || (GameServer()->m_apPlayers[NotThisID] && GameServer()->m_apPlayers[NotThisID]->GetTeam() != TEAM_SPECTATORS))
|
2010-05-29 07:25:38 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
int aNumplayers[2] = {0,0};
|
2008-03-23 14:59:58 +00:00
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
2011-02-12 10:40:36 +00:00
|
|
|
if(GameServer()->m_apPlayers[i] && i != NotThisID)
|
2008-03-23 14:59:58 +00:00
|
|
|
{
|
2011-01-03 11:50:38 +00:00
|
|
|
if(GameServer()->m_apPlayers[i]->GetTeam() >= TEAM_RED && GameServer()->m_apPlayers[i]->GetTeam() <= TEAM_BLUE)
|
2010-05-29 07:25:38 +00:00
|
|
|
aNumplayers[GameServer()->m_apPlayers[i]->GetTeam()]++;
|
2008-03-23 14:59:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
return (aNumplayers[0] + aNumplayers[1]) < g_Config.m_SvMaxClients-g_Config.m_SvSpectatorSlots;
|
2007-10-05 00:05:21 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
bool IGameController::CheckTeamBalance()
|
2008-09-07 08:10:56 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(!IsTeamplay() || !g_Config.m_SvTeambalanceTime)
|
2008-09-07 08:10:56 +00:00
|
|
|
return true;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int aT[2] = {0, 0};
|
2008-09-07 08:10:56 +00:00
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CPlayer *pP = GameServer()->m_apPlayers[i];
|
2011-01-03 11:50:38 +00:00
|
|
|
if(pP && pP->GetTeam() != TEAM_SPECTATORS)
|
2010-05-29 07:25:38 +00:00
|
|
|
aT[pP->GetTeam()]++;
|
2008-09-07 08:10:56 +00:00
|
|
|
}
|
|
|
|
|
2010-08-17 22:06:00 +00:00
|
|
|
char aBuf[256];
|
2010-05-29 07:25:38 +00:00
|
|
|
if(absolute(aT[0]-aT[1]) >= 2)
|
2008-09-07 08:10:56 +00:00
|
|
|
{
|
2011-01-17 11:56:49 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "Teams are NOT balanced (red=%d blue=%d)", aT[0], aT[1]);
|
2010-08-17 22:06:00 +00:00
|
|
|
GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
|
2010-05-29 07:25:38 +00:00
|
|
|
if(GameServer()->m_pController->m_UnbalancedTick == -1)
|
|
|
|
GameServer()->m_pController->m_UnbalancedTick = Server()->Tick();
|
2008-09-07 08:10:56 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-01-17 11:56:49 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "Teams are balanced (red=%d blue=%d)", aT[0], aT[1]);
|
2010-08-17 22:06:00 +00:00
|
|
|
GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
|
2010-05-29 07:25:38 +00:00
|
|
|
GameServer()->m_pController->m_UnbalancedTick = -1;
|
2008-09-07 08:10:56 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
bool IGameController::CanChangeTeam(CPlayer *pPlayer, int JoinTeam)
|
2008-09-07 08:10:56 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int aT[2] = {0, 0};
|
2008-09-07 08:10:56 +00:00
|
|
|
|
2011-01-03 11:50:38 +00:00
|
|
|
if (!IsTeamplay() || JoinTeam == TEAM_SPECTATORS || !g_Config.m_SvTeambalanceTime)
|
2008-09-07 08:10:56 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CPlayer *pP = GameServer()->m_apPlayers[i];
|
2011-01-03 11:50:38 +00:00
|
|
|
if(pP && pP->GetTeam() != TEAM_SPECTATORS)
|
2010-05-29 07:25:38 +00:00
|
|
|
aT[pP->GetTeam()]++;
|
2008-09-07 08:10:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// simulate what would happen if changed team
|
2010-05-29 07:25:38 +00:00
|
|
|
aT[JoinTeam]++;
|
2011-01-03 11:50:38 +00:00
|
|
|
if (pPlayer->GetTeam() != TEAM_SPECTATORS)
|
2010-05-29 07:25:38 +00:00
|
|
|
aT[JoinTeam^1]--;
|
2008-09-07 08:10:56 +00:00
|
|
|
|
|
|
|
// there is a player-difference of at least 2
|
2010-05-29 07:25:38 +00:00
|
|
|
if(absolute(aT[0]-aT[1]) >= 2)
|
2008-09-07 08:10:56 +00:00
|
|
|
{
|
|
|
|
// player wants to join team with less players
|
2011-01-03 11:50:38 +00:00
|
|
|
if ((aT[0] < aT[1] && JoinTeam == TEAM_RED) || (aT[0] > aT[1] && JoinTeam == TEAM_BLUE))
|
2008-09-07 08:10:56 +00:00
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void IGameController::DoPlayerScoreWincheck()
|
2008-01-17 23:09:49 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_GameOverTick == -1 && !m_Warmup)
|
2008-01-17 23:09:49 +00:00
|
|
|
{
|
|
|
|
// gather some stats
|
2010-05-29 07:25:38 +00:00
|
|
|
int Topscore = 0;
|
|
|
|
int TopscoreCount = 0;
|
2008-01-17 23:09:49 +00:00
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(GameServer()->m_apPlayers[i])
|
2008-01-17 23:09:49 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(GameServer()->m_apPlayers[i]->m_Score > Topscore)
|
2008-01-17 23:09:49 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Topscore = GameServer()->m_apPlayers[i]->m_Score;
|
|
|
|
TopscoreCount = 1;
|
2008-01-17 23:09:49 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(GameServer()->m_apPlayers[i]->m_Score == Topscore)
|
|
|
|
TopscoreCount++;
|
2008-01-17 23:09:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// check score win condition
|
2010-05-29 07:25:38 +00:00
|
|
|
if((g_Config.m_SvScorelimit > 0 && Topscore >= g_Config.m_SvScorelimit) ||
|
|
|
|
(g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60))
|
2008-01-17 23:09:49 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(TopscoreCount == 1)
|
|
|
|
EndRound();
|
2008-01-17 23:09:49 +00:00
|
|
|
else
|
2010-05-29 07:25:38 +00:00
|
|
|
m_SuddenDeath = 1;
|
2008-01-17 23:09:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void IGameController::DoTeamScoreWincheck()
|
2007-11-26 20:47:49 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_GameOverTick == -1 && !m_Warmup)
|
2007-11-26 20:47:49 +00:00
|
|
|
{
|
|
|
|
// check score win condition
|
2011-01-03 11:50:38 +00:00
|
|
|
if((g_Config.m_SvScorelimit > 0 && (m_aTeamscore[TEAM_RED] >= g_Config.m_SvScorelimit || m_aTeamscore[TEAM_BLUE] >= g_Config.m_SvScorelimit)) ||
|
2010-05-29 07:25:38 +00:00
|
|
|
(g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60))
|
2007-11-26 20:47:49 +00:00
|
|
|
{
|
2011-01-03 11:50:38 +00:00
|
|
|
if(m_aTeamscore[TEAM_RED] != m_aTeamscore[TEAM_BLUE])
|
2010-05-29 07:25:38 +00:00
|
|
|
EndRound();
|
2007-11-26 20:47:49 +00:00
|
|
|
else
|
2010-05-29 07:25:38 +00:00
|
|
|
m_SuddenDeath = 1;
|
2007-11-26 20:47:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int IGameController::ClampTeam(int Team)
|
2007-12-18 23:21:57 +00:00
|
|
|
{
|
2011-01-03 11:50:38 +00:00
|
|
|
if(Team < 0)
|
|
|
|
return TEAM_SPECTATORS;
|
2010-05-29 07:25:38 +00:00
|
|
|
if(IsTeamplay())
|
|
|
|
return Team&1;
|
2011-01-03 11:50:38 +00:00
|
|
|
return 0;
|
2007-12-18 23:21:57 +00:00
|
|
|
}
|