4802: make the vanilla teams independent from the ddrace teams r=def- a=C0D3D3V

Fixes #259
Because my changes have some effects on the display and thus people who like it as it was could bother, I have described my changes in detail here.

Until now it was the case that players who are in /spec (while sv_pausable is activated) or the own active player who is in /pause or /spec are in the Spectators team.

With this change this is no longer the case. I took the opportunity to make a few adjustments in the display logic. 

On the server side nothing had to be adjusted, because there was already a separation of the normal and the ddnet teams. 


1. Regarding the specators component:

I intentionally did not adjust the conditions in the OnRender function (lines 224, 306, 325 and 338) so that you can manually select players who are in /spec to watch as well.
I find this helpful, because it has often annoyed me not to be able to quickly find players who are in /spec on the map.

This also allows the selection of players that are in spec in demos. The only problem is that in demos the information about sepc players is missing (The same as in Game, only in Game the information is provided as soon as you spectate). However, until now this was also the case for players who are not in their own team. I find it handy to also have Spec players selectable, so that when they become active, the camera follows them directly.

In addition, you can spectate yourself in demos as well as in the game.
In demos this was already possible, as long as the own player in the demo is not currently in pause, at that moment you could only follow the recorded spectating camera. 

However, I have kept that in SpectateNext, SpectatePrevious and SpectateClosest the own player is not included. However, it is also possible to jump here in spectating to players in /spec.  


2.  Regarding the scoreboard component:

Now only real spectators are displayed under the scoreboard in the spectators team. No longer players who are in /spec or the own player who is currently paused.
So I did not adjust line 125, 341, 354, 367.

Line 724 would not need to be adjusted anyway since it only affects vanilla team games. If the function GetClanName is used for DDnet, this has the effect that paused players are also included.

I have adjusted the active condition of the scoreboard so that it is not automatically displayed when the player is spectating (that's the way it used to be).

Since now the own player is shown in the scoreboard even if he is paused, I have removed the marking of the own player when following another player (line 416).


3.  Regarding the menus_ingame component:
I left the behavior as it was, since we are talking about dangerous commands here (join spectator team and commit suicide) I think it is quite good that these are hidden when the player is paused.

To maintain this behavior, when creating the kill button, we must also check if we are not in pause or spec.
Actually we could check here m_pClient->m_Snap.m_SpecInfo.m_Active just like I did in the scoreboard, but since the code was already created I kept it.


4.  Regarding the IsOtherTeam function in gameclient:
This function is used to determine if the transparency m_ClShowOthersAlpha should be applied to players and nameplates of other teams and if entities of other teams should be predicted.

So I left the behavior as it was, i.e. if you pause via /pause or /spec the transparency is not applied, because then False is returned.

5. Regarding the HUD component:
I have not adjusted any condition here (line 310, 319 and 323). So far the behavior was that when the player went on pause (/pause /spec), in the small time display at the bottom right the top2 players were displayed and otherwise the best and the own player.
Now it is so that the own player is also displayed when he is paused, but not when he is a real spectator.
I personally find it strange why the display should change just because you pause. 

6. Regarding the chat component:

If the dummy paused is in the same team as the player and then a team message arrives, it will no longer be double logged.
Until now, when a player is in the same team in /spec and sends a message, his name was displayed in the Spectators team color and not in the team color. Since I have not adjusted the condition in line 803, the player names are also displayed in the team color for such messages.


7. Regarding the items component:

Here it is determined whether the local player is in the game and depending on that other GameTicks are used and ReconstructSmokeTrail is not canceled. 
Here I could not work in so exactly, no idea what consequences this has that I have not adjusted the conditions in line 47 and 560.  
I noticed at least when testing no difference, maybe someone who knows about it can explain to me what that has for effects.


About all changes I made we can discuss I am ready to undo them or restore the behavior as it was before.  But please justify with arguments.


Independently:
I added a -1 check for the m_LocalClientID to the Strong Week indicators in the Nameplates. So that with server demos the array is not accessed outside of the array range. For demos there are currently no predicted characters and therefore no strong week indicators, so it doesn't change anything.


## Checklist

- [x] Tested the change ingame
- [ ] Provided screenshots if it is a visual change  
I can provide screenshots to compare before after, but it's best to test it yourself.

- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test if it works standalone, system.c especially
- [x] Considered possible null pointers and out of bounds array indexing
- [x] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: c0d3d3v <c0d3d3v@mag-keinen-spam.de>
This commit is contained in:
bors[bot] 2022-03-14 13:06:42 +00:00 committed by GitHub
commit d172a7fd2a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 18 additions and 12 deletions

View file

@ -117,6 +117,7 @@ enum
VERSION_DDNET_GAMETICK = 10042, VERSION_DDNET_GAMETICK = 10042,
VERSION_DDNET_MSG_LEGACY = 15040, VERSION_DDNET_MSG_LEGACY = 15040,
VERSION_DDNET_SWITCH = 15060, VERSION_DDNET_SWITCH = 15060,
VERSION_DDNET_INDEPENDENT_SPECTATORS_TEAM = 16000,
}; };
#endif #endif

