added pause command. Closes #15

This commit is contained in:
oy 2012-01-10 00:49:31 +01:00
parent 9251796c3a
commit dfe91338f0
23 changed files with 181 additions and 55 deletions

View file

@ -199,7 +199,7 @@ int CControls::SnapInput(int *pData)
void CControls::OnRender()
{
// update target pos
if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED || m_pClient->m_Snap.m_SpecInfo.m_Active))
if(m_pClient->m_Snap.m_pGameInfoObj && !m_pClient->m_Snap.m_SpecInfo.m_Active)
m_TargetPos = m_pClient->m_LocalCharacterPos + m_MousePos;
else if(m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_Snap.m_SpecInfo.m_UsePosition)
m_TargetPos = m_pClient->m_Snap.m_SpecInfo.m_Position + m_MousePos;

View file

@ -60,6 +60,11 @@ void CDamageInd::OnRender()
else
m_aItems[i].m_StartTime += (Client()->LocalTime()-s_LastLocalTime)*(1.0f-pInfo->m_Speed);
}
else
{
if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)
m_aItems[i].m_StartTime += Client()->LocalTime()-s_LastLocalTime;
}
float Life = 0.75f - (Client()->LocalTime() - m_aItems[i].m_StartTime);
if(Life < 0.0f)

View file

@ -41,7 +41,10 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID)
Speed = m_pClient->m_Tuning.m_GunSpeed;
}
float Ct = (Client()->PrevGameTick()-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime();
static float s_LastGameTickTime = Client()->GameTickTime();
if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
s_LastGameTickTime = Client()->GameTickTime();
float Ct = (Client()->PrevGameTick()-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + s_LastGameTickTime;
if(Ct < 0)
return; // projectile havn't been shot yet
@ -63,22 +66,23 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID)
if(pCurrent->m_Type == WEAPON_GRENADE)
{
m_pClient->m_pEffects->SmokeTrail(Pos, Vel*-1);
static float s_Time = 0.0f;
static float s_LastLocalTime = Client()->LocalTime();
if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
{
const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
static float Time = 0;
static float LastLocalTime = Client()->LocalTime();
if(!pInfo->m_Paused)
Time += (Client()->LocalTime()-LastLocalTime)*pInfo->m_Speed;
Graphics()->QuadsSetRotation(Time*pi*2*2 + ItemID);
LastLocalTime = Client()->LocalTime();
s_Time += (Client()->LocalTime()-s_LastLocalTime)*pInfo->m_Speed;
}
else
Graphics()->QuadsSetRotation(Client()->LocalTime()*pi*2*2 + ItemID);
{
if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
s_Time += Client()->LocalTime()-s_LastLocalTime;
}
Graphics()->QuadsSetRotation(s_Time*pi*2*2 + ItemID);
s_LastLocalTime = Client()->LocalTime();
}
else
{
@ -130,26 +134,23 @@ void CItems::RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCu
Graphics()->QuadsSetRotation(Angle);
static float s_Time = 0.0f;
static float s_LastLocalTime = Client()->LocalTime();
float Offset = Pos.y/32.0f + Pos.x/32.0f;
if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
{
const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
static float Time = 0;
static float LastLocalTime = Client()->LocalTime();
if(!pInfo->m_Paused)
Time += (Client()->LocalTime()-LastLocalTime)*pInfo->m_Speed;
Pos.x += cosf(Time*2.0f+Offset)*2.5f;
Pos.y += sinf(Time*2.0f+Offset)*2.5f;
LastLocalTime = Client()->LocalTime();
s_Time += (Client()->LocalTime()-s_LastLocalTime)*pInfo->m_Speed;
}
else
{
Pos.x += cosf(Client()->LocalTime()*2.0f+Offset)*2.5f;
Pos.y += sinf(Client()->LocalTime()*2.0f+Offset)*2.5f;
}
if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
s_Time += Client()->LocalTime()-s_LastLocalTime;
}
Pos.x += cosf(s_Time*2.0f+Offset)*2.5f;
Pos.y += sinf(s_Time*2.0f+Offset)*2.5f;
s_LastLocalTime = Client()->LocalTime();
RenderTools()->DrawSprite(Pos.x, Pos.y, Size);
Graphics()->QuadsEnd();
}

View file

