added spectator mode for dead players in survival

This commit is contained in:
oy 2012-02-15 01:40:24 +01:00
parent 6b8287f7c7
commit ad33841deb
10 changed files with 136 additions and 41 deletions

View file

@ -129,7 +129,7 @@ void CItems::RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCu
case PICKUP_LASER:
Size = g_pData->m_Weapons.m_aId[WEAPON_LASER].m_VisualSize;
break;
case SPRITE_PICKUP_NINJA:
case PICKUP_NINJA:
m_pClient->m_pEffects->PowerupShine(Pos, vec2(96,18));
Size *= 2.0f;
Pos.x -= 10.0f;

View file

@ -414,8 +414,8 @@ bool CScoreboard::Active()
if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS)
{
// we are not a spectator, check if we are dead and the game isn't paused
if(!m_pClient->m_Snap.m_pLocalCharacter && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
// we are not a spectator, check if we are dead, don't follow a player and the game isn't paused
if(!m_pClient->m_Snap.m_pLocalCharacter && !m_pClient->m_Snap.m_SpecInfo.m_Active && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
return true;
}

View file

@ -195,28 +195,33 @@ void CSpectator::OnRender()
float LineHeight = 60.0f;
bool Selected = false;
if(m_pClient->m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW)
if(m_pClient->m_Snap.m_pLocalInfo->m_Team == TEAM_SPECTATORS)
{
Graphics()->TextureSet(-1);
Graphics()->QuadsBegin();
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.25f);
RenderTools()->DrawRoundRect(Width/2.0f-280.0f, Height/2.0f-280.0f, 270.0f, 60.0f, 20.0f);
Graphics()->QuadsEnd();
}
if(m_pClient->m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW)
{
Graphics()->TextureSet(-1);
Graphics()->QuadsBegin();
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.25f);
RenderTools()->DrawRoundRect(Width/2.0f-280.0f, Height/2.0f-280.0f, 270.0f, 60.0f, 20.0f);
Graphics()->QuadsEnd();
}
if(m_SelectorMouse.x >= -280.0f && m_SelectorMouse.x <= -10.0f &&
m_SelectorMouse.y >= -280.0f && m_SelectorMouse.y <= -220.0f)
{
m_SelectedSpectatorID = SPEC_FREEVIEW;
Selected = true;
if(m_SelectorMouse.x >= -280.0f && m_SelectorMouse.x <= -10.0f &&
m_SelectorMouse.y >= -280.0f && m_SelectorMouse.y <= -220.0f)
{
m_SelectedSpectatorID = SPEC_FREEVIEW;
Selected = true;
}
TextRender()->TextColor(1.0f, 1.0f, 1.0f, Selected?1.0f:0.5f);
TextRender()->Text(0, Width/2.0f-240.0f, Height/2.0f-265.0f, FontSize, Localize("Free-View"), -1);
}
TextRender()->TextColor(1.0f, 1.0f, 1.0f, Selected?1.0f:0.5f);
TextRender()->Text(0, Width/2.0f-240.0f, Height/2.0f-265.0f, FontSize, Localize("Free-View"), -1);
float x = -270.0f, y = StartY;
for(int i = 0, Count = 0; i < MAX_CLIENTS; ++i)
{
if(!m_pClient->m_Snap.m_paPlayerInfos[i] || m_pClient->m_Snap.m_paPlayerInfos[i]->m_Team == TEAM_SPECTATORS)
if(!m_pClient->m_Snap.m_paPlayerInfos[i] || m_pClient->m_Snap.m_paPlayerInfos[i]->m_Team == TEAM_SPECTATORS ||
(m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS && (m_pClient->m_Snap.m_paPlayerInfos[i]->m_PlayerFlags&PLAYERFLAG_DEAD ||
m_pClient->m_Snap.m_pLocalInfo->m_Team != m_pClient->m_Snap.m_paPlayerInfos[i]->m_Team || i == m_pClient->m_Snap.m_LocalClientID)))
continue;
if(++Count%9 == 0)

View file

@ -777,7 +777,7 @@ void CGameClient::OnNewSnapshot()
{
m_Snap.m_pSpectatorInfo = (const CNetObj_SpectatorInfo *)pData;
m_Snap.m_pPrevSpectatorInfo = (const CNetObj_SpectatorInfo *)Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_SPECTATORINFO, Item.m_ID);
m_Snap.m_SpecInfo.m_Active = true;
m_Snap.m_SpecInfo.m_SpectatorID = m_Snap.m_pSpectatorInfo->m_SpectatorID;
}
else if(Item.m_Type == NETOBJTYPE_GAMEINFO)