View file

@ -170,10 +170,7 @@ void CMenus::RenderGame(CUIRect MainView)
} }
} }
} }
}
if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pGameInfoObj)
{
if(m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS) if(m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS)
{ {
ButtonBar.VSplitLeft(5.0f, 0, &ButtonBar); ButtonBar.VSplitLeft(5.0f, 0, &ButtonBar);

View file

@ -241,7 +241,7 @@ void CNamePlates::RenderNameplatePos(vec2 Position, const CNetObj_PlayerInfo *pP
if((g_Config.m_Debug || g_Config.m_ClNameplatesStrong) && g_Config.m_ClNameplates) if((g_Config.m_Debug || g_Config.m_ClNameplatesStrong) && g_Config.m_ClNameplates)
{ {
if(m_pClient->m_Snap.m_aCharacters[pPlayerInfo->m_ClientID].m_HasExtendedData && m_pClient->m_Snap.m_aCharacters[m_pClient->m_Snap.m_LocalClientID].m_HasExtendedData) if(m_pClient->m_Snap.m_LocalClientID != -1 && m_pClient->m_Snap.m_aCharacters[pPlayerInfo->m_ClientID].m_HasExtendedData && m_pClient->m_Snap.m_aCharacters[m_pClient->m_Snap.m_LocalClientID].m_HasExtendedData)
{ {
CCharacter *pLocalChar = m_pClient->m_GameWorld.GetCharacterByID(m_pClient->m_Snap.m_LocalClientID); CCharacter *pLocalChar = m_pClient->m_GameWorld.GetCharacterByID(m_pClient->m_Snap.m_LocalClientID);
CCharacter *pCharacter = m_pClient->m_GameWorld.GetCharacterByID(pPlayerInfo->m_ClientID); CCharacter *pCharacter = m_pClient->m_GameWorld.GetCharacterByID(pPlayerInfo->m_ClientID);

View file

@ -413,7 +413,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
OldDDTeam = DDTeam; OldDDTeam = DDTeam;
// background so it's easy to find the local player or the followed one in spectator mode // background so it's easy to find the local player or the followed one in spectator mode
if(pInfo->m_Local || (m_pClient->m_Snap.m_SpecInfo.m_Active && pInfo->m_ClientID == m_pClient->m_Snap.m_SpecInfo.m_SpectatorID)) if((!m_pClient->m_Snap.m_SpecInfo.m_Active && pInfo->m_Local) || (m_pClient->m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW && pInfo->m_Local) || (m_pClient->m_Snap.m_SpecInfo.m_Active && pInfo->m_ClientID == m_pClient->m_Snap.m_SpecInfo.m_SpectatorID))
{ {
Graphics()->TextureClear(); Graphics()->TextureClear();
Graphics()->QuadsBegin(); Graphics()->QuadsBegin();
@ -701,7 +701,7 @@ bool CScoreboard::Active()
if(m_Active) if(m_Active)
return true; return true;
if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS) if(m_pClient->m_Snap.m_pLocalInfo && !m_pClient->m_Snap.m_SpecInfo.m_Active)
{ {
// we are not a spectator, check if we are dead // we are not a spectator, check if we are dead
if(!m_pClient->m_Snap.m_pLocalCharacter && g_Config.m_ClScoreboardOnDeath) if(!m_pClient->m_Snap.m_pLocalCharacter && g_Config.m_ClScoreboardOnDeath)

View file

@ -136,7 +136,7 @@ void CSpectator::ConSpectateClosest(IConsole::IResult *pResult, void *pUserData)
int ClosestDistance = INT_MAX; int ClosestDistance = INT_MAX;
for(int i = 0; i < MAX_CLIENTS; i++) for(int i = 0; i < MAX_CLIENTS; i++)
{ {
if(i == SpectatorID || !Snap.m_paPlayerInfos[i] || Snap.m_paPlayerInfos[i]->m_Team == TEAM_SPECTATORS) if(i == SpectatorID || !Snap.m_paPlayerInfos[i] || Snap.m_paPlayerInfos[i]->m_Team == TEAM_SPECTATORS || (SpectatorID == SPEC_FREEVIEW && i == Snap.m_LocalClientID))
continue; continue;
const CNetObj_Character &MaybeClosestCharacter = Snap.m_aCharacters[i].m_Cur; const CNetObj_Character &MaybeClosestCharacter = Snap.m_aCharacters[i].m_Cur;
int Distance = distance(CurPosition, vec2(MaybeClosestCharacter.m_X, MaybeClosestCharacter.m_Y)); int Distance = distance(CurPosition, vec2(MaybeClosestCharacter.m_X, MaybeClosestCharacter.m_Y));

View file

@ -1251,6 +1251,12 @@ void CGameClient::OnNewSnapshot()
m_aClients[Item.m_ID].m_Afk = pInfo->m_Flags & EXPLAYERFLAG_AFK; m_aClients[Item.m_ID].m_Afk = pInfo->m_Flags & EXPLAYERFLAG_AFK;
m_aClients[Item.m_ID].m_Paused = pInfo->m_Flags & EXPLAYERFLAG_PAUSED; m_aClients[Item.m_ID].m_Paused = pInfo->m_Flags & EXPLAYERFLAG_PAUSED;
m_aClients[Item.m_ID].m_Spec = pInfo->m_Flags & EXPLAYERFLAG_SPEC; m_aClients[Item.m_ID].m_Spec = pInfo->m_Flags & EXPLAYERFLAG_SPEC;
if(Item.m_ID == m_Snap.m_LocalClientID && (m_aClients[Item.m_ID].m_Paused || m_aClients[Item.m_ID].m_Spec))
{
m_Snap.m_SpecInfo.m_Active = true;
m_Snap.m_SpecInfo.m_SpectatorID = SPEC_FREEVIEW;
}
} }
} }
else if(Item.m_Type == NETOBJTYPE_CHARACTER) else if(Item.m_Type == NETOBJTYPE_CHARACTER)
@ -2597,7 +2603,7 @@ bool CGameClient::IsOtherTeam(int ClientID)
if(m_Snap.m_LocalClientID < 0) if(m_Snap.m_LocalClientID < 0)
return false; return false;
else if((m_aClients[m_Snap.m_LocalClientID].m_Team == TEAM_SPECTATORS && m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW) || ClientID < 0) else if((m_Snap.m_SpecInfo.m_Active && m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW) || ClientID < 0)
return false; return false;
else if(m_Snap.m_SpecInfo.m_Active && m_Snap.m_SpecInfo.m_SpectatorID != SPEC_FREEVIEW) else if(m_Snap.m_SpecInfo.m_Active && m_Snap.m_SpecInfo.m_SpectatorID != SPEC_FREEVIEW)
{ {

View file

@ -359,10 +359,12 @@ void CPlayer::Snap(int SnappingClient)
pPlayerInfo->m_Score = Score; pPlayerInfo->m_Score = Score;
pPlayerInfo->m_Local = (int)(m_ClientID == SnappingClient && (m_Paused != PAUSE_PAUSED || SnappingClientVersion >= VERSION_DDNET_OLD)); pPlayerInfo->m_Local = (int)(m_ClientID == SnappingClient && (m_Paused != PAUSE_PAUSED || SnappingClientVersion >= VERSION_DDNET_OLD));
pPlayerInfo->m_ClientID = id; pPlayerInfo->m_ClientID = id;
pPlayerInfo->m_Team = (SnappingClientVersion < VERSION_DDNET_OLD || m_Paused != PAUSE_PAUSED || m_ClientID != SnappingClient) && m_Paused < PAUSE_SPEC ? m_Team : TEAM_SPECTATORS; pPlayerInfo->m_Team = m_Team;
if(SnappingClientVersion < VERSION_DDNET_INDEPENDENT_SPECTATORS_TEAM)
if(m_ClientID == SnappingClient && m_Paused == PAUSE_PAUSED && SnappingClientVersion < VERSION_DDNET_OLD) {
pPlayerInfo->m_Team = TEAM_SPECTATORS; // In older versions the SPECTATORS TEAM was also used if the own player is in PAUSE_PAUSED or if any player is in PAUSE_SPEC.
pPlayerInfo->m_Team = (m_Paused != PAUSE_PAUSED || m_ClientID != SnappingClient) && m_Paused < PAUSE_SPEC ? m_Team : TEAM_SPECTATORS;
}
} }
else else
{ {