cleaned up gamecontroller

This commit is contained in:
oy 2012-02-15 01:39:13 +01:00
parent b32aff7d89
commit 5e4caa9b9c
15 changed files with 754 additions and 773 deletions

View file

@ -23,6 +23,7 @@ enum
TEAM_SPECTATORS=-1, TEAM_SPECTATORS=-1,
TEAM_RED, TEAM_RED,
TEAM_BLUE, TEAM_BLUE,
NUM_TEAMS,
FLAG_MISSING=-3, FLAG_MISSING=-3,
FLAG_ATSTAND, FLAG_ATSTAND,

View file

@ -544,15 +544,6 @@ void CCharacter::ResetInput()
void CCharacter::Tick() void CCharacter::Tick()
{ {
if(m_pPlayer->m_ForceBalanced)
{
char Buf[128];
str_format(Buf, sizeof(Buf), "You were moved to %s due to team balancing", GameServer()->m_pController->GetTeamName(m_pPlayer->GetTeam()));
GameServer()->SendBroadcast(Buf, m_pPlayer->GetCID());
m_pPlayer->m_ForceBalanced = false;
}
m_Core.m_Input = m_Input; m_Core.m_Input = m_Input;
m_Core.Tick(true); m_Core.Tick(true);
@ -723,7 +714,7 @@ bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon)
{ {
m_Core.m_Vel += Force; m_Core.m_Vel += Force;
if(GameServer()->m_pController->IsFriendlyFire(m_pPlayer->GetCID(), From) && !g_Config.m_SvTeamdamage) if(GameServer()->m_pController->IsFriendlyFire(m_pPlayer->GetCID(), From))
return false; return false;
// m_pPlayer only inflicts half damage on self // m_pPlayer only inflicts half damage on self

View file

@ -364,9 +364,9 @@ void CGameContext::CheckPureTuning()
if(!m_pController) if(!m_pController)
return; return;
if( str_comp(m_pController->m_pGameType, "DM")==0 || if( str_comp(m_pController->GetGameType(), "DM")==0 ||
str_comp(m_pController->m_pGameType, "TDM")==0 || str_comp(m_pController->GetGameType(), "TDM")==0 ||
str_comp(m_pController->m_pGameType, "CTF")==0) str_comp(m_pController->GetGameType(), "CTF")==0)
{ {
CTuningParams p; CTuningParams p;
if(mem_comp(&p, &m_Tuning, sizeof(p)) != 0) if(mem_comp(&p, &m_Tuning, sizeof(p)) != 0)
@ -398,10 +398,8 @@ void CGameContext::SwapTeams()
for(int i = 0; i < MAX_CLIENTS; ++i) 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]->GetTeam() != TEAM_SPECTATORS)
m_apPlayers[i]->SetTeam(m_apPlayers[i]->GetTeam()^1, false); m_pController->DoTeamChange(m_apPlayers[i], m_apPlayers[i]->GetTeam()^1, false);
} }
(void)m_pController->CheckTeamBalance();
} }
void CGameContext::OnTick() void CGameContext::OnTick()
@ -506,13 +504,13 @@ void CGameContext::OnTick()
#ifdef CONF_DEBUG #ifdef CONF_DEBUG
if(g_Config.m_DbgDummies) for(int i = 0; i < MAX_CLIENTS; i++)
{ {
for(int i = 0; i < g_Config.m_DbgDummies ; i++) if(m_apPlayers[i] && m_apPlayers[i]->IsDummy())
{ {
CNetObj_PlayerInput Input = {0}; CNetObj_PlayerInput Input = {0};
Input.m_Direction = (i&1)?-1:1; Input.m_Direction = (i&1)?-1:1;
m_apPlayers[MAX_CLIENTS-i-1]->OnPredictedInput(&Input); m_apPlayers[i]->OnPredictedInput(&Input);
} }
} }
#endif #endif
@ -545,24 +543,12 @@ void CGameContext::OnClientEnter(int ClientID)
m_VoteUpdate = true; m_VoteUpdate = true;
} }
void CGameContext::OnClientConnected(int ClientID) void CGameContext::OnClientConnected(int ClientID, bool Dummy)
{ {
// Check which team the player should be on m_apPlayers[ClientID] = new(ClientID) CPlayer(this, ClientID, Dummy);
const int StartTeam = g_Config.m_SvTournamentMode ? TEAM_SPECTATORS : m_pController->GetAutoTeam(ClientID);
m_apPlayers[ClientID] = new(ClientID) CPlayer(this, ClientID, StartTeam); if(Dummy)
//players[client_id].init(client_id); return;
//players[client_id].client_id = client_id;
(void)m_pController->CheckTeamBalance();
#ifdef CONF_DEBUG
if(g_Config.m_DbgDummies)
{
if(ClientID >= MAX_CLIENTS-g_Config.m_DbgDummies)
return;
}
#endif
// send active vote // send active vote
if(m_VoteCloseTime) if(m_VoteCloseTime)
@ -577,11 +563,10 @@ void CGameContext::OnClientConnected(int ClientID)
void CGameContext::OnClientDrop(int ClientID, const char *pReason) void CGameContext::OnClientDrop(int ClientID, const char *pReason)
{ {
AbortVoteKickOnDisconnect(ClientID); AbortVoteKickOnDisconnect(ClientID);
m_apPlayers[ClientID]->OnDisconnect(pReason); m_pController->OnPlayerDisconnect(m_apPlayers[ClientID], pReason);
delete m_apPlayers[ClientID]; delete m_apPlayers[ClientID];
m_apPlayers[ClientID] = 0; m_apPlayers[ClientID] = 0;
(void)m_pController->CheckTeamBalance();
m_VoteUpdate = true; m_VoteUpdate = true;
// update spectator modes // update spectator modes
@ -825,8 +810,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
pPlayer->m_LastSetTeam = Server()->Tick(); pPlayer->m_LastSetTeam = Server()->Tick();
if(pPlayer->GetTeam() == TEAM_SPECTATORS || pMsg->m_Team == TEAM_SPECTATORS) if(pPlayer->GetTeam() == TEAM_SPECTATORS || pMsg->m_Team == TEAM_SPECTATORS)
m_VoteUpdate = true; m_VoteUpdate = true;
pPlayer->SetTeam(pMsg->m_Team); m_pController->DoTeamChange(pPlayer, pMsg->m_Team);
(void)m_pController->CheckTeamBalance();
pPlayer->m_TeamChangeTick = Server()->Tick(); pPlayer->m_TeamChangeTick = Server()->Tick();
} }
else else
@ -1088,8 +1072,7 @@ void CGameContext::ConSetTeam(IConsole::IResult *pResult, void *pUserData)
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
pSelf->m_apPlayers[ClientID]->m_TeamChangeTick = pSelf->Server()->Tick()+pSelf->Server()->TickSpeed()*Delay*60; pSelf->m_apPlayers[ClientID]->m_TeamChangeTick = pSelf->Server()->Tick()+pSelf->Server()->TickSpeed()*Delay*60;
pSelf->m_apPlayers[ClientID]->SetTeam(Team); pSelf->m_pController->DoTeamChange(pSelf->m_apPlayers[ClientID], Team);
(void)pSelf->m_pController->CheckTeamBalance();
} }
void CGameContext::ConSetTeamAll(IConsole::IResult *pResult, void *pUserData) void CGameContext::ConSetTeamAll(IConsole::IResult *pResult, void *pUserData)
@ -1103,9 +1086,7 @@ void CGameContext::ConSetTeamAll(IConsole::IResult *pResult, void *pUserData)
for(int i = 0; i < MAX_CLIENTS; ++i) for(int i = 0; i < MAX_CLIENTS; ++i)
if(pSelf->m_apPlayers[i]) if(pSelf->m_apPlayers[i])
pSelf->m_apPlayers[i]->SetTeam(Team, false); pSelf->m_pController->DoTeamChange(pSelf->m_apPlayers[i], Team, false);
(void)pSelf->m_pController->CheckTeamBalance();
} }
void CGameContext::ConSwapTeams(IConsole::IResult *pResult, void *pUserData) void CGameContext::ConSwapTeams(IConsole::IResult *pResult, void *pUserData)
@ -1135,26 +1116,24 @@ void CGameContext::ConShuffleTeams(IConsole::IResult *pResult, void *pUserData)
if(pSelf->m_apPlayers[i] && pSelf->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS) if(pSelf->m_apPlayers[i] && pSelf->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
{ {
if(CounterRed == PlayerTeam) if(CounterRed == PlayerTeam)
pSelf->m_apPlayers[i]->SetTeam(TEAM_BLUE, false); pSelf->m_pController->DoTeamChange(pSelf->m_apPlayers[i], TEAM_BLUE, false);
else if(CounterBlue == PlayerTeam) else if(CounterBlue == PlayerTeam)
pSelf->m_apPlayers[i]->SetTeam(TEAM_RED, false); pSelf->m_pController->DoTeamChange(pSelf->m_apPlayers[i], TEAM_RED, false);
else else
{ {
if(rand() % 2) if(rand() % 2)
{ {
pSelf->m_apPlayers[i]->SetTeam(TEAM_BLUE, false); pSelf->m_pController->DoTeamChange(pSelf->m_apPlayers[i], TEAM_BLUE, false);
++CounterBlue; ++CounterBlue;
} }
else else
{ {
pSelf->m_apPlayers[i]->SetTeam(TEAM_RED, false); pSelf->m_pController->DoTeamChange(pSelf->m_apPlayers[i], TEAM_RED, false);
++CounterRed; ++CounterRed;
} }
} }
} }
} }
(void)pSelf->m_pController->CheckTeamBalance();
} }
void CGameContext::ConLockTeams(IConsole::IResult *pResult, void *pUserData) void CGameContext::ConLockTeams(IConsole::IResult *pResult, void *pUserData)
@ -1445,26 +1424,20 @@ void CGameContext::OnConsoleInit()
Console()->Chain("sv_motd", ConchainSpecialMotdupdate, this); Console()->Chain("sv_motd", ConchainSpecialMotdupdate, this);
} }
void CGameContext::OnInit(/*class IKernel *pKernel*/) void CGameContext::OnInit()
{ {
// init everything
m_pServer = Kernel()->RequestInterface<IServer>(); m_pServer = Kernel()->RequestInterface<IServer>();
m_pConsole = Kernel()->RequestInterface<IConsole>(); m_pConsole = Kernel()->RequestInterface<IConsole>();
m_World.SetGameServer(this); m_World.SetGameServer(this);
m_Events.SetGameServer(this); m_Events.SetGameServer(this);
//if(!data) // only load once
//data = load_data_from_memory(internal_data);
for(int i = 0; i < NUM_NETOBJTYPES; i++) for(int i = 0; i < NUM_NETOBJTYPES; i++)
Server()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i)); Server()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i));
m_Layers.Init(Kernel()); m_Layers.Init(Kernel());
m_Collision.Init(&m_Layers); m_Collision.Init(&m_Layers);
// reset everything here
//world = new GAMEWORLD;
//players = new CPlayer[MAX_CLIENTS];
// select gametype // select gametype
if(str_comp(g_Config.m_SvGametype, "mod") == 0) if(str_comp(g_Config.m_SvGametype, "mod") == 0)
m_pController = new CGameControllerMOD(this); m_pController = new CGameControllerMOD(this);
@ -1475,23 +1448,9 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/)
else else
m_pController = new CGameControllerDM(this); m_pController = new CGameControllerDM(this);
// setup core world
//for(int i = 0; i < MAX_CLIENTS; i++)
// game.players[i].core.world = &game.world.core;
// create all entities from the game layer // create all entities from the game layer
CMapItemLayerTilemap *pTileMap = m_Layers.GameLayer(); CMapItemLayerTilemap *pTileMap = m_Layers.GameLayer();
CTile *pTiles = (CTile *)Kernel()->RequestInterface<IMap>()->GetData(pTileMap->m_Data); CTile *pTiles = (CTile *)Kernel()->RequestInterface<IMap>()->GetData(pTileMap->m_Data);
/*
num_spawn_points[0] = 0;
num_spawn_points[1] = 0;
num_spawn_points[2] = 0;
*/
for(int y = 0; y < pTileMap->m_Height; y++) for(int y = 0; y < pTileMap->m_Height; y++)
{ {
for(int x = 0; x < pTileMap->m_Width; x++) for(int x = 0; x < pTileMap->m_Width; x++)
@ -1506,15 +1465,11 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/)
} }
} }
//game.world.insert_entity(game.Controller);
#ifdef CONF_DEBUG #ifdef CONF_DEBUG
if(g_Config.m_DbgDummies) if(g_Config.m_DbgDummies)
{ {
for(int i = 0; i < g_Config.m_DbgDummies ; i++) for(int i = 0; i < g_Config.m_DbgDummies ; i++)
{ OnClientConnected(MAX_CLIENTS-i-1, true);
OnClientConnected(MAX_CLIENTS-i-1);
}
} }
#endif #endif
} }
@ -1565,7 +1520,7 @@ bool CGameContext::IsClientPlayer(int ClientID)
return m_apPlayers[ClientID] && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS ? false : true; return m_apPlayers[ClientID] && m_apPlayers[ClientID]->GetTeam() == TEAM_SPECTATORS ? false : true;
} }
const char *CGameContext::GameType() { return m_pController && m_pController->m_pGameType ? m_pController->m_pGameType : ""; } const char *CGameContext::GameType() { return m_pController && m_pController->GetGameType() ? m_pController->GetGameType() : ""; }
const char *CGameContext::Version() { return GAME_VERSION; } const char *CGameContext::Version() { return GAME_VERSION; }
const char *CGameContext::NetVersion() { return GAME_NETVERSION; } const char *CGameContext::NetVersion() { return GAME_NETVERSION; }

View file

@ -162,7 +162,8 @@ public:
virtual void OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID); virtual void OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID);
virtual void OnClientConnected(int ClientID); virtual void OnClientConnected(int ClientID) { OnClientConnected(ClientID, false); }
void OnClientConnected(int ClientID, bool Dummy);
virtual void OnClientEnter(int ClientID); virtual void OnClientEnter(int ClientID);
virtual void OnClientDrop(int ClientID, const char *pReason); virtual void OnClientDrop(int ClientID, const char *pReason);
virtual void OnClientDirectInput(int ClientID, void *pInput); virtual void OnClientDirectInput(int ClientID, void *pInput);

File diff suppressed because it is too large Load diff

View file

@ -4,6 +4,7 @@
#define GAME_SERVER_GAMECONTROLLER_H #define GAME_SERVER_GAMECONTROLLER_H
#include <base/vmath.h> #include <base/vmath.h>
#include <game/generated/protocol.h>
/* /*
Class: Game Controller Class: Game Controller
@ -12,16 +13,33 @@
*/ */
class IGameController class IGameController
{ {
vec2 m_aaSpawnPoints[3][64];
int m_aNumSpawnPoints[3];
class CGameContext *m_pGameServer; class CGameContext *m_pGameServer;
class IServer *m_pServer; class IServer *m_pServer;
protected: // activity
CGameContext *GameServer() const { return m_pGameServer; } void DoActivityCheck();
IServer *Server() const { return m_pServer; }
// balancing
enum
{
TBALANCE_CHECK=-2,
TBALANCE_OK,
};
int m_UnbalancedTick;
virtual bool CanBeMovedOnBalance(int ClientID) const;
void CheckTeamBalance();
void DoTeamBalance();
// game
virtual void DoWincheck();
// map
char m_aMapWish[128];
void CycleMap();
// spawn
struct CSpawnEval struct CSpawnEval
{ {
CSpawnEval() CSpawnEval()
@ -36,59 +54,58 @@ protected:
int m_FriendlyTeam; int m_FriendlyTeam;
float m_Score; float m_Score;
}; };
vec2 m_aaSpawnPoints[3][64];
int m_aNumSpawnPoints[3];
float EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos); float EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos) const;
void EvaluateSpawnType(CSpawnEval *pEval, int Type); void EvaluateSpawnType(CSpawnEval *pEval, int Type) const;
bool EvaluateSpawn(class CPlayer *pP, vec2 *pPos);
void CycleMap(); // team
int ClampTeam(int Team) const;
protected:
CGameContext *GameServer() const { return m_pGameServer; }
IServer *Server() const { return m_pServer; }
// game
int m_GameOverTick;
int m_RoundCount;
int m_RoundStartTick;
int m_SuddenDeath;
int m_aTeamscore[NUM_TEAMS];
int m_Warmup;
void EndRound();
void ResetGame(); void ResetGame();
char m_aMapWish[128]; // info
int m_RoundStartTick;
int m_GameOverTick;
int m_SuddenDeath;
int m_aTeamscore[2];
int m_Warmup;
int m_RoundCount;
int m_GameFlags; int m_GameFlags;
int m_UnbalancedTick;
bool m_ForceBalanced;
public:
const char *m_pGameType; const char *m_pGameType;
bool IsTeamplay() const; public:
bool IsGameOver() const { return m_GameOverTick != -1; }
IGameController(class CGameContext *pGameServer); IGameController(class CGameContext *pGameServer);
virtual ~IGameController(); virtual ~IGameController() {};
virtual void DoWincheck();
void DoWarmup(int Seconds);
void StartRound();
void EndRound();
void ChangeMap(const char *pToMap);
bool IsFriendlyFire(int ClientID1, int ClientID2);
bool IsForceBalanced();
// event
/* /*
Function: on_CCharacter_death
Called when a CCharacter in the world dies.
Arguments:
victim - The CCharacter that died.
killer - The player that killed it.
weapon - What weapon that killed it. Can be -1 for undefined
weapon when switching team or player suicides.
*/ */
virtual bool CanBeMovedOnBalance(int ClientID); virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon);
/*
Function: on_CCharacter_spawn
Called when a CCharacter spawns into the game world.
virtual void Tick(); Arguments:
chr - The CCharacter that was spawned.
virtual void Snap(int SnappingClient); */
virtual void OnCharacterSpawn(class CCharacter *pChr);
/* /*
Function: on_entity Function: on_entity
@ -104,44 +121,41 @@ public:
*/ */
virtual bool OnEntity(int Index, vec2 Pos); virtual bool OnEntity(int Index, vec2 Pos);
/* void OnPlayerDisconnect(class CPlayer *pPlayer, const char *pReason);
Function: on_CCharacter_spawn void OnPlayerInfoChange(class CPlayer *pPlayer);
Called when a CCharacter spawns into the game world.
Arguments: void OnReset();
chr - The CCharacter that was spawned.
*/
virtual void OnCharacterSpawn(class CCharacter *pChr);
/* // game
Function: on_CCharacter_death void DoWarmup(int Seconds);
Called when a CCharacter in the world dies.
Arguments: void StartRound();
victim - The CCharacter that died.
killer - The player that killed it.
weapon - What weapon that killed it. Can be -1 for undefined
weapon when switching team or player suicides.
*/
virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon);
// general
virtual void Snap(int SnappingClient);
virtual void Tick();
virtual void OnPlayerInfoChange(class CPlayer *pP); // info
bool IsFriendlyFire(int ClientID1, int ClientID2) const;
bool IsGameOver() const { return m_GameOverTick != -1; }
bool IsTeamplay() const { return m_GameFlags&GAMEFLAG_TEAMS; }
// const char *GetGameType() const { return m_pGameType; }
virtual bool CanSpawn(int Team, vec2 *pPos); const char *GetTeamName(int Team) const;
/* // map
void ChangeMap(const char *pToMap);
*/ //spawn
virtual const char *GetTeamName(int Team); bool CanSpawn(int Team, vec2 *pPos) const;
virtual int GetAutoTeam(int NotThisID);
virtual bool CanJoinTeam(int Team, int NotThisID);
bool CheckTeamBalance();
bool CanChangeTeam(CPlayer *pPplayer, int JoinTeam);
int ClampTeam(int Team);
virtual void PostReset(); // team
bool CanJoinTeam(int Team, int NotThisID) const;
bool CanChangeTeam(CPlayer *pPplayer, int JoinTeam) const;
void DoTeamChange(class CPlayer *pPlayer, int Team, bool DoChatMsg=true);
int GetStartTeam(int NotThisID);
}; };
#endif #endif

View file

@ -10,35 +10,34 @@
#include <game/server/gamecontext.h> #include <game/server/gamecontext.h>
#include "ctf.h" #include "ctf.h"
CGameControllerCTF::CGameControllerCTF(class CGameContext *pGameServer) CGameControllerCTF::CGameControllerCTF(CGameContext *pGameServer)
: IGameController(pGameServer) : IGameController(pGameServer)
{ {
// game
m_apFlags[0] = 0; m_apFlags[0] = 0;
m_apFlags[1] = 0; m_apFlags[1] = 0;
m_pGameType = "CTF"; m_pGameType = "CTF";
m_GameFlags = GAMEFLAG_TEAMS|GAMEFLAG_FLAGS; m_GameFlags = GAMEFLAG_TEAMS|GAMEFLAG_FLAGS;
} }
bool CGameControllerCTF::OnEntity(int Index, vec2 Pos) // balancing
bool CGameControllerCTF::CanBeMovedOnBalance(int ClientID)
{ {
if(IGameController::OnEntity(Index, Pos)) CCharacter* Character = GameServer()->m_apPlayers[ClientID]->GetCharacter();
return true; if(Character)
{
int Team = -1; for(int fi = 0; fi < 2; fi++)
if(Index == ENTITY_FLAGSTAND_RED) Team = TEAM_RED; {
if(Index == ENTITY_FLAGSTAND_BLUE) Team = TEAM_BLUE; CFlag *F = m_apFlags[fi];
if(Team == -1 || m_apFlags[Team]) if(F->m_pCarryingCharacter == Character)
return false; return false;
}
CFlag *F = new CFlag(&GameServer()->m_World, Team); }
F->m_StandPos = Pos;
F->m_Pos = Pos;
m_apFlags[Team] = F;
GameServer()->m_World.InsertEntity(F);
return true; return true;
} }
int CGameControllerCTF::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int WeaponID) // event
int CGameControllerCTF::OnCharacterDeath(CCharacter *pVictim, CPlayer *pKiller, int WeaponID)
{ {
IGameController::OnCharacterDeath(pVictim, pKiller, WeaponID); IGameController::OnCharacterDeath(pVictim, pKiller, WeaponID);
int HadFlag = 0; int HadFlag = 0;
@ -66,45 +65,48 @@ int CGameControllerCTF::OnCharacterDeath(class CCharacter *pVictim, class CPlaye
return HadFlag; return HadFlag;
} }
void CGameControllerCTF::DoWincheck() bool CGameControllerCTF::OnEntity(int Index, vec2 Pos)
{ {
if(m_GameOverTick == -1 && !m_Warmup) if(IGameController::OnEntity(Index, Pos))
{ return true;
// check score win condition
if((g_Config.m_SvScorelimit > 0 && (m_aTeamscore[TEAM_RED] >= g_Config.m_SvScorelimit || m_aTeamscore[TEAM_BLUE] >= g_Config.m_SvScorelimit)) ||
(g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60))
{
if(m_SuddenDeath)
{
if(m_aTeamscore[TEAM_RED]/100 != m_aTeamscore[TEAM_BLUE]/100)
EndRound();
}
else
{
if(m_aTeamscore[TEAM_RED] != m_aTeamscore[TEAM_BLUE])
EndRound();
else
m_SuddenDeath = 1;
}
}
}
}
bool CGameControllerCTF::CanBeMovedOnBalance(int ClientID) int Team = -1;
{ if(Index == ENTITY_FLAGSTAND_RED) Team = TEAM_RED;
CCharacter* Character = GameServer()->m_apPlayers[ClientID]->GetCharacter(); if(Index == ENTITY_FLAGSTAND_BLUE) Team = TEAM_BLUE;
if(Character) if(Team == -1 || m_apFlags[Team])
{ return false;
for(int fi = 0; fi < 2; fi++)
{ CFlag *F = new CFlag(&GameServer()->m_World, Team);
CFlag *F = m_apFlags[fi]; F->m_StandPos = Pos;
if(F->m_pCarryingCharacter == Character) F->m_Pos = Pos;
return false; m_apFlags[Team] = F;
} GameServer()->m_World.InsertEntity(F);
}
return true; return true;
} }
// game
void CGameControllerCTF::DoWincheck()
{
// check score win condition
if((g_Config.m_SvScorelimit > 0 && (m_aTeamscore[TEAM_RED] >= g_Config.m_SvScorelimit || m_aTeamscore[TEAM_BLUE] >= g_Config.m_SvScorelimit)) ||
(g_Config.m_SvTimelimit > 0 && (Server()->Tick()-m_RoundStartTick) >= g_Config.m_SvTimelimit*Server()->TickSpeed()*60))
{
if(m_SuddenDeath)
{
if(m_aTeamscore[TEAM_RED]/100 != m_aTeamscore[TEAM_BLUE]/100)
EndRound();
}
else
{
if(m_aTeamscore[TEAM_RED] != m_aTeamscore[TEAM_BLUE])
EndRound();
else
m_SuddenDeath = 1;
}
}
}
// general
void CGameControllerCTF::Snap(int SnappingClient) void CGameControllerCTF::Snap(int SnappingClient)
{ {
IGameController::Snap(SnappingClient); IGameController::Snap(SnappingClient);

View file

@ -7,17 +7,24 @@
class CGameControllerCTF : public IGameController class CGameControllerCTF : public IGameController
{ {
public: // balancing
virtual bool CanBeMovedOnBalance(int ClientID);
// game
class CFlag *m_apFlags[2]; class CFlag *m_apFlags[2];
CGameControllerCTF(class CGameContext *pGameServer);
virtual void DoWincheck(); virtual void DoWincheck();
virtual bool CanBeMovedOnBalance(int ClientID);
public:
CGameControllerCTF(class CGameContext *pGameServer);
// event
virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon);
virtual bool OnEntity(int Index, vec2 Pos);
// general
virtual void Snap(int SnappingClient); virtual void Snap(int SnappingClient);
virtual void Tick(); virtual void Tick();
virtual bool OnEntity(int Index, vec2 Pos);
virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon);
}; };
#endif #endif

View file

@ -3,13 +3,8 @@
#include "dm.h" #include "dm.h"
CGameControllerDM::CGameControllerDM(class CGameContext *pGameServer) CGameControllerDM::CGameControllerDM(CGameContext *pGameServer)
: IGameController(pGameServer) : IGameController(pGameServer)
{ {
m_pGameType = "DM"; m_pGameType = "DM";
} }
void CGameControllerDM::Tick()
{
IGameController::Tick();
}

View file

@ -8,6 +8,6 @@ class CGameControllerDM : public IGameController
{ {
public: public:
CGameControllerDM(class CGameContext *pGameServer); CGameControllerDM(class CGameContext *pGameServer);
virtual void Tick();
}; };
#endif #endif

View file

@ -12,6 +12,7 @@ CGameControllerTDM::CGameControllerTDM(class CGameContext *pGameServer) : IGameC
m_GameFlags = GAMEFLAG_TEAMS; m_GameFlags = GAMEFLAG_TEAMS;
} }
// event
int CGameControllerTDM::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon) int CGameControllerTDM::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon)
{ {
IGameController::OnCharacterDeath(pVictim, pKiller, Weapon); IGameController::OnCharacterDeath(pVictim, pKiller, Weapon);
@ -31,6 +32,7 @@ int CGameControllerTDM::OnCharacterDeath(class CCharacter *pVictim, class CPlaye
return 0; return 0;
} }
// general
void CGameControllerTDM::Snap(int SnappingClient) void CGameControllerTDM::Snap(int SnappingClient)
{ {
IGameController::Snap(SnappingClient); IGameController::Snap(SnappingClient);
@ -45,8 +47,3 @@ void CGameControllerTDM::Snap(int SnappingClient)
pGameDataObj->m_FlagCarrierRed = 0; pGameDataObj->m_FlagCarrierRed = 0;
pGameDataObj->m_FlagCarrierBlue = 0; pGameDataObj->m_FlagCarrierBlue = 0;
} }
void CGameControllerTDM::Tick()
{
IGameController::Tick();
}

View file

@ -9,8 +9,11 @@ class CGameControllerTDM : public IGameController
public: public:
CGameControllerTDM(class CGameContext *pGameServer); CGameControllerTDM(class CGameContext *pGameServer);
int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon); // event
virtual int OnCharacterDeath(class CCharacter *pVictim, class CPlayer *pKiller, int Weapon);
// general
virtual void Snap(int SnappingClient); virtual void Snap(int SnappingClient);
virtual void Tick();
}; };
#endif #endif