@ -77,7 +77,8 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void
CMapItemEnvelope *pItem = (CMapItemEnvelope *)pThis->m_pLayers->Map()->GetItem(Start+Env, 0, 0);
static float Time = 0;
static float s_Time = 0.0f;
static float s_LastLocalTime = pThis->Client()->LocalTime();
if(pThis->Client()->State() == IClient::STATE_DEMOPLAYBACK)
{
const IDemoPlayer::CInfo *pInfo = pThis->DemoPlayer()->BaseInfo();
@ -90,25 +91,28 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void
pThis->m_CurrentLocalTick = pInfo->m_CurrentTick;
}
Time = mix(pThis->m_LastLocalTick / (float)pThis->Client()->GameTickSpeed(),
s_Time = mix(pThis->m_LastLocalTick / (float)pThis->Client()->GameTickSpeed(),
pThis->m_CurrentLocalTick / (float)pThis->Client()->GameTickSpeed(),
pThis->Client()->IntraGameTick());
}
pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, Time+TimeOffset, pChannels);
pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time+TimeOffset, pChannels);
}
else
{
if(pItem->m_Version < 2 || pItem->m_Synchronized)
if(pThis->m_pClient->m_Snap.m_pGameInfoObj && !(pThis->m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
{
if(pThis->m_pClient->m_Snap.m_pGameInfoObj)
Time = mix((pThis->Client()->PrevGameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(),
if(pItem->m_Version < 2 || pItem->m_Synchronized)
{
s_Time = mix((pThis->Client()->PrevGameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(),
(pThis->Client()->GameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(),
pThis->Client()->IntraGameTick());
}
else
s_Time += pThis->Client()->LocalTime()-s_LastLocalTime;
}
else
Time = pThis->Client()->LocalTime();
pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, Time+TimeOffset, pChannels);
pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time+TimeOffset, pChannels);
s_LastLocalTime = pThis->Client()->LocalTime();
}
}

View file

@ -43,6 +43,11 @@ void CParticles::Add(int Group, CParticle *pPart)
if(pInfo->m_Paused)
return;
}
else
{
if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)
return;
}
if (m_FirstFree == -1)
return;
@ -142,7 +147,10 @@ void CParticles::OnRender()
Update((float)((t-LastTime)/(double)time_freq())*pInfo->m_Speed);
}
else
Update((float)((t-LastTime)/(double)time_freq()));
{
if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
Update((float)((t-LastTime)/(double)time_freq()));
}
LastTime = t;
}

View file

