]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/wepent.qc
Merge branch 'master' into Mario/wepent_experimental
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / wepent.qc
1 #include "wepent.qh"
2
3 #define WEPENT_SET_NORMAL(var, x) MACRO_BEGIN \
4         var = x; \
5 MACRO_END
6
7 /** the engine player name strings are mutable! */
8 #define WEPENT_SET_MUTABLE_STRING(var, x) MACRO_BEGIN \
9         if (var) strunzone(var); \
10         var = strzone(x); \
11 MACRO_END
12
13 // #define PROP(public, fld, set, sv, cl)
14 #define WEPENT_NETPROPS(PROP) PROP(false, sv_entnum, WEPENT_SET_NORMAL, {}, {}) /* sentinel */ \
15         PROP(false, m_switchweapon, WEPENT_SET_NORMAL, \
16         { WriteByte(chan, this.m_switchweapon.m_id); }, \
17         { (viewmodels[this.m_wepent_slot]).switchweapon = Weapons_from(ReadByte()); }) \
18     \
19     PROP(false, m_switchingweapon, WEPENT_SET_NORMAL, \
20         { WriteByte(chan, this.m_switchingweapon.m_id); }, \
21         { (viewmodels[this.m_wepent_slot]).switchingweapon = Weapons_from(ReadByte()); }) \
22     \
23     PROP(false, m_weapon, WEPENT_SET_NORMAL, \
24         { WriteByte(chan, this.m_weapon.m_id); }, \
25         { (viewmodels[this.m_wepent_slot]).activeweapon = Weapons_from(ReadByte()); }) \
26     \
27     PROP(false, m_alpha, WEPENT_SET_NORMAL, \
28         { WriteByte(chan, this.m_alpha * 16); }, \
29         { (viewmodels[this.m_wepent_slot]).alpha = ReadByte() / 16; }) \
30     \
31     PROP(false, vortex_charge, WEPENT_SET_NORMAL, \
32         { WriteByte(chan, this.vortex_charge * 16); }, \
33         { (viewmodels[this.m_wepent_slot]).vortex_charge = ReadByte() / 16; }) \
34     \
35     PROP(false, m_gunalign, WEPENT_SET_NORMAL, \
36         { WriteByte(chan, this.m_gunalign); }, \
37         { (viewmodels[this.m_wepent_slot]).m_gunalign = ReadByte(); }) \
38     \
39     PROP(false, porto_v_angle_held, WEPENT_SET_NORMAL, \
40         { WriteByte(chan, this.porto_v_angle_held); if(this.porto_v_angle_held) { \
41                  WriteAngle(chan, this.porto_v_angle.x); WriteAngle(chan, this.porto_v_angle.y); \
42                 } }, \
43         { (viewmodels[this.m_wepent_slot]).angles_held_status = ReadByte(); if((viewmodels[this.m_wepent_slot]).angles_held_status) { \
44                 (viewmodels[this.m_wepent_slot]).angles_held_x = ReadAngle(); (viewmodels[this.m_wepent_slot]).angles_held_y = ReadAngle(); (viewmodels[this.m_wepent_slot]).angles_held_z = 0; } \
45                 else { (viewmodels[this.m_wepent_slot]).angles_held = '0 0 0'; } }) \
46     \
47     PROP(false, tuba_instrument, WEPENT_SET_NORMAL, \
48         { WriteByte(chan, this.tuba_instrument); }, \
49         { (viewmodels[this.m_wepent_slot]).tuba_instrument = ReadByte(); }) \
50     \
51         /**/
52
53 #ifdef SVQC
54
55         int WEPENT_PUBLICMASK = 0;
56         STATIC_INIT(WEPENT_PUBLICMASK)
57         {
58                 int i = 0;
59                 #define X(public, fld, set, sv, cl) { \
60                         if (public) { \
61                                 WEPENT_PUBLICMASK |= BIT(i); \
62                         } \
63                         i += 1; \
64                 }
65                 WEPENT_NETPROPS(X);
66         #undef X
67                 if (i >= BITS(16 - 1)) LOG_FATAL("Exceeded WEPENT_NETPROPS limit");
68         }
69
70         bool _wepent_send(entity this, entity to, int sf, int chan)
71         {
72                 sf |= this.m_forceupdate;
73                 this.m_forceupdate = 0;
74                 if (chan == MSG_ENTITY)
75                         WriteHeader(chan, ENT_CLIENT_WEPENT);
76                 else
77                         WriteHeader(chan, CLIENT_WEPENT);
78                 .entity weaponentity = this.owner.weaponentity_fld;
79                 WriteByte(chan, weaponslot(weaponentity));
80                 WriteShort(chan, sf);
81                 int i = 0;
82                 #define X(public, fld, set, sv, cl) { \
83                         if (sf & BIT(i)) { \
84                                 sv; \
85                         } \
86                         i += 1; \
87                 }
88                 WEPENT_NETPROPS(X);
89         #undef X
90                 return true;
91         }
92
93         bool wepent_send(entity this, entity to, int sf)
94         {
95                 return _wepent_send(this, to, sf, MSG_ENTITY);
96         }
97
98         void wepent_think(entity this)
99         {
100                 if(wasfreed(this.owner) || !this.owner)
101                 {
102                         delete(this);
103                         return;
104                 }
105
106                 this.nextthink = time;
107
108                 entity o = this.owner;
109
110                 int i = 0;
111                 #define X(public, fld, set, sv, cl) { \
112                         if (this.fld != o.fld) { \
113                                 set(this.fld, o.fld); \
114                                 this.SendFlags |= BIT(i); \
115                         } \
116                         i += 1; \
117                 }
118                 WEPENT_NETPROPS(X);
119         #undef X
120         }
121
122         bool wepent_customize(entity this, entity client)
123         {
124                 //entity e = WaypointSprite_getviewentity(client);
125                 .entity weaponentity = this.owner.weaponentity_fld;
126                 return client.(weaponentity) == this.owner;
127         }
128
129         void wepent_link(entity wep)
130         {
131                 entity e = new(wepent_sender);
132                 e.owner = wep;
133                 setthink(e, wepent_think);
134                 e.nextthink = time;
135                 //e.drawonlytoclient = wep.owner;
136                 setcefc(e, wepent_customize);
137                 Net_LinkEntity(e, false, 0, wepent_send);
138         }
139
140 #endif
141
142 #ifdef CSQC
143
144         bool ReadWepent(entity this)
145         {
146                 int slot = ReadByte();
147                 this.m_wepent_slot = slot;
148                 viewmodels[slot].m_wepent_slot = slot;
149                 int sf = ReadShort();
150                 int i = 0;
151                 #define X(public, fld, set, sv, cl) { \
152                         if (sf & BIT(i)) { \
153                                 cl; \
154                         } \
155                         i += 1; \
156                 }
157                 WEPENT_NETPROPS(X);
158         #undef X
159                 return true;
160         }
161
162         NET_HANDLE(ENT_CLIENT_WEPENT, bool isnew)
163         {
164                 if (isnew)
165                         this.classname = "wepent_receiver";
166                 return ReadWepent(this);
167         }
168
169         NET_HANDLE(CLIENT_WEPENT, bool isnew)
170         {
171                 return ReadWepent(NULL);
172         }
173
174 #endif