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