@ -285,14 +285,17 @@ void CPlayers::RenderPlayer(
else if(!WantOtherDir)
State.Add(&g_pData->m_aAnimations[ANIM_WALK], WalkTime, 1.0f);
static float s_LastGameTickTime = Client()->GameTickTime();
if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
s_LastGameTickTime = Client()->GameTickTime();
if (Player.m_Weapon == WEAPON_HAMMER)
{
float ct = (Client()->PrevGameTick()-Player.m_AttackTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime();
float ct = (Client()->PrevGameTick()-Player.m_AttackTick)/(float)SERVER_TICK_SPEED + s_LastGameTickTime;
State.Add(&g_pData->m_aAnimations[ANIM_HAMMER_SWING], clamp(ct*5.0f,0.0f,1.0f), 1.0f);
}
if (Player.m_Weapon == WEAPON_NINJA)
{
float ct = (Client()->PrevGameTick()-Player.m_AttackTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime();
float ct = (Client()->PrevGameTick()-Player.m_AttackTick)/(float)SERVER_TICK_SPEED + s_LastGameTickTime;
State.Add(&g_pData->m_aAnimations[ANIM_NINJA_SWING], clamp(ct*2.0f,0.0f,1.0f), 1.0f);
}
@ -364,15 +367,22 @@ void CPlayers::RenderPlayer(
if ((Client()->GameTick()-Player.m_AttackTick) <= (SERVER_TICK_SPEED / 6) && g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles)
{
int IteX = rand() % g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles;
static int s_LastIteX = IteX;
if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
{
static int s_LastIteX = IteX;
const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
if(pInfo->m_Paused)
IteX = s_LastIteX;
else
s_LastIteX = IteX;
}
else
{
if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)
IteX = s_LastIteX;
else
s_LastIteX = IteX;
}
if(g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX])
{
vec2 Dir = vec2(pPlayerChar->m_X,pPlayerChar->m_Y) - vec2(pPrevChar->m_X, pPrevChar->m_Y);
@ -393,7 +403,11 @@ void CPlayers::RenderPlayer(
{
// TODO: should be an animation
Recoil = 0;
float a = (Client()->GameTick()-Player.m_AttackTick+IntraTick)/5.0f;
static float s_LastIntraTick = IntraTick;
if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
s_LastIntraTick = IntraTick;
float a = (Client()->GameTick()-Player.m_AttackTick+s_LastIntraTick)/5.0f;
if(a < 1)
Recoil = sinf(a*pi);
p = Position + Dir * g_pData->m_Weapons.m_aId[iw].m_Offsetx - Dir*Recoil*10.0f;
@ -415,15 +429,22 @@ void CPlayers::RenderPlayer(
}
int IteX = rand() % g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles;
static int s_LastIteX = IteX;
if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
{
static int s_LastIteX = IteX;
const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
if(pInfo->m_Paused)
IteX = s_LastIteX;
else
s_LastIteX = IteX;
}
else
{
if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)
IteX = s_LastIteX;
else
s_LastIteX = IteX;
}
if (Alpha > 0.0f && g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX])
{
float OffsetY = -g_pData->m_Weapons.m_aId[iw].m_Muzzleoffsety;

View file

@ -657,6 +657,20 @@ void CCharacter::TickDefered()
}
}
void CCharacter::TickPaused()
{
++m_AttackTick;
++m_DamageTakenTick;
++m_Ninja.m_ActivationTick;
++m_ReckoningTick;
if(m_LastAction != -1)
++m_LastAction;
if(m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart > -1)
++m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart;
if(m_EmoteStop > -1)
++m_EmoteStop;
}
bool CCharacter::IncreaseHealth(int Amount)
{
if(m_Health >= 10)

View file

@ -30,6 +30,7 @@ public:
virtual void Destroy();
virtual void Tick();
virtual void TickDefered();
virtual void TickPaused();
virtual void Snap(int SnappingClient);
bool IsGrounded();

View file

@ -23,6 +23,13 @@ void CFlag::Reset()
m_GrabTick = 0;
}
void CFlag::TickPaused()
{
++m_DropTick;
if(m_GrabTick)
++m_GrabTick;
}
void CFlag::Snap(int SnappingClient)
{
if(NetworkClipped(SnappingClient))

View file

@ -21,6 +21,7 @@ public:
CFlag(CGameWorld *pGameWorld, int Team);
virtual void Reset();
virtual void TickPaused();
virtual void Snap(int SnappingClient);
};

View file

@ -91,6 +91,11 @@ void CLaser::Tick()
DoBounce();
}
void CLaser::TickPaused()
{
++m_EvalTick;
}
void CLaser::Snap(int SnappingClient)
{
if(NetworkClipped(SnappingClient))

View file

@ -12,6 +12,7 @@ public:
virtual void Reset();
virtual void Tick();
virtual void TickPaused();
virtual void Snap(int SnappingClient);
protected:

View file

@ -117,6 +117,12 @@ void CPickup::Tick()
}
}
void CPickup::TickPaused()
{
if(m_SpawnTick != -1)
++m_SpawnTick;
}
void CPickup::Snap(int SnappingClient)
{
if(m_SpawnTick != -1 || NetworkClipped(SnappingClient))

View file

@ -14,6 +14,7 @@ public:
virtual void Reset();
virtual void Tick();
virtual void TickPaused();
virtual void Snap(int SnappingClient);
private:

View file

@ -82,6 +82,11 @@ void CProjectile::Tick()
}
}
void CProjectile::TickPaused()
{
++m_StartTick;
}
void CProjectile::FillInfo(CNetObj_Projectile *pProj)
{
pProj->m_X = (int)m_Pos.x;

View file

@ -14,6 +14,7 @@ public:
virtual void Reset();
virtual void Tick();
virtual void TickPaused();
virtual void Snap(int SnappingClient);
private:

View file

@ -105,6 +105,12 @@ public:
*/
virtual void TickDefered() {}
/*
Function: TickPaused
Called when the game is paused, to freeze the state and position of the entity.
*/
virtual void TickPaused() {}
/*
Function: snap
Called when a new snapshot is being generated for a specific

View file

@ -1036,6 +1036,16 @@ void CGameContext::ConTuneDump(IConsole::IResult *pResult, void *pUserData)
}
}
void CGameContext::ConPause(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
if(pSelf->m_pController->IsGameOver())
return;
pSelf->m_World.m_Paused ^= 1;
}
void CGameContext::ConChangeMap(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
@ -1409,6 +1419,7 @@ void CGameContext::OnConsoleInit()
Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConTuneReset, this, "Reset tuning");
Console()->Register("tune_dump", "", CFGFLAG_SERVER, ConTuneDump, this, "Dump tuning");
Console()->Register("pause", "", CFGFLAG_SERVER, ConPause, this, "Pause/unpause game");
Console()->Register("change_map", "?r", CFGFLAG_SERVER|CFGFLAG_STORE, ConChangeMap, this, "Change map");
Console()->Register("restart", "?i", CFGFLAG_SERVER|CFGFLAG_STORE, ConRestart, this, "Restart in x seconds (0 = abort)");
Console()->Register("broadcast", "r", CFGFLAG_SERVER, ConBroadcast, this, "Broadcast message");

View file

@ -48,6 +48,7 @@ class CGameContext : public IGameServer
static void ConTuneParam(IConsole::IResult *pResult, void *pUserData);
static void ConTuneReset(IConsole::IResult *pResult, void *pUserData);
static void ConTuneDump(IConsole::IResult *pResult, void *pUserData);
static void ConPause(IConsole::IResult *pResult, void *pUserData);
static void ConChangeMap(IConsole::IResult *pResult, void *pUserData);
static void ConRestart(IConsole::IResult *pResult, void *pUserData);
static void ConBroadcast(IConsole::IResult *pResult, void *pUserData);

View file

@ -430,8 +430,12 @@ void IGameController::Tick()
}
}
// game is Paused
if(GameServer()->m_World.m_Paused)
++m_RoundStartTick;
// do team-balancing
if (IsTeamplay() && m_UnbalancedTick != -1 && Server()->Tick() > m_UnbalancedTick+g_Config.m_SvTeambalanceTime*Server()->TickSpeed()*60)
if(IsTeamplay() && m_UnbalancedTick != -1 && Server()->Tick() > m_UnbalancedTick+g_Config.m_SvTeambalanceTime*Server()->TickSpeed()*60)
{
GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", "Balancing teams");

View file

@ -64,6 +64,7 @@ public:
const char *m_pGameType;
bool IsTeamplay() const;
bool IsGameOver() const { return m_GameOverTick != -1; }
IGameController(class CGameContext *pGameServer);
virtual ~IGameController();

View file

@ -173,6 +173,17 @@ void CGameWorld::Tick()
pEnt = m_pNextTraverseEntity;
}
}
else
{
// update all objects
for(int i = 0; i < NUM_ENTTYPES; i++)
for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; )
{
m_pNextTraverseEntity = pEnt->m_pNextTypeEntity;
pEnt->TickPaused();
pEnt = m_pNextTraverseEntity;
}
}
RemoveEntities();
}

View file

@ -60,26 +60,37 @@ void CPlayer::Tick()
}
}
if(!m_pCharacter && m_Team == TEAM_SPECTATORS && m_SpectatorID == SPEC_FREEVIEW)
m_ViewPos -= vec2(clamp(m_ViewPos.x-m_LatestActivity.m_TargetX, -500.0f, 500.0f), clamp(m_ViewPos.y-m_LatestActivity.m_TargetY, -400.0f, 400.0f));
if(!m_pCharacter && m_DieTick+Server()->TickSpeed()*3 <= Server()->Tick())
m_Spawning = true;
if(m_pCharacter)
if(!GameServer()->m_World.m_Paused)
{
if(m_pCharacter->IsAlive())
if(!m_pCharacter && m_Team == TEAM_SPECTATORS && m_SpectatorID == SPEC_FREEVIEW)
m_ViewPos -= vec2(clamp(m_ViewPos.x-m_LatestActivity.m_TargetX, -500.0f, 500.0f), clamp(m_ViewPos.y-m_LatestActivity.m_TargetY, -400.0f, 400.0f));
if(!m_pCharacter && m_DieTick+Server()->TickSpeed()*3 <= Server()->Tick())
m_Spawning = true;
if(m_pCharacter)
{
m_ViewPos = m_pCharacter->m_Pos;
}
else
{
delete m_pCharacter;
m_pCharacter = 0;
if(m_pCharacter->IsAlive())
{
m_ViewPos = m_pCharacter->m_Pos;
}
else
{
delete m_pCharacter;
m_pCharacter = 0;
}
}
else if(m_Spawning && m_RespawnTick <= Server()->Tick())
TryRespawn();
}
else if(m_Spawning && m_RespawnTick <= Server()->Tick())
TryRespawn();
else
{
++m_RespawnTick;
++m_DieTick;
++m_ScoreStartTick;
++m_LastActionTick;
++m_TeamChangeTick;
}
}
void CPlayer::PostTick()