1#include "interactions.h"
2
3#include <engine/shared/protocol.h>
4
5#include <game/server/entities/character.h>
6#include <game/server/gamecontext.h>
7#include <game/server/player.h>
8
9const CPlayer *CInteractions::GetPlayer(const CGameContext *pGameServer, int ClientId) const
10{
11 dbg_assert(ClientId >= 0 && ClientId < MAX_CLIENTS, "invalid client id %d", ClientId);
12 return pGameServer->m_apPlayers[ClientId];
13}
14
15const CCharacter *CInteractions::Character(const CGameContext *pGameServer, int ClientId) const
16{
17 return pGameServer->GetPlayerChar(ClientId);
18}
19
20bool CInteractions::IsSolo(const CGameContext *pGameServer, int ClientId) const
21{
22 const CCharacter *pChr = Character(pGameServer, ClientId);
23 return pChr && pChr->Core()->m_Solo;
24}
25
26int CInteractions::GetDDRaceTeam(const CGameContext *pGameServer, int ClientId) const
27{
28 return pGameServer->GetDDRaceTeam(ClientId);
29}
30
31void CInteractions::Init(int OwnerId, uint32_t UniqueOwnerId)
32{
33 m_OwnerId = OwnerId;
34 m_UniqueOwnerId = UniqueOwnerId;
35}
36
37void CInteractions::FillOwnerConnected(
38 bool OwnerAlive,
39 int DDRaceTeam,
40 bool Solo,
41 bool NoHitOthers,
42 bool NoHitSelf)
43{
44 m_OwnerAlive = OwnerAlive;
45 m_DDRaceTeam = DDRaceTeam;
46 m_Solo = Solo;
47 m_NoHitOthers = NoHitOthers;
48 m_NoHitSelf = NoHitSelf;
49}
50
51void CInteractions::FillOwnerDisconnected()
52{
53 m_OwnerAlive = false;
54 m_OwnerId = -1;
55 // m_UniqueOwnerId = 0; // TODO: yes no maybe?
56}
57
58bool CInteractions::CanSee(const CGameContext *pGameServer, int ClientId) const
59{
60 const CPlayer *pPlayer = GetPlayer(pGameServer, ClientId);
61 if(!pPlayer)
62 return false; // Player doesn't exist
63
64 if(!(pPlayer->GetTeam() == TEAM_SPECTATORS || pPlayer->IsPaused()))
65 { // Not spectator
66 if(ClientId != m_OwnerId)
67 { // Actions of other players
68 if(!Character(pGameServer, ClientId))
69 return false; // Player is currently dead
70 if(pPlayer->m_ShowOthers == SHOW_OTHERS_ONLY_TEAM)
71 {
72 if(GetDDRaceTeam(pGameServer, ClientId) != m_DDRaceTeam && GetDDRaceTeam(pGameServer, ClientId) != TEAM_SUPER)
73 return false; // In different teams
74 }
75 else if(pPlayer->m_ShowOthers == SHOW_OTHERS_OFF)
76 {
77 if(m_Solo)
78 return false; // When in solo part don't show others
79 if(IsSolo(pGameServer, ClientId))
80 return false; // When in solo part don't show others
81 if(GetDDRaceTeam(pGameServer, ClientId) != m_DDRaceTeam && GetDDRaceTeam(pGameServer, ClientId) != TEAM_SUPER)
82 return false; // In different teams
83 }
84 } // See everything of yourself
85 }
86 else if(pPlayer->SpectatorId() != SPEC_FREEVIEW)
87 { // Spectating specific player
88 if(pPlayer->SpectatorId() != m_OwnerId)
89 { // Actions of other players
90 if(!Character(pGameServer, ClientId: pPlayer->SpectatorId()))
91 return false; // Player is currently dead
92 if(pPlayer->m_ShowOthers == SHOW_OTHERS_ONLY_TEAM)
93 {
94 if(GetDDRaceTeam(pGameServer, ClientId: pPlayer->SpectatorId()) != m_DDRaceTeam && GetDDRaceTeam(pGameServer, ClientId: pPlayer->SpectatorId()) != TEAM_SUPER)
95 return false; // In different teams
96 }
97 else if(pPlayer->m_ShowOthers == SHOW_OTHERS_OFF)
98 {
99 if(m_Solo)
100 return false; // When in solo part don't show others
101 if(IsSolo(pGameServer, ClientId: pPlayer->SpectatorId()))
102 return false; // When in solo part don't show others
103 if(GetDDRaceTeam(pGameServer, ClientId: pPlayer->SpectatorId()) != m_DDRaceTeam && GetDDRaceTeam(pGameServer, ClientId: pPlayer->SpectatorId()) != TEAM_SUPER)
104 return false; // In different teams
105 }
106 } // See everything of player you're spectating
107 }
108 else
109 { // Freeview
110 if(pPlayer->m_SpecTeam)
111 { // Show only players in own team when spectating
112 if(GetDDRaceTeam(pGameServer, ClientId) != m_DDRaceTeam && GetDDRaceTeam(pGameServer, ClientId) != TEAM_SUPER)
113 return false; // in different teams
114 }
115 }
116
117 return true;
118}
119
120bool CInteractions::CanHit(const CGameContext *pGameServer, int ClientId) const
121{
122 const CPlayer *pPlayer = GetPlayer(pGameServer, ClientId);
123 if(!pPlayer)
124 return false;
125
126 if(m_DDRaceTeam && GetDDRaceTeam(pGameServer, ClientId) != m_DDRaceTeam)
127 return false;
128 if(m_Solo && m_UniqueOwnerId != pPlayer->GetUniqueCid())
129 return false;
130 if(m_NoHitOthers && m_UniqueOwnerId != pPlayer->GetUniqueCid())
131 return false;
132 if(m_NoHitSelf && m_UniqueOwnerId == pPlayer->GetUniqueCid())
133 return false;
134
135 return true;
136}
137
138CClientMask CInteractions::CanSeeMask(const CGameContext *pGameServer) const
139{
140 if(m_DDRaceTeam == TEAM_SUPER)
141 {
142 return CClientMask().set();
143 }
144
145 CClientMask Mask;
146 for(int i = 0; i < MAX_CLIENTS; ++i)
147 {
148 if(CanSee(pGameServer, ClientId: i))
149 {
150 Mask.set(pos: i);
151 }
152 }
153 return Mask;
154}
155
156CClientMask CInteractions::CanHitMask(const CGameContext *pGameServer) const
157{
158 if(m_DDRaceTeam == TEAM_SUPER)
159 {
160 return CClientMask().set();
161 }
162
163 CClientMask Mask;
164 for(int i = 0; i < MAX_CLIENTS; ++i)
165 {
166 if(CanHit(pGameServer, ClientId: i))
167 {
168 Mask.set(pos: i);
169 }
170 }
171 return Mask;
172}
173