View file

@ -770,7 +770,8 @@ bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon)
int Mask = CmaskOne(From);
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_SpectatorID == From)
if(GameServer()->m_apPlayers[i] && (GameServer()->m_apPlayers[i]->GetTeam() == TEAM_SPECTATORS || GameServer()->m_apPlayers[i]->m_DeadSpecMode) &&
GameServer()->m_apPlayers[i]->GetSpectatorID() == From)
Mask |= CmaskOne(i);
}
GameServer()->CreateSound(GameServer()->m_apPlayers[From]->m_ViewPos, SOUND_HIT, Mask);
@ -848,7 +849,7 @@ void CCharacter::Snap(int SnappingClient)
pCharacter->m_Direction = m_Input.m_Direction;
if(m_pPlayer->GetCID() == SnappingClient || SnappingClient == -1 ||
(!g_Config.m_SvStrictSpectateMode && m_pPlayer->GetCID() == GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID))
(!g_Config.m_SvStrictSpectateMode && m_pPlayer->GetCID() == GameServer()->m_apPlayers[SnappingClient]->GetSpectatorID()))
{
pCharacter->m_Health = m_Health;
pCharacter->m_Armor = m_Armor;

View file

@ -573,13 +573,6 @@ void CGameContext::OnClientDrop(int ClientID, const char *pReason)
m_apPlayers[ClientID] = 0;
m_VoteUpdate = true;
// update spectator modes
for(int i = 0; i < MAX_CLIENTS; ++i)
{
if(m_apPlayers[i] && m_apPlayers[i]->m_SpectatorID == ClientID)
m_apPlayers[i]->m_SpectatorID = SPEC_FREEVIEW;
}
}
void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
@ -832,15 +825,12 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
{
CNetMsg_Cl_SetSpectatorMode *pMsg = (CNetMsg_Cl_SetSpectatorMode *)pRawMsg;
if(pPlayer->GetTeam() != TEAM_SPECTATORS || pPlayer->m_SpectatorID == pMsg->m_SpectatorID || ClientID == pMsg->m_SpectatorID ||
(g_Config.m_SvSpamprotection && pPlayer->m_LastSetSpectatorMode && pPlayer->m_LastSetSpectatorMode+Server()->TickSpeed()*3 > Server()->Tick()))
if(g_Config.m_SvSpamprotection && pPlayer->m_LastSetSpectatorMode && pPlayer->m_LastSetSpectatorMode+Server()->TickSpeed()*3 > Server()->Tick())
return;
pPlayer->m_LastSetSpectatorMode = Server()->Tick();
if(pMsg->m_SpectatorID != SPEC_FREEVIEW && (!m_apPlayers[pMsg->m_SpectatorID] || m_apPlayers[pMsg->m_SpectatorID]->GetTeam() == TEAM_SPECTATORS))
if(!pPlayer->SetSpectatorID(pMsg->m_SpectatorID))
SendChatTarget(ClientID, "Invalid spectator id used");
else
pPlayer->m_SpectatorID = pMsg->m_SpectatorID;
}
else if (MsgID == NETMSGTYPE_CL_STARTINFO)
{

View file

@ -226,6 +226,16 @@ int IGameController::OnCharacterDeath(class CCharacter *pVictim, class CPlayer *
}
if(Weapon == WEAPON_SELF)
pVictim->GetPlayer()->m_RespawnTick = Server()->Tick()+Server()->TickSpeed()*3.0f;
// update spectator modes for dead players in survival
if(m_GameFlags&GAMEFLAG_SURVIVAL)
{
for(int i = 0; i < MAX_CLIENTS; ++i)
if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->m_DeadSpecMode)
GameServer()->m_apPlayers[i]->UpdateDeadSpecMode();
}
return 0;
}

View file

@ -254,7 +254,8 @@ void CGameControllerCTF::Tick()
if(!pPlayer)
continue;
if(pPlayer->GetTeam() == TEAM_SPECTATORS && pPlayer->m_SpectatorID != SPEC_FREEVIEW && GameServer()->m_apPlayers[pPlayer->m_SpectatorID] && GameServer()->m_apPlayers[pPlayer->m_SpectatorID]->GetTeam() == fi)
if((pPlayer->GetTeam() == TEAM_SPECTATORS || pPlayer->m_DeadSpecMode) && pPlayer->GetSpectatorID() != SPEC_FREEVIEW &&
GameServer()->m_apPlayers[pPlayer->GetSpectatorID()] && GameServer()->m_apPlayers[pPlayer->GetSpectatorID()]->GetTeam() == fi)
GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_EN, c);
else if(pPlayer->GetTeam() == fi)
GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_EN, c);

View file

@ -27,6 +27,8 @@ CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, bool Dummy)
m_IsReadyToPlay = GameServer()->m_pController->GetGameState() != IGameController::GS_WARMUP &&
GameServer()->m_pController->GetGameState() != IGameController::GS_PAUSED;
m_RespawnDisabled = GameServer()->m_pController->GetStartRespawnState();
m_DeadSpecMode = false;
m_Spawning = 0;
}
CPlayer::~CPlayer()
@ -74,7 +76,7 @@ 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())
if(!m_pCharacter && m_DieTick+Server()->TickSpeed()*3 <= Server()->Tick() && !m_DeadSpecMode)
Respawn();
if(m_pCharacter)
@ -107,8 +109,8 @@ void CPlayer::PostTick()
}
}
// update view pos for spectators
if(m_Team == TEAM_SPECTATORS && m_SpectatorID != SPEC_FREEVIEW && GameServer()->m_apPlayers[m_SpectatorID])
// update view pos for spectators and dead players
if((m_Team == TEAM_SPECTATORS || m_DeadSpecMode) && m_SpectatorID != SPEC_FREEVIEW && GameServer()->m_apPlayers[m_SpectatorID])
m_ViewPos = GameServer()->m_apPlayers[m_SpectatorID]->m_ViewPos;
}
@ -147,7 +149,7 @@ void CPlayer::Snap(int SnappingClient)
if(m_ClientID == SnappingClient)
pPlayerInfo->m_Local = 1;
if(m_ClientID == SnappingClient && m_Team == TEAM_SPECTATORS)
if(m_ClientID == SnappingClient && (m_Team == TEAM_SPECTATORS || m_DeadSpecMode))
{
CNetObj_SpectatorInfo *pSpectatorInfo = static_cast<CNetObj_SpectatorInfo *>(Server()->SnapNewItem(NETOBJTYPE_SPECTATORINFO, m_ClientID, sizeof(CNetObj_SpectatorInfo)));
if(!pSpectatorInfo)
@ -162,6 +164,21 @@ void CPlayer::Snap(int SnappingClient)
void CPlayer::OnDisconnect()
{
KillCharacter();
if(m_Team != TEAM_SPECTATORS)
{
// update spectator modes
for(int i = 0; i < MAX_CLIENTS; ++i)
{
if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->m_SpectatorID == m_ClientID)
{
if(GameServer()->m_apPlayers[i]->m_DeadSpecMode)
GameServer()->m_apPlayers[i]->UpdateDeadSpecMode();
else
GameServer()->m_apPlayers[i]->m_SpectatorID = SPEC_FREEVIEW;
}
}
}
}
void CPlayer::OnPredictedInput(CNetObj_PlayerInput *NewInput)
@ -236,20 +253,79 @@ void CPlayer::Respawn()
{
if(m_RespawnDisabled)
{
// todo: enable spectate mode
// enable spectate mode for dead players
m_DeadSpecMode = true;
UpdateDeadSpecMode();
return;
}
m_DeadSpecMode = false;
if(m_Team != TEAM_SPECTATORS)
m_Spawning = true;
}
bool CPlayer::SetSpectatorID(int SpectatorID)
{
if(m_SpectatorID == SpectatorID || m_ClientID == SpectatorID)
return false;
if(m_Team == TEAM_SPECTATORS)
{
// check for freeview or if wanted player is playing
if(SpectatorID == SPEC_FREEVIEW || (GameServer()->m_apPlayers[SpectatorID] && GameServer()->m_apPlayers[SpectatorID]->GetTeam() != TEAM_SPECTATORS))
{
m_SpectatorID = SpectatorID;
return true;
}
}
else if(m_DeadSpecMode)
{
// check if wanted player can be followed
if(GameServer()->m_apPlayers[SpectatorID] && DeadCanFollow(GameServer()->m_apPlayers[SpectatorID]))
{
m_SpectatorID = SpectatorID;
return true;
}
}
return false;
}
bool CPlayer::DeadCanFollow(CPlayer *pPlayer) const
{
// check if wanted player is in the same team and alive
return (!pPlayer->m_RespawnDisabled || (pPlayer->GetCharacter() && pPlayer->GetCharacter()->IsAlive())) && pPlayer->GetTeam() == m_Team;
}
void CPlayer::UpdateDeadSpecMode()
{
// check if actual spectator id is valid
if(m_SpectatorID != SPEC_FREEVIEW && GameServer()->m_apPlayers[m_SpectatorID] && DeadCanFollow(GameServer()->m_apPlayers[m_SpectatorID]))
return;
// find player to follow
for(int i = 0; i < MAX_CLIENTS; ++i)
{
if(GameServer()->m_apPlayers[i] && DeadCanFollow(GameServer()->m_apPlayers[i]))
{
m_SpectatorID = i;
return;
}
}
// no one available to follow -> turn spectator mode off
m_DeadSpecMode = false;
}
void CPlayer::SetTeam(int Team, bool DoChatMsg)
{
KillCharacter();
m_Team = Team;
m_LastActionTick = Server()->Tick();
m_SpectatorID = SPEC_FREEVIEW;
m_DeadSpecMode = false;
// we got to wait 0.5 secs before respawning
m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
@ -260,7 +336,12 @@ void CPlayer::SetTeam(int Team, bool DoChatMsg)
for(int i = 0; i < MAX_CLIENTS; ++i)
{
if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->m_SpectatorID == m_ClientID)
GameServer()->m_apPlayers[i]->m_SpectatorID = SPEC_FREEVIEW;
{
if(GameServer()->m_apPlayers[i]->m_DeadSpecMode)
GameServer()->m_apPlayers[i]->UpdateDeadSpecMode();
else
GameServer()->m_apPlayers[i]->m_SpectatorID = SPEC_FREEVIEW;
}
}
}
}

View file

@ -53,7 +53,11 @@ public:
int m_aActLatency[MAX_CLIENTS];
// used for spectator mode
int m_SpectatorID;
int GetSpectatorID() const { return m_SpectatorID; }
bool SetSpectatorID(int SpectatorID);
bool m_DeadSpecMode;
bool DeadCanFollow(CPlayer *pPlayer) const;
void UpdateDeadSpecMode();
bool m_IsReadyToEnter;
bool m_IsReadyToPlay;
@ -118,6 +122,9 @@ private:
int m_ClientID;
int m_Team;
bool m_Dummy;
// used for spectator mode
int m_SpectatorID;
};
#endif