]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/state.qh
Viewmodel: fix switching when spectating
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / state.qh
1 #pragma once
2
3 /**
4  * Purpose: common player state, usable on client and server
5  * Client: singleton representing the viewed player
6  * Server: instance per client, clients decoupled from players
7  */
8 CLASS(PlayerState, Object)
9         ATTRIB(PlayerState, m_client, entity, NULL)
10         CONSTRUCTOR(PlayerState, entity client)
11         {
12                 CONSTRUCT(PlayerState);
13                 this.m_client = client;
14         }
15         ATTRIB(PlayerState, m_switchingweapon, Weapon, Weapons_from(-1))
16         ATTRIB(PlayerState, m_switchweapon, Weapon, Weapons_from(-1))
17         ATTRIB(PlayerState, m_weapon, Weapon, Weapons_from(-1))
18         METHOD(PlayerState, ps_push, void(PlayerState this, entity cl))
19         {
20                 STAT(ACTIVEWEAPON, cl) = this.m_weapon.m_id;
21                 STAT(SWITCHINGWEAPON, cl) = this.m_switchingweapon.m_id;
22                 STAT(SWITCHWEAPON, cl) = this.m_switchweapon.m_id;
23         }
24 ENDCLASS(PlayerState)
25
26 .PlayerState _ps;
27 #if NDEBUG
28         #define PS(this) (this._ps)
29 #else
30         PlayerState PS(entity this) { assert(IS_CLIENT(this)); return this._ps; }
31 #endif
32
33 void Inventory_new(entity this);
34 void Inventory_delete(entity this);
35
36 // TODO: renew on death
37
38 void PlayerState_attach(entity this)
39 {
40         this._ps = NEW(PlayerState, this);
41
42         Inventory_new(this);
43 }
44
45 void PlayerState_detach(entity this)
46 {
47         if (!PS(this)) return;  // initial connect
48         FOREACH_CLIENT(PS(it) == PS(this), { PS(it) = NULL; });
49         remove(PS(this));
50         this._ps = NULL;
51
52     Inventory_delete(self);
53 }
54
55 /**
56  * Purpose: common client state, usable on client and server
57  * Client: singleton representing the viewed player
58  * Server: instance per client
59  */
60 CLASS(ClientState, Object)
61         ATTRIB(ClientState, m_client, entity, NULL)
62         CONSTRUCTOR(ClientState, entity client)
63         {
64                 CONSTRUCT(ClientState);
65                 this.m_client = client;
66         }
67 ENDCLASS(ClientState)
68
69 .ClientState _cs;
70
71 #if NDEBUG
72         #define CS(this) (this._cs)
73 #else
74         ClientState CS(entity this) { assert(IS_CLIENT(this)); assert(this._cs); return this._cs; }
75 #endif
76
77 void GetCvars(int);
78 void DecodeLevelParms(entity this);
79 void PlayerScore_Attach(entity this);
80 void ClientData_Attach(entity this);
81 void accuracy_init(entity this);
82 void entcs_attach(entity this);
83 void playerdemo_init(entity this);
84 void anticheat_init(entity this);
85 void W_HitPlotOpen(entity this);
86 void bot_clientconnect(entity this);
87
88 void ClientState_attach(entity this)
89 {
90         this._cs = NEW(ClientState, this);
91
92     GetCvars(0);  // get other cvars from player
93
94         // TODO: xonstat elo.txt support, until then just 404s
95         if (false && IS_REAL_CLIENT(this)) { PlayerStats_PlayerBasic_CheckUpdate(this); }
96
97         // TODO: fold all of these into ClientState
98
99         DecodeLevelParms(this);
100
101         PlayerScore_Attach(this);
102         ClientData_Attach(this);
103         accuracy_init(this);
104         entcs_attach(this);
105         playerdemo_init(this);
106         anticheat_init(this);
107         W_HitPlotOpen(this);
108
109         bot_clientconnect(this);
110 }
111
112 void bot_clientdisconnect();
113 void W_HitPlotClose(entity this);
114 void anticheat_report();
115 void playerdemo_shutdown();
116 void entcs_detach(entity this);
117 void accuracy_free(entity this);
118 void ClientData_Detach(entity this);
119 void PlayerScore_Detach(entity this);
120
121 void ClientState_detach(entity this)
122 {
123         remove(CS(this));
124         this._cs = NULL;
125
126     GetCvars(-1);  // free cvars
127
128     bot_clientdisconnect();
129
130     W_HitPlotClose(this);
131     anticheat_report();
132     playerdemo_shutdown();
133     entcs_detach(this);
134     accuracy_free(self);
135     ClientData_Detach(this);
136     PlayerScore_Detach(self);
137 }