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(pPlayer->m_ShowOthers == SHOW_OTHERS_ONLY_TEAM)
69 {
70 if(GetDDRaceTeam(pGameServer, ClientId) != m_DDRaceTeam && GetDDRaceTeam(pGameServer, ClientId) != TEAM_SUPER)
71 return false; // In different teams
72 }
73 else if(pPlayer->m_ShowOthers == SHOW_OTHERS_OFF)
74 {
75 if(m_Solo)
76 return false; // When in solo part don't show others
77 if(IsSolo(pGameServer, ClientId))
78 return false; // When in solo part don't show others
79 if(GetDDRaceTeam(pGameServer, ClientId) != m_DDRaceTeam && GetDDRaceTeam(pGameServer, ClientId) != TEAM_SUPER)
80 return false; // In different teams
81 }
82 } // See everything of yourself
83 }
84 else if(pPlayer->SpectatorId() != SPEC_FREEVIEW)
85 { // Spectating specific player
86 if(pPlayer->SpectatorId() != m_OwnerId)
87 { // Actions of other players
88 if(!Character(pGameServer, ClientId: pPlayer->SpectatorId()))
89 return false; // Player is currently dead
90 if(pPlayer->m_ShowOthers == SHOW_OTHERS_ONLY_TEAM)
91 {
92 if(GetDDRaceTeam(pGameServer, ClientId: pPlayer->SpectatorId()) != m_DDRaceTeam && GetDDRaceTeam(pGameServer, ClientId: pPlayer->SpectatorId()) != TEAM_SUPER)
93 return false; // In different teams
94 }
95 else if(pPlayer->m_ShowOthers == SHOW_OTHERS_OFF)
96 {
97 if(m_Solo)
98 return false; // When in solo part don't show others
99 if(IsSolo(pGameServer, ClientId: pPlayer->SpectatorId()))
100 return false; // When in solo part don't show others
101 if(GetDDRaceTeam(pGameServer, ClientId: pPlayer->SpectatorId()) != m_DDRaceTeam && GetDDRaceTeam(pGameServer, ClientId: pPlayer->SpectatorId()) != TEAM_SUPER)
102 return false; // In different teams
103 }
104 } // See everything of player you're spectating
105 }
106 else
107 { // Freeview
108 if(pPlayer->m_SpecTeam)
109 { // Show only players in own team when spectating
110 if(GetDDRaceTeam(pGameServer, ClientId) != m_DDRaceTeam && GetDDRaceTeam(pGameServer, ClientId) != TEAM_SUPER)
111 return false; // in different teams
112 }
113 }
114
115 return true;
116}
117
118bool CInteractions::CanHit(const CGameContext *pGameServer, int ClientId) const
119{
120 const CPlayer *pPlayer = GetPlayer(pGameServer, ClientId);
121 if(!pPlayer)
122 return false;
123
124 if(m_DDRaceTeam && GetDDRaceTeam(pGameServer, ClientId) != m_DDRaceTeam)
125 return false;
126 if(m_Solo && m_UniqueOwnerId != pPlayer->GetUniqueCid())
127 return false;
128 if(m_NoHitOthers && m_UniqueOwnerId != pPlayer->GetUniqueCid())
129 return false;
130 if(m_NoHitSelf && m_UniqueOwnerId == pPlayer->GetUniqueCid())
131 return false;
132
133 return true;
134}
135
136CClientMask CInteractions::CanSeeMask(const CGameContext *pGameServer) const
137{
138 if(m_DDRaceTeam == TEAM_SUPER)
139 {
140 return CClientMask().set();
141 }
142
143 CClientMask Mask;
144 for(int i = 0; i < MAX_CLIENTS; ++i)
145 {
146 if(CanSee(pGameServer, ClientId: i))
147 {
148 Mask.set(pos: i);
149 }
150 }
151 return Mask;
152}
153
154CClientMask CInteractions::CanHitMask(const CGameContext *pGameServer) const
155{
156 if(m_DDRaceTeam == TEAM_SUPER)
157 {
158 return CClientMask().set();
159 }
160
161 CClientMask Mask;
162 for(int i = 0; i < MAX_CLIENTS; ++i)
163 {
164 if(CanHit(pGameServer, ClientId: i))
165 {
166 Mask.set(pos: i);
167 }
168 }
169 return Mask;
170}
171
172const CCharacter *CInteractions::OwnerCharacter(const CGameContext *pGameServer) const
173{
174 const CCharacter *pChr = pGameServer->GetPlayerChar(ClientId: m_OwnerId);
175 if(!pChr)
176 return nullptr;
177 if(pChr->GetPlayer()->GetUniqueCid() != m_UniqueOwnerId)
178 return nullptr;
179 return pChr;
180}
181