Xonotic
all.qh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <common/command/_mod.qh>
4 #include <common/stats.qh>
5 #include "config.qh"
6 
7 #include "weapon.qh"
8 
9 #ifdef SVQC
10 void WriteWepSet(float dest, WepSet w);
11 #endif
12 
13 #ifdef CSQC
14 WepSet WepSet_GetFromStat();
15 WepSet WepSet_GetFromStat_InMap();
16 WepSet ReadWepSet();
17 #endif
18 
19 #ifdef GAMEQC
20 #include "calculations.qh"
21 #include "projectiles.qh"
22 #include <common/models/all.qh>
23 #include <common/effects/all.qh>
24 #endif
25 
26 #include <common/util.qh>
27 
28 REGISTRY(Weapons, 72) // Increase as needed. Can be up to 72.
29 REGISTER_REGISTRY(Weapons)
30 STATIC_INIT(WeaponPickup) { FOREACH(Weapons, true, it.m_pickup = NEW(WeaponPickup, it)); }
31 
32 #ifdef SVQC
33 #include <server/bot/api.qh>
34 #endif
35 
36 .WepSet m_wepset;
37 #define WEPSET(id) (WEP_##id.m_wepset)
38 #define WepSet_FromWeapon(it) ((it).m_wepset)
40 
41 #define DEFAULT_FILENAME "weapons_dump.cfg"
42 // NOTE: dumpeffectinfo, dumpnotifs, dumpturrets and dumpweapons use similar code
43 GENERIC_COMMAND(dumpweapons, "Dump all turrets into " DEFAULT_FILENAME, false) // WEAPONTODO: make this work with other progs than just server
44 {
45  switch(request)
46  {
48  {
49  #ifdef SVQC
50  wep_config_file = -1;
51  wep_config_alsoprint = -1;
52  string filename = argv(1);
53 
54  if(filename == "")
55  {
56  filename = DEFAULT_FILENAME;
57  wep_config_alsoprint = false;
58  }
59  else if(filename == "-")
60  {
61  filename = DEFAULT_FILENAME;
62  wep_config_alsoprint = true;
63  }
64  wep_config_file = fopen(filename, FILE_WRITE);
65 
66  if(wep_config_file >= 0)
67  {
69  LOG_INFOF("Dumping weapons... File located in ^2data/data/%s^7.", filename);
70  fclose(wep_config_file);
71  wep_config_file = -1;
72  wep_config_alsoprint = -1;
73  }
74  else
75  {
76  LOG_INFOF("^1Error: ^7Could not open file '%s'!", filename);
77  }
78  #else
79  LOG_INFO("Weapons dump command only works with sv_cmd.");
80  #endif
81  return;
82  }
83 
84  default:
85  case CMD_REQUEST_USAGE:
86  {
87  LOG_HELP("Usage:^3 ", GetProgramCommandPrefix(), " dumpweapons [<filename>]");
88  LOG_HELPF(" Where <filename> is the file to write (default is %s),", DEFAULT_FILENAME);
89  LOG_HELP(" if supplied with '-' output to console as well as default,");
90  LOG_HELP(" if left blank, it will only write to default.");
91  return;
92  }
93  }
94 }
95 #undef DEFAULT_FILENAME
96 
97 #ifdef SVQC
98 entity W_PROP_reloader;
99 float autocvar_w_prop_interval = 5;
100 .void(Weapon this, int) wr_net;
101 void W_PROP_reload(int chan, entity to)
102 {
103  W_PROP_reloader.nextthink = time + autocvar_w_prop_interval;
104  msg_entity = to;
105  FOREACH(Weapons, true, {
106  it.wr_update(it);
107  void(Weapon, int) f = it.wr_net;
108  if (f) f(it, chan);
109  });
110 }
111 void W_PROP_think(entity this)
112 {
113  W_PROP_reload(MSG_ALL, NULL);
114 }
115 STATIC_INIT_LATE(W_PROP_reloader)
116 {
117  entity e = W_PROP_reloader = new_pure(W_PROP_reloader);
118  setthink(e, W_PROP_think);
119  W_PROP_think(e);
120 }
121 #endif
122 
123 #define REGISTER_WEAPON(...) EVAL_REGISTER_WEAPON(OVERLOAD(REGISTER_WEAPON, __VA_ARGS__))
124 #define EVAL_REGISTER_WEAPON(...) __VA_ARGS__
125 #define REGISTER_WEAPON_2(id, inst) REGISTER(Weapons, WEP, id, m_id, inst)
126 
127 #define REGISTER_WEAPON_3(id, sname, inst) \
128  REGISTER_WEAPON_2(id, inst); \
129  [[alias("WEP_" #id)]] Weapon _wep_##sname
130 
131 REGISTER_WEAPON(Null, NEW(Weapon));
132 REGISTRY_DEFINE_GET(Weapons, WEP_Null)
133 
135 {
136  FOREACH(Weapons, it != WEP_Null && it.netname == s, return it);
137  return WEP_Null;
138 }
139 
140 
141 #ifdef GAMEQC
142 
143 // legacy w_prop mappings
144 #define X(fld, T) .T fld; .T wepvar_##fld = fld;
145 X(switchdelay_drop, float)
146 X(switchdelay_raise, float)
147 X(weaponreplace, string)
148 X(weaponstartoverride, float)
149 X(weaponstart, float)
150 X(weaponthrowable, float)
151 #ifdef SVQC
152 X(reload_ammo, float)
153 const .float reloading_ammo = reload_ammo;
154 X(reload_time, float)
155 const .float reloading_time = reload_time;
156 #endif
157 #undef X
158 
159 #endif
160 
161 
162 
163 #define W_PROPS(L, class, prefix) \
164  L(W_PROP_BEGIN, W_PROP, W_PROP_END, class, prefix) \
165  L(W_CONFIG_BEGIN, W_CONFIG, W_CONFIG_END, class, prefix) \
166  L(W_UPDATE_BEGIN, W_UPDATE, W_UPDATE_END, class, prefix) \
167  L(W_NET_BEGIN, W_NET, W_NET_END, class, prefix) \
168  \
169 
170 
171  #define W_PROP(class, wepname, fld, T, m) W_PROP_##m(class, fld, T, wepname)
172  #define W_PROP_NONE(class, fld, T, wepname) _W_PROP(class, fld, T, wepname)
173  #define W_PROP_PRI(class, fld, T, wepname) _W_PROP(class, primary_##fld, T, wepname)
174  #define W_PROP_SEC(class, fld, T, wepname) _W_PROP(class, secondary_##fld, T, wepname)
175  #define W_PROP_BOTH(class, fld, T, wepname) \
176  W_PROP_PRI(class, fld, T, wepname) \
177  W_PROP_SEC(class, fld, T, wepname)
178  #define W_PROP_BEGIN(class)
179  #ifdef GAMEQC
180  #define _W_PROP(class, fld, T, wepname) \
181  /* static */ T _W_PROP_CVAR(wepname, fld); \
182  ATTRIB(class, wepvar_##fld, T, _W_PROP_CVAR(wepname, fld));
183  #define _W_PROP_CVAR(wepname, fld) autocvar_g_balance_##wepname##_##fld
184  #else
185  #define _W_PROP(class, fld, T, wepname)
186  #define _W_PROP_CVAR(wepname, fld)
187  #endif
188  #define W_PROP_END()
189 
190 
191 
192  #define W_CONFIG(class, wepname, fld, T, m) W_CONFIG_##m(class, fld, T, wepname)
193  #define W_CONFIG_NONE(class, fld, T, wepname) _W_CONFIG(class, fld, T, wepname)
194  #define W_CONFIG_PRI(class, fld, T, wepname) _W_CONFIG(class, primary_##fld, T, wepname)
195  #define W_CONFIG_SEC(class, fld, T, wepname) _W_CONFIG(class, secondary_##fld, T, wepname)
196  #define W_CONFIG_BOTH(class, fld, T, wepname) \
197  W_CONFIG_PRI(class, fld, T, wepname) \
198  W_CONFIG_SEC(class, fld, T, wepname)
199  #ifdef SVQC
200  #define W_CONFIG_BEGIN(class) METHOD(class, wr_config, void(class this)) {
201  #define _W_CONFIG(class, fld, T, wepname) if (#wepname == this.netname) WEP_CONFIG_WRITE_CVARS(wepname, fld, T);
202  #define W_CONFIG_END() }
203  #else
204  #define W_CONFIG_BEGIN(class)
205  #define _W_CONFIG(class, fld, T, wepname)
206  #define W_CONFIG_END()
207  #endif
208 
209 
210  #define W_UPDATE(class, wepname, fld, T, m) W_UPDATE_##m(class, fld, T, wepname)
211  #define W_UPDATE_NONE(class, fld, T, wepname) _W_UPDATE(class, fld, T, wepname)
212  #define W_UPDATE_PRI(class, fld, T, wepname) _W_UPDATE(class, primary_##fld, T, wepname)
213  #define W_UPDATE_SEC(class, fld, T, wepname) _W_UPDATE(class, secondary_##fld, T, wepname)
214  #define W_UPDATE_BOTH(class, fld, T, wepname) \
215  W_UPDATE_PRI(class, fld, T, wepname) \
216  W_UPDATE_SEC(class, fld, T, wepname)
217  #ifdef GAMEQC
218  .entity baseline, baseline_target;
219  #define W_UPDATE_BEGIN(class) \
220  METHOD(class, wr_update, void(class this)) \
221  { \
222  noref entity b = this.baseline; \
223  if (!b) \
224  { \
225  b = this.baseline = new_pure(baseline); \
226  b.baseline_target = this; \
227  }
228  #ifdef SVQC
229  #define _W_UPDATE(class, fld, T, wepname) \
230  { \
231  T it = _W_PROP_CVAR(wepname, fld); \
232  b.wepvar_##fld = this.wepvar_##fld; \
233  this.wepvar_##fld = it; \
234  }
235  #else
236  #define _W_UPDATE(class, fld, T, wepname)
237  #endif
238  #define W_UPDATE_END() }
239  #else
240  #define W_UPDATE_BEGIN(class)
241  #define _W_UPDATE(class, fld, T, wepname)
242  #define W_UPDATE_END()
243  #endif
244 
245 
246  #define W_NET(class, wepname, fld, T, m) W_NET_##m(class, fld, T, wepname)
247  #define W_NET_NONE(class, fld, T, wepname) _W_NET(class, fld, T, wepname)
248  #define W_NET_PRI(class, fld, T, wepname) _W_NET(class, primary_##fld, T, wepname)
249  #define W_NET_SEC(class, fld, T, wepname) _W_NET(class, secondary_##fld, T, wepname)
250  #define W_NET_BOTH(class, fld, T, wepname) \
251  W_NET_PRI(class, fld, T, wepname) \
252  W_NET_SEC(class, fld, T, wepname)
253  #if defined(CSQC)
254  REGISTER_NET_TEMP(WeaponUpdate)
255  #define W_NET_BEGIN(class) METHOD(class, wr_net, void(class this, int i)) { int n = 0;
256  #define _W_NET(class, fld, T, wepname) \
257  { \
258  if (++n == i) this.wepvar_##fld = Read_##T(); \
259  }
260  .void(Weapon this, int i) wr_net;
261  NET_HANDLE(WeaponUpdate, bool isnew)
262  {
263  Weapon w = REGISTRY_GET(Weapons, ReadByte());
264  for (int i; (i = ReadByte()); )
265  {
266  w.wr_net(w, i);
267  }
268  return true;
269  }
270  #define W_NET_END() }
271  #elif defined(SVQC)
272  REGISTER_NET_TEMP(WeaponUpdate)
273  #define W_NET_BEGIN(class) \
274  METHOD(class, wr_net, void(class this, int chan)) \
275  { \
276  bool commit = false; \
277  int i = 0;
278  #define _W_NET(class, fld, T, wepname) \
279  { \
280  ++i; \
281  T it = this.wepvar_##fld; \
282  if (chan == MSG_ONE || it != this.baseline.wepvar_##fld) \
283  { \
284  if (!commit) { commit = true; WriteHeader(chan, WeaponUpdate); WriteByte(chan, this.m_id); } \
285  WriteByte(chan, i); Write_##T(chan, it); \
286  } \
287  }
288  #define W_NET_END() if (commit) WriteByte(chan, 0); }
289  #else
290  #define W_NET_BEGIN(class)
291  #define _W_NET(class, fld, T, wepname)
292  #define W_NET_END()
293  #endif
294 
295 
296 
297 // read cvars from weapon settings
298 // cvars are created as such: g_balance_wepname_name
299 #define WEP_CVAR(wepname, name) (_wep_##wepname.wepvar_##name)
300 #define WEP_CVAR_PRI(wepname, name) WEP_CVAR(wepname, primary_##name)
301 #define WEP_CVAR_SEC(wepname, name) WEP_CVAR(wepname, secondary_##name)
302 #define WEP_CVAR_BOTH(wepname, isprimary, name) ((isprimary) ? WEP_CVAR_PRI(wepname, name) : WEP_CVAR_SEC(wepname, name))
303 
304 const int WEP_FIRST = 1;
305 #define WEP_LAST (REGISTRY_COUNT(Weapons) - 1)
308 
309 #include "all.inc"
310 
311 // TODO: remove after 0.8.2. Retains impulse number compatibility because 0.8.1 clients don't reload the weapons.cfg
312 #define WEP_HARDCODED_IMPULSES 20
313 
314 // TODO: invert after 0.8.2. Will require moving 'best weapon' impulses
315 #define WEP_IMPULSE_BEGIN 230
316 #define WEP_IMPULSE_END bound(WEP_IMPULSE_BEGIN, WEP_IMPULSE_BEGIN + (REGISTRY_COUNT(Weapons) - 1) - 1, 253)
317 
319 REGISTRY_CHECK(Weapons)
320 
321 STATIC_INIT(register_weapons_done)
322 {
323  string inaccessible = "";
324  FOREACH(Weapons, true, {
325  WepSet set = it.m_wepset = _WepSet_FromWeapon(it.m_id = i);
326  WEPSET_ALL |= set;
327  if (it.spawnflags & WEP_FLAG_SUPERWEAPON) WEPSET_SUPERWEAPONS |= set;
328  if (it == WEP_Null) continue;
329  int imp = WEP_IMPULSE_BEGIN + it.m_id - 1;
330  if (imp <= WEP_IMPULSE_END)
331  localcmd(sprintf("alias weapon_%s \"impulse %d\"\n", it.netname, imp));
332  else
333  inaccessible = strcat(inaccessible, "\n", it.netname);
334  });
335  if (inaccessible && autocvar_developer > 0) LOG_TRACEF("Impulse limit exceeded, weapon(s) will not be directly accessible: %s", inaccessible);
336  #ifdef CSQC
337  FOREACH(Weapons, true, it.wr_init(it));
338  #endif
339  weaponorder_byid = "";
340  for (int i = REGISTRY_MAX(Weapons) - 1; i >= 1; --i)
341  if (REGISTRY_GET(Weapons, i))
342  weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
343  weaponorder_byid = strzone(substring(weaponorder_byid, 1, -1));
344 }
345 
346 #ifdef GAMEQC
347 
348 .entity weaponchild;
349 .entity exteriorweaponentity;
350 vector weaponentity_glowmod(Weapon wep, entity actor, int c, entity wepent)
351 {
352  vector g;
353  if (!(g = wep.wr_glow(wep, actor, wepent))) g = colormapPaletteColor(c & 0x0F, true) * 2;
354  return g;
355 }
356 
357 .int m_gunalign;
358 
359 //.int weapon; // current weapon
360 .string weaponname; // name of .weapon
361 
362 .vector spawnorigin; // for casings
363 
364 .vector movedir_aligned; // shot origin based on weapon alignment (unaffected by shootfromeye)
365 
366 // weapon animation vectors:
367 .vector anim_fire1;
368 .vector anim_fire2;
369 .vector anim_idle;
370 .vector anim_reload;
371 
372 .entity muzzle_flash;
373 
374 // static frame globals
375 
376 ENUMCLASS(WFRAME)
377 CASE(WFRAME, DONTCHANGE)
378 CASE(WFRAME, FIRE1)
379 CASE(WFRAME, FIRE2)
380 CASE(WFRAME, IDLE)
381 CASE(WFRAME, RELOAD)
382 ENUMCLASS_END(WFRAME)
383 
384 .WFRAME wframe;
385 
386 #ifdef SVQC
387  string autocvar_g_shootfromfixedorigin;
388  #define G_SHOOTFROMFIXEDORIGIN autocvar_g_shootfromfixedorigin
389 #elif defined(CSQC)
390  string autocvar_cl_shootfromfixedorigin;
391  #define G_SHOOTFROMFIXEDORIGIN autocvar_cl_shootfromfixedorigin
392 #endif
393 
394 vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn);
395 void CL_WeaponEntity_SetModel(entity this, string name, bool _anim);
396 
397 REPLICATE_INIT(int, cvar_cl_gunalign);
398 REPLICATE_INIT(bool, cvar_cl_weapon_switch_reload);
399 REPLICATE_INIT(bool, cvar_cl_weapon_switch_fallback_to_impulse);
400 REPLICATE_INIT(int, cvar_cl_weaponimpulsemode);
401 
402 REPLICATE_INIT(string, cvar_cl_weaponpriority);
403 REPLICATE_INIT(string, cvar_cl_weaponpriorities[10]);
404 
405 #ifdef CSQC
406 REPLICATE_INIT(bool, cvar_cl_accuracy_data_share);
407 REPLICATE_INIT(bool, cvar_cl_accuracy_data_receive);
408 #endif
409 
410 #ifdef SVQC
411 void wframe_send(entity actor, entity weaponentity, int wepframe, float attackrate, bool restartanim);
412 
413 void W_MuzzleFlash(Weapon thiswep, entity actor, .entity weaponentity, vector shotorg, vector shotdir);
414 
415 string W_FixWeaponOrder_ForceComplete_AndBuildImpulseList(entity this, string wo);
416 string W_FixWeaponOrder_AllowIncomplete(entity this, string order);
417 #endif
418 
419 #endif
vector WepSet
Definition: weapon.qh:11
int int int imp
Definition: impulse.qc:90
vector shotorg
Definition: aim.qh:12
#define REGISTER_WEAPON(...)
Definition: all.qh:123
#define LOG_HELPF(...)
Definition: log.qh:96
REGISTRY(Weapons, 72) STATIC_INIT(WeaponPickup)
Definition: all.qh:28
WepSet WEPSET_SUPERWEAPONS
Definition: all.qh:307
REPLICATE_INIT(float, cvar_cl_autotaunt)
vector dest
Definition: jumppads.qh:41
const int WEP_FIRST
Definition: all.qh:304
#define ENUMCLASS(id)
Definition: enumclass.qh:22
#define NEW(cname,...)
Definition: oo.qh:105
#define WEP_IMPULSE_END
Definition: all.qh:316
#define WEP_IMPULSE_BEGIN
Definition: all.qh:315
REGISTRY_SORT(Notifications)
WepSet WEPSET_ALL
Definition: all.qh:306
STATIC_INIT_LATE(Notif_Choices)
Definition: all.qh:720
const int CMD_REQUEST_USAGE
Definition: command.qh:4
entity() spawn
#define REGISTRY_GET(id, i)
Definition: registry.qh:43
#define REGISTRY_CHECK(id)
Definition: registry.qh:175
#define NET_HANDLE(id, param)
Definition: net.qh:12
entity to
Definition: self.qh:96
#define LOG_HELP(...)
Definition: log.qh:95
#define REGISTER_REGISTRY(id)
Definition: registry.qh:212
#define REGISTRY_DEFINE_GET(id, null)
Definition: registry.qh:40
entity msg_entity
Definition: progsdefs.qc:63
#define LOG_INFOF(...)
Definition: log.qh:71
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
WepSet _WepSet_FromWeapon(int i)
Definition: all.qc:53
X(1, 1) X(2
#define NULL
Definition: post.qh:17
const int CMD_REQUEST_COMMAND
Definition: command.qh:3
#define LOG_INFO(...)
Definition: log.qh:70
#define LOG_TRACEF(...)
Definition: log.qh:82
#define REGISTRY_MAX(id)
Definition: registry.qh:17
string weaponorder_byid
Definition: weapon.qh:214
vector(float skel, float bonenum) _skel_get_boneabs_hidden
#define ENUMCLASS_END(id)
Definition: enumclass.qh:24
const float FILE_WRITE
Definition: csprogsdefs.qc:233
string W_FixWeaponOrder_AllowIncomplete(entity this, string order)
Definition: all.qc:177
STATIC_INIT(IMPULSES_renumber)
Definition: all.qh:8
#define new_pure(class)
purely logical entities (.origin doesn&#39;t work)
Definition: oo.qh:62
noref int autocvar_developer
Definition: log.qh:102
#define setthink(e, f)
#define CASE(class, id)
Definition: enumclass.qh:23
#define REGISTER_NET_TEMP(id)
Definition: net.qh:33
vector shotdir
Definition: aim.qh:13
GENERIC_COMMAND(dumpitems, "Dump all items to the console", false)
Definition: all.qh:36
#define WEP_HARDCODED_IMPULSES
Definition: all.qh:312
WepSet m_wepset
Definition: all.qh:36
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition: weapon.qh:41
float time
Definition: csprogsdefs.qc:16
float reload_time
Weapon Weapon_from_name(string s)
Definition: all.qh:134
#define DEFAULT_FILENAME
Definition: all.qh:41
void(entity this) impulse_handle
#define FOREACH(list, cond, body)
Definition: iter.qh:19
void Dump_Weapon_Settings()
Definition: config.qc:32
#define colormapPaletteColor(c, isPants)
Definition: color.qh:5
const int WEP_FLAG_SUPERWEAPON
Definition: weapon.qh:202