View file

@ -125,7 +125,7 @@ void CGameWorld::Reset()
} }
RemoveEntities(); RemoveEntities();
GameServer()->m_pController->PostReset(); GameServer()->m_pController->OnReset();
RemoveEntities(); RemoveEntities();
m_ResetRequested = false; m_ResetRequested = false;
@ -154,8 +154,6 @@ void CGameWorld::Tick()
if(!m_Paused) if(!m_Paused)
{ {
if(GameServer()->m_pController->IsForceBalanced())
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Teams have been balanced");
// update all objects // update all objects
for(int i = 0; i < NUM_ENTTYPES; i++) for(int i = 0; i < NUM_ENTTYPES; i++)
for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; ) for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; )

View file

@ -9,7 +9,7 @@ MACRO_ALLOC_POOL_ID_IMPL(CPlayer, MAX_CLIENTS)
IServer *CPlayer::Server() const { return m_pGameServer->Server(); } IServer *CPlayer::Server() const { return m_pGameServer->Server(); }
CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, int Team) CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, bool Dummy)
{ {
m_pGameServer = pGameServer; m_pGameServer = pGameServer;
m_RespawnTick = Server()->Tick(); m_RespawnTick = Server()->Tick();
@ -17,10 +17,11 @@ CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, int Team)
m_ScoreStartTick = Server()->Tick(); m_ScoreStartTick = Server()->Tick();
m_pCharacter = 0; m_pCharacter = 0;
m_ClientID = ClientID; m_ClientID = ClientID;
m_Team = GameServer()->m_pController->ClampTeam(Team); m_Team = GameServer()->m_pController->GetStartTeam(ClientID);
m_SpectatorID = SPEC_FREEVIEW; m_SpectatorID = SPEC_FREEVIEW;
m_LastActionTick = Server()->Tick(); m_LastActionTick = Server()->Tick();
m_TeamChangeTick = Server()->Tick(); m_TeamChangeTick = Server()->Tick();
m_Dummy = Dummy;
} }
CPlayer::~CPlayer() CPlayer::~CPlayer()
@ -31,10 +32,7 @@ CPlayer::~CPlayer()
void CPlayer::Tick() void CPlayer::Tick()
{ {
#ifdef CONF_DEBUG if(!IsDummy() && !Server()->ClientIngame(m_ClientID))
if(!g_Config.m_DbgDummies || m_ClientID < MAX_CLIENTS-g_Config.m_DbgDummies)
#endif
if(!Server()->ClientIngame(m_ClientID))
return; return;
Server()->SetClientScore(m_ClientID, m_Score); Server()->SetClientScore(m_ClientID, m_Score);
@ -112,10 +110,7 @@ void CPlayer::PostTick()
void CPlayer::Snap(int SnappingClient) void CPlayer::Snap(int SnappingClient)
{ {
#ifdef CONF_DEBUG if(!IsDummy() && !Server()->ClientIngame(m_ClientID))
if(!g_Config.m_DbgDummies || m_ClientID < MAX_CLIENTS-g_Config.m_DbgDummies)
#endif
if(!Server()->ClientIngame(m_ClientID))
return; return;
CNetObj_ClientInfo *pClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, m_ClientID, sizeof(CNetObj_ClientInfo))); CNetObj_ClientInfo *pClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, m_ClientID, sizeof(CNetObj_ClientInfo)));
@ -155,22 +150,9 @@ void CPlayer::Snap(int SnappingClient)
} }
} }
void CPlayer::OnDisconnect(const char *pReason) void CPlayer::OnDisconnect()
{ {
KillCharacter(); KillCharacter();
if(Server()->ClientIngame(m_ClientID))
{
char aBuf[512];
if(pReason && *pReason)
str_format(aBuf, sizeof(aBuf), "'%s' has left the game (%s)", Server()->ClientName(m_ClientID), pReason);
else
str_format(aBuf, sizeof(aBuf), "'%s' has left the game", Server()->ClientName(m_ClientID));
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
str_format(aBuf, sizeof(aBuf), "leave player='%d:%s'", m_ClientID, Server()->ClientName(m_ClientID));
GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "game", aBuf);
}
} }
void CPlayer::OnPredictedInput(CNetObj_PlayerInput *NewInput) void CPlayer::OnPredictedInput(CNetObj_PlayerInput *NewInput)
@ -243,28 +225,13 @@ void CPlayer::Respawn()
void CPlayer::SetTeam(int Team, bool DoChatMsg) void CPlayer::SetTeam(int Team, bool DoChatMsg)
{ {
// clamp the team
Team = GameServer()->m_pController->ClampTeam(Team);
if(m_Team == Team)
return;
char aBuf[512];
if(DoChatMsg)
{
str_format(aBuf, sizeof(aBuf), "'%s' joined the %s", Server()->ClientName(m_ClientID), GameServer()->m_pController->GetTeamName(Team));
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
}
KillCharacter(); KillCharacter();
m_Team = Team; m_Team = Team;
m_LastActionTick = Server()->Tick(); m_LastActionTick = Server()->Tick();
// we got to wait 0.5 secs before respawning // we got to wait 0.5 secs before respawning
m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2; m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' m_Team=%d", m_ClientID, Server()->ClientName(m_ClientID), m_Team);
GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
GameServer()->m_pController->OnPlayerInfoChange(GameServer()->m_apPlayers[m_ClientID]);
if(Team == TEAM_SPECTATORS) if(Team == TEAM_SPECTATORS)
{ {

View file

@ -13,7 +13,7 @@ class CPlayer
MACRO_ALLOC_POOL_ID() MACRO_ALLOC_POOL_ID()
public: public:
CPlayer(CGameContext *pGameServer, int ClientID, int Team); CPlayer(CGameContext *pGameServer, int ClientID, bool Dummy);
~CPlayer(); ~CPlayer();
void Init(int CID); void Init(int CID);
@ -23,6 +23,7 @@ public:
void SetTeam(int Team, bool DoChatMsg=true); void SetTeam(int Team, bool DoChatMsg=true);
int GetTeam() const { return m_Team; }; int GetTeam() const { return m_Team; };
int GetCID() const { return m_ClientID; }; int GetCID() const { return m_ClientID; };
bool IsDummy() const { return m_Dummy; }
void Tick(); void Tick();
void PostTick(); void PostTick();
@ -30,7 +31,7 @@ public:
void OnDirectInput(CNetObj_PlayerInput *NewInput); void OnDirectInput(CNetObj_PlayerInput *NewInput);
void OnPredictedInput(CNetObj_PlayerInput *NewInput); void OnPredictedInput(CNetObj_PlayerInput *NewInput);
void OnDisconnect(const char *pReason); void OnDisconnect();
void KillCharacter(int Weapon = WEAPON_GAME); void KillCharacter(int Weapon = WEAPON_GAME);
CCharacter *GetCharacter(); CCharacter *GetCharacter();
@ -76,7 +77,6 @@ public:
int m_DieTick; int m_DieTick;
int m_Score; int m_Score;
int m_ScoreStartTick; int m_ScoreStartTick;
bool m_ForceBalanced;
int m_LastActionTick; int m_LastActionTick;
int m_TeamChangeTick; int m_TeamChangeTick;
struct struct
@ -107,6 +107,7 @@ private:
bool m_Spawning; bool m_Spawning;
int m_ClientID; int m_ClientID;
int m_Team; int m_Team;
bool m_Dummy;
}; };
#endif #endif