Xonotic
all.qc
Go to the documentation of this file.
1 #include "all.qh"
2 #ifndef WEAPONS_ALL_C
3 #define WEAPONS_ALL_C
4 
5 #if defined(CSQC)
6  #include <client/main.qh>
7  #include <common/constants.qh>
8  #include <common/deathtypes/all.qh>
10  #include <common/stats.qh>
11  #include <common/util.qh>
14  #include <lib/csqcmodel/cl_model.qh>
17  #include <lib/warpzone/client.qh>
18  #include <lib/warpzone/common.qh>
19 #elif defined(MENUQC)
21 #elif defined(SVQC)
22  #include <common/constants.qh>
23  #include <common/deathtypes/all.qh>
24  #include <common/items/_mod.qh>
25  #include <common/mapinfo.qh>
26  #include <common/monsters/_mod.qh>
28  #include <common/stats.qh>
29  #include <common/teams.qh>
30  #include <common/util.qh>
32  #include <common/weapons/config.qc>
33  #include <common/weapons/config.qh>
35  #include <lib/csqcmodel/sv_model.qh>
37  #include <lib/warpzone/common.qh>
38  #include <lib/warpzone/server.qh>
40  #include <server/command/_mod.qh>
41  #include <server/hook.qh>
42  #include <server/items/spawning.qh>
43  #include <server/mutators/_mod.qh>
44  #include <server/portals.qh>
45  #include <server/weapons/common.qh>
47  #include <server/weapons/tracing.qh>
48 #endif
49 
50 
51 // WEAPON PLUGIN SYSTEM
52 
54 {
55  a -= WEP_FIRST;
56  if (REGISTRY_MAX(Weapons) > 24)
57  if (a >= 24)
58  {
59  a -= 24;
60  if (REGISTRY_MAX(Weapons) > 48)
61  if (a >= 24)
62  {
63  a -= 24;
64  return '0 0 1' * BIT(a);
65  }
66  return '0 1 0' * BIT(a);
67  }
68  return '1 0 0' * BIT(a);
69 }
70 #ifdef SVQC
71  void WriteWepSet(float dst, WepSet w)
72  {
73  if (REGISTRY_MAX(Weapons) > 48) WriteInt72_t(dst, w);
74  else if (REGISTRY_MAX(Weapons) > 24) WriteInt48_t(dst, w);
75  else WriteInt24_t(dst, w.x);
76  }
77 #endif
78 #ifdef CSQC
79  WepSet WepSet_GetFromStat()
80  {
81  return STAT(WEAPONS);
82  }
83  WepSet WepSet_GetFromStat_InMap()
84  {
85  return STAT(WEAPONSINMAP);
86  }
87  WepSet ReadWepSet()
88  {
89  if (REGISTRY_MAX(Weapons) > 48) return ReadInt72_t();
90  if (REGISTRY_MAX(Weapons) > 24) return ReadInt48_t();
91  return ReadInt24_t() * '1 0 0';
92  }
93 #endif
94 
95 string W_FixWeaponOrder(string order, float complete)
96 {
97  return fixPriorityList(order, WEP_FIRST, WEP_LAST, WEP_IMPULSE_BEGIN - WEP_FIRST, complete);
98 }
99 string W_NameWeaponOrder_MapFunc(string s)
100 {
101  int i = stof(s);
102  if (s == "0" || i)
103  {
104  entity wi = REGISTRY_GET(Weapons, i);
105  if (wi != WEP_Null) return wi.netname;
106  }
107  return s;
108 }
109 
110 string W_UndeprecateName(string s)
111 {
112  switch (s)
113  {
114  case "nex": return "vortex";
115  case "rocketlauncher": return "devastator";
116  case "laser": return "blaster";
117  case "minstanex": return "vaporizer";
118  case "grenadelauncher": return "mortar";
119  case "uzi": return "machinegun";
120  case "hmg": return "okhmg";
121  case "rpc": return "okrpc";
122  default: return s;
123  }
124 }
125 string W_NameWeaponOrder(string order)
126 {
128 }
130 {
131  if (s == "0" || stof(s)) return s;
132  s = W_UndeprecateName(s);
133  FOREACH(Weapons, it != WEP_Null && it.netname == s, return ftos(i));
134  return s;
135 }
136 string W_NumberWeaponOrder(string order)
137 {
139 }
140 
144 {
145  float h;
149 }
151 {
153  Weapon e1 = REGISTRY_GET(Weapons, si);
155  Weapon e2 = REGISTRY_GET(Weapons, sj);
156  int d = (e1.impulse + 9) % 10 - (e2.impulse + 9) % 10;
157  if (d != 0) return -d; // high impulse first!
158  string s = strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " ");
159  return strstrofs(s, sprintf(" %d ", si), 0)
160  - strstrofs(s, sprintf(" %d ", sj), 0); // low char index first!
161 }
163 {
164  int i;
166  for (i = WEP_FIRST; i <= WEP_LAST; ++i)
169  NULL);
170  o = "";
171  for (i = WEP_FIRST; i <= WEP_LAST; ++i)
174  return substring(o, 1, -1);
175 }
176 
177 string W_FixWeaponOrder_AllowIncomplete(entity this, string order)
178 {
179  return W_FixWeaponOrder(order, 0);
180 }
181 
182 string W_FixWeaponOrder_ForceComplete(string order)
183 {
184  if (order == "") order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
185  return W_FixWeaponOrder(order, 1);
186 }
187 
188 WepSet W_RandomWeapons(entity e, WepSet remaining, int n)
189 {
190  WepSet result = '0 0 0';
191  for (int j = 0; j < n; ++j)
192  {
194  FOREACH(Weapons, it != WEP_Null, {
195  if (remaining & (it.m_wepset))
196  RandomSelection_AddEnt(it, 1, 1);
197  });
199  result |= WepSet_FromWeapon(w);
200  remaining &= ~WepSet_FromWeapon(w);
201  }
202  return result;
203 }
204 
205 // TODO: registry handles for below functions
206 string GetAmmoPicture(Resource ammotype)
207 {
208  switch (ammotype)
209  {
210  case RES_SHELLS: return ITEM_Shells.m_icon;
211  case RES_BULLETS: return ITEM_Bullets.m_icon;
212  case RES_ROCKETS: return ITEM_Rockets.m_icon;
213  case RES_CELLS: return ITEM_Cells.m_icon;
214  case RES_PLASMA: return ITEM_Plasma.m_icon;
215  case RES_FUEL: return ITEM_JetpackFuel.m_icon;
216  default: return ""; // wtf, no ammo type?
217  }
218 }
219 
220 string GetAmmoName(Resource ammotype)
221 {
222  switch (ammotype)
223  {
224  case RES_SHELLS: return ITEM_Shells.m_name;
225  case RES_BULLETS: return ITEM_Bullets.m_name;
226  case RES_ROCKETS: return ITEM_Rockets.m_name;
227  case RES_CELLS: return ITEM_Cells.m_name;
228  case RES_PLASMA: return ITEM_Plasma.m_name;
229  case RES_FUEL: return ITEM_JetpackFuel.m_name;
230  default: return "batteries";
231  }
232 }
233 
235 {
236  switch (ammotype)
237  {
238  case RES_SHELLS: return ITEM_Shells;
239  case RES_BULLETS: return ITEM_Bullets;
240  case RES_ROCKETS: return ITEM_Rockets;
241  case RES_CELLS: return ITEM_Cells;
242  case RES_PLASMA: return ITEM_Plasma;
243  case RES_FUEL: return ITEM_JetpackFuel;
244  }
245  LOG_WARNF("Invalid ammo type %d ", ammotype.m_id);
246  return NULL;
247  // WEAPONTODO: use this generic func to reduce duplication ?
248  // GetAmmoPicture GetAmmoName notif_arg_item_wepammo ammo_pickupevalfunc ?
249 }
250 
251 #ifdef CSQC
252 Resource GetAmmoTypeFromNum(int i)
253 {
254  switch (i)
255  {
256  case 0: return RES_SHELLS;
257  case 1: return RES_BULLETS;
258  case 2: return RES_ROCKETS;
259  case 3: return RES_CELLS;
260  case 4: return RES_PLASMA;
261  case 5: return RES_FUEL;
262  default: return RES_NONE;
263  }
264 }
265 
266 int GetAmmoStat(Resource ammotype)
267 {
268  switch (ammotype)
269  {
270  case RES_SHELLS: return STAT_SHELLS;
271  case RES_BULLETS: return STAT_NAILS;
272  case RES_ROCKETS: return STAT_ROCKETS;
273  case RES_CELLS: return STAT_CELLS;
274  case RES_PLASMA: return STAT_PLASMA.m_id;
275  case RES_FUEL: return STAT_FUEL.m_id;
276  default: return -1;
277  }
278 }
279 #endif
280 
281 string W_Sound(string w_snd)
282 {
283  string output = strcat("weapons/", w_snd);
284  MUTATOR_CALLHOOK(WeaponSound, w_snd, output);
285  return M_ARGV(1, string);
286 }
287 
288 string W_Model(string w_mdl)
289 {
290  string output = strcat("models/weapons/", w_mdl);
291  MUTATOR_CALLHOOK(WeaponModel, w_mdl, output);
292  return M_ARGV(1, string);
293 }
294 
295 #ifdef GAMEQC
296 vector shotorg_adjustfromclient(vector vecs, float y_is_right, float algn)
297 {
298  switch (algn)
299  {
300  default:
301  case 3:
302  // right alignment
303  break;
304  case 4:
305  // left
306  vecs.y = -vecs.y;
307  break;
308  case 1:
309  case 2:
310  // center
311  vecs.y = 0;
312  vecs.z -= 2;
313  break;
314  }
315  return vecs;
316 }
317 
318 vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn)
319 {
320  string s;
321  if (visual)
322  {
323  vecs = shotorg_adjustfromclient(vecs, y_is_right, algn);
324  }
325  else if (STAT(SHOOTFROMEYE))
326  {
327  vecs.y = vecs.z = 0;
328  }
329  else if (STAT(SHOOTFROMCENTER))
330  {
331  vecs.y = 0;
332  vecs.z -= 2;
333  }
334  else if ((s = G_SHOOTFROMFIXEDORIGIN) != "")
335  {
336  vector v = stov(s);
337  if (y_is_right) v.y = -v.y;
338  if (v.x != 0) vecs.x = v.x;
339  vecs.y = v.y;
340  vecs.z = v.z;
341  }
342  else // just do the same as top
343  {
344  vecs = shotorg_adjustfromclient(vecs, y_is_right, algn);
345  }
346 
347  return vecs;
348 }
349 
350 #define shotorg_adjust shotorg_adjust_values
351 
403 void CL_WeaponEntity_SetModel(entity this, string name, bool _anim)
404 {
405  if (name == "")
406  {
407  vector oldmin = this.mins, oldmax = this.maxs;
408  setmodel(this, MDL_Null);
409  setsize(this, oldmin, oldmax);
410  if (this.weaponchild) delete(this.weaponchild);
411  this.weaponchild = NULL;
412  this.movedir = '0 0 0';
413  this.spawnorigin = '0 0 0';
414  this.oldorigin = '0 0 0';
415  this.anim_fire1 = '0 1 0.01';
416  this.anim_fire2 = '0 1 0.01';
417  this.anim_idle = '0 1 0.01';
418  this.anim_reload = '0 1 0.01';
419  }
420  else
421  {
422  // if there is a child entity, hide it until we're sure we use it
423  if (this.weaponchild) this.weaponchild.model = "";
424  _setmodel(this, W_Model(strcat("v_", name, ".md3")));
425  int v_shot_idx; // used later
426  (v_shot_idx = gettagindex(this, "shot")) || (v_shot_idx = gettagindex(this, "tag_shot"));
427 
428  _setmodel(this, W_Model(strcat("h_", name, ".iqm")));
429  // preset some defaults that work great for renamed zym files (which don't need an animinfo)
430  this.anim_fire1 = animfixfps(this, '0 1 0.01', '0 0 0');
431  this.anim_fire2 = animfixfps(this, '1 1 0.01', '0 0 0');
432  this.anim_idle = animfixfps(this, '2 1 0.01', '0 0 0');
433  this.anim_reload = animfixfps(this, '3 1 0.01', '0 0 0');
434 
435  // if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model)
436  // if we don't, this is a "real" animated model
437  string t;
438  if ((t = "weapon", gettagindex(this, t)) || (t = "tag_weapon", gettagindex(this, t)))
439  {
440  if (!this.weaponchild)
441  {
442  this.weaponchild = new(weaponchild);
443 #ifdef CSQC
444  this.weaponchild.drawmask = MASK_NORMAL;
445  this.weaponchild.renderflags |= RF_VIEWMODEL;
446 #endif
447  }
448  _setmodel(this.weaponchild, W_Model(strcat("v_", name, ".md3")));
449  setsize(this.weaponchild, '0 0 0', '0 0 0');
450  setattachment(this.weaponchild, this, t);
451  }
452  else
453  {
454  if (this.weaponchild) delete(this.weaponchild);
455  this.weaponchild = NULL;
456  }
457 
458  setsize(this, '0 0 0', '0 0 0');
459  setorigin(this, '0 0 0');
460  this.angles = '0 0 0';
461  this.frame = 0;
462 #ifdef SVQC
463  this.viewmodelforclient = NULL;
464 #else
465  this.renderflags &= ~RF_VIEWMODEL;
466 #endif
467  if (v_shot_idx) // v_ model attached to invisible h_ model
468  {
469  this.movedir = gettaginfo(this.weaponchild, v_shot_idx);
470  }
471  else
472  {
473  int idx;
474  if ((idx = gettagindex(this, "shot")) || (idx = gettagindex(this, "tag_shot")))
475  {
476  this.movedir = gettaginfo(this, idx);
477  }
478  else
479  {
480  LOG_WARNF("weapon model %s does not support the 'shot' tag, will display shots TOTALLY wrong",
481  this.model);
482  this.movedir = '0 0 0';
483  }
484  }
485  {
486  int idx = 0;
487  // v_ model attached to invisible h_ model
488  if (this.weaponchild
489  && ((idx = gettagindex(this.weaponchild, "shell")) || (idx = gettagindex(this.weaponchild, "tag_shell"))))
490  {
491  this.spawnorigin = gettaginfo(this.weaponchild, idx);
492  }
493  else if ((idx = gettagindex(this, "shell")) || (idx = gettagindex(this, "tag_shell")))
494  {
495  this.spawnorigin = gettaginfo(this, idx);
496  }
497  else
498  {
499  LOG_WARNF("weapon model %s does not support the 'shell' tag, will display casings wrong",
500  this.model);
501  this.spawnorigin = this.movedir;
502  }
503  }
504  if (v_shot_idx)
505  {
506  this.oldorigin = '0 0 0'; // use regular attachment
507  }
508  else
509  {
510  int idx;
511  if (this.weaponchild)
512  (idx = gettagindex(this, "weapon")) || (idx = gettagindex(this, "tag_weapon"));
513  else
514  (idx = gettagindex(this, "handle")) || (idx = gettagindex(this, "tag_handle"));
515  if (idx)
516  {
517  this.oldorigin = this.movedir - gettaginfo(this, idx);
518  }
519  else
520  {
521  LOG_WARNF(
522  "weapon model %s does not support the 'handle' tag "
523  "and neither does the v_ model support the 'shot' tag, "
524  "will display muzzle flashes TOTALLY wrong\n",
525  this.model);
526  this.oldorigin = '0 0 0'; // there is no way to recover from this
527  }
528  }
529 
530 #ifdef SVQC
531  this.viewmodelforclient = this.owner;
532 #else
533  this.renderflags |= RF_VIEWMODEL;
534 #endif
535  }
536 
537  this.view_ofs = '0 0 0';
538  this.movedir_aligned = this.movedir;
539 
540  if (this.movedir.x >= 0)
541  {
542  //int algn = STAT(GUNALIGN, this.owner);
543  int algn = W_GunAlign(this, STAT(GUNALIGN, this.owner));
544  #ifdef SVQC
545  this.m_gunalign = algn;
546  #endif
547  vector v = this.movedir;
548  this.movedir = shotorg_adjust(v, false, false, algn);
549  this.movedir_aligned = shotorg_adjust(v, false, true, algn);
550  this.view_ofs = shotorg_adjust(v, false, true, algn) - v;
551  }
552  int compressed_shotorg = compressShotOrigin(this.movedir);
553  // make them match perfectly
554 #ifdef SVQC
555  // null during init
556  if (this.owner) STAT(SHOTORG, this.owner) = compressed_shotorg;
557 #endif
558  this.movedir = decompressShotOrigin(compressed_shotorg);
559 
560  this.spawnorigin += this.view_ofs; // offset the casings origin by the same amount
561 
562  // check if an instant weapon switch occurred
563  setorigin(this, this.view_ofs);
564  if (!_anim) return;
565  // reset animstate now
566  this.wframe = WFRAME_IDLE;
567  setanim(this, this.anim_idle, true, false, true);
568 }
569 #endif
570 
571 #ifdef GAMEQC
572 
573 REGISTER_NET_TEMP(wframe)
574 #ifdef CSQC
575 NET_HANDLE(wframe, bool isNew)
576 {
577  WFRAME fr = ReadByte();
578  float t = ReadFloat();
579  int slot = ReadByte();
580  bool restartanim = ReadByte();
581  entity wepent = viewmodels[slot];
582  if(fr == WFRAME_IDLE)
583  wepent.animstate_looping = false; // we don't need to enforce idle animation
584  else
585  {
586  vector a = '0 0 0';
587  switch(fr)
588  {
589  default:
590  case WFRAME_IDLE: a = wepent.anim_idle; break;
591  case WFRAME_FIRE1: a = wepent.anim_fire1; break;
592  case WFRAME_FIRE2: a = wepent.anim_fire2; break;
593  case WFRAME_RELOAD: a = wepent.anim_reload; break;
594  }
595  a.z *= t;
596  anim_set(wepent, a, !restartanim, restartanim, restartanim);
597  }
598  wepent.state = ReadByte();
599  wepent.weapon_nextthink = ReadFloat();
600  switch (wepent.state)
601  {
602  case WS_RAISE:
603  wepent.weapon_switchdelay = wepent.activeweapon.switchdelay_raise;
604  break;
605  case WS_DROP:
606  wepent.weapon_switchdelay = wepent.activeweapon.switchdelay_drop;
607  break;
608  default:
609  wepent.weapon_switchdelay = 0;
610  break;
611  }
612  return true;
613 }
614 #endif
615 
616 #ifdef SVQC
617 void wframe_send(entity actor, entity weaponentity, int wepframe, float attackrate, bool restartanim)
618 {
619  if (!IS_REAL_CLIENT(actor)) return;
620  int channel = MSG_ONE;
621  msg_entity = actor;
622  WriteHeader(channel, wframe);
623  WriteByte(channel, wepframe);
624  WriteFloat(channel, attackrate);
625  WriteByte(channel, weaponslot(weaponentity.weaponentity_fld));
626  WriteByte(channel, restartanim);
627  WriteByte(channel, weaponentity.state);
628  WriteFloat(channel, weaponentity.weapon_nextthink);
629 }
630 #endif
631 
632 REGISTER_NET_C2S(w_whereis)
633 #ifdef SVQC
634 void Weapon_whereis(Weapon this, entity cl);
635 NET_HANDLE(w_whereis, bool)
636 {
637  Weapon wpn = ReadRegistered(Weapons);
638  if (wpn != WEP_Null) Weapon_whereis(wpn, sender);
639  return true;
640 }
641 #else
642 void w_whereis(Weapon this)
643 {
644  int channel = MSG_C2S;
645  WriteHeader(channel, w_whereis);
646  WriteRegistered(Weapons, channel, this);
647 }
648 CLIENT_COMMAND(weapon_find, "Show spawn locations of a weapon")
649 {
650  switch (request)
651  {
652  case CMD_REQUEST_COMMAND:
653  {
654  string s = argv(1);
655  if (s == "all")
656  {
657  FOREACH(Weapons, it != WEP_Null, w_whereis(it));
658  return;
659  }
660  if (s == "unowned")
661  {
662  FOREACH(Weapons, it != WEP_Null && !(STAT(WEAPONS) & it.m_wepset), w_whereis(it));
663  return;
664  }
665  FOREACH(Weapons, it != WEP_Null && it.netname == s,
666  {
667  w_whereis(it);
668  return;
669  });
670  }
671  default:
672  LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
673  case CMD_REQUEST_USAGE:
674  {
675  LOG_HELP("Usage:^3 cl_cmd weapon_find <weapon>");
676  LOG_HELP(" Where <weapon> is the lowercase weapon name, 'all' or 'unowned'.");
677  return;
678  }
679  }
680 }
681 #endif
682 
683 #ifdef SVQC
684 void W_MuzzleFlash_Model_AttachToShotorg(entity actor, .entity weaponentity, entity flash, vector offset)
685 {
686  flash.owner = actor;
687  flash.angles_z = random() * 360;
688 
689  entity view = actor.(weaponentity);
690  entity exterior = actor.exteriorweaponentity;
691 
692  if (view.oldorigin.x > 0)
693  {
694  setattachment(flash, exterior, "");
695  setorigin(flash, view.oldorigin + offset);
696  }
697  else
698  {
699  if (gettagindex(exterior, "shot")) setattachment(flash, exterior, "shot");
700  else setattachment(flash, exterior, "tag_shot");
701  setorigin(flash, offset);
702  }
703 }
704 #elif defined(CSQC)
705 void W_MuzzleFlash_Model_AttachToShotorg(entity wepent, entity flash, vector offset)
706 {
707  flash.owner = wepent;
708  flash.angles_z = random() * 360;
709 
710  if (gettagindex(wepent, "shot")) setattachment(flash, wepent, "shot");
711  else setattachment(flash, wepent, "tag_shot");
712  setorigin(flash, offset);
713 }
714 #endif
715 
716 void W_MuzzleFlash_Model_Think(entity this)
717 {
718  this.frame += 2;
719  this.scale *= 0.5;
720  this.alpha -= 0.25;
721  this.nextthink = time + 0.05;
722 
723  if(this.alpha <= 0)
724  {
725  setthink(this, SUB_Remove);
726  this.nextthink = time;
727  this.realowner.muzzle_flash = NULL;
728  return;
729  }
730 }
731 
732 void W_MuzzleFlash_Model(entity wepent, entity muzzlemodel)
733 {
734  if(wepent.muzzle_flash == NULL)
735  wepent.muzzle_flash = spawn();
736 
737  entity flash = wepent.muzzle_flash;
738  setmodel(flash, muzzlemodel); // precision set below
739 
740  flash.scale = 0.75;
741  setthink(flash, W_MuzzleFlash_Model_Think);
742  flash.nextthink = time + 0.02;
743  flash.frame = 2;
744  flash.alpha = 0.75;
745  flash.angles_z = random() * 180;
746  flash.effects = EF_ADDITIVE | EF_FULLBRIGHT;
747  flash.owner = flash.realowner = wepent;
748 
749 #ifdef CSQC
750  flash.drawmask = MASK_NORMAL;
751 #endif
752 }
753 
754 REGISTER_NET_TEMP(w_muzzleflash)
755 
756 #ifdef SVQC
757 void W_MuzzleFlash(Weapon thiswep, entity actor, .entity weaponentity, vector shotorg, vector shotdir)
758 {
759  // don't show an exterior muzzle effect for the off-hand
760  if(weaponslot(weaponentity) == 0)
761  {
762  Send_Effect_Except(thiswep.m_muzzleeffect, shotorg, shotdir * 1000, 1, actor);
763 
764  if(thiswep.m_muzzlemodel != MDL_Null)
765  {
766  W_MuzzleFlash_Model(actor.exteriorweaponentity, thiswep.m_muzzlemodel);
767  W_MuzzleFlash_Model_AttachToShotorg(actor, weaponentity, actor.exteriorweaponentity.muzzle_flash, '5 0 0');
768  }
769  }
770 
771  FOREACH_CLIENT(it == actor || (IS_SPEC(it) && it.enemy == actor),
772  {
773  if(!IS_REAL_CLIENT(it))
774  continue;
775  int channel = MSG_ONE;
776  msg_entity = it;
777  WriteHeader(channel, w_muzzleflash);
778  WriteByte(channel, thiswep.m_id);
779  WriteByte(channel, weaponslot(weaponentity));
780  WriteVector(channel, shotorg);
781  });
782 }
783 #elif defined(CSQC)
784 NET_HANDLE(w_muzzleflash, bool isNew)
785 {
786  return = true;
787  int weapon_id = ReadByte();
788  int slot = ReadByte();
789  vector sv_shotorg = ReadVector();
790 
791  Weapon thiswep = REGISTRY_GET(Weapons, weapon_id);
792  vector viewangles = getpropertyvec(VF_CL_VIEWANGLES);
793  vector forward, right, up;
794  MAKE_VECTORS(viewangles, forward, right, up);
795 
797  {
798  // in third person mode, show the muzzle flash from the server side weapon position
799  // we don't have a view model to reference in this case
800  pointparticles(thiswep.m_muzzleeffect, sv_shotorg, forward * 1000, 1);
801  return;
802  }
803  if(!autocvar_r_drawviewmodel) return;
804 
805  entity wepent = viewmodels[slot];
806  // get the local player entity to calculate shot origin
808  if(!rlplayer)
809  rlplayer = csqcplayer; // fall back to the global
810 
811  vector md = wepent.movedir_aligned;
812  vector vecs = ((md.x > 0) ? md : '0 0 0');
813  vector dv = forward * vecs.x + right * -vecs.y + up * vecs.z;
814  vector org = rlplayer.origin + rlplayer.view_ofs + dv;
815 
816  pointparticles(thiswep.m_muzzleeffect, org, forward * 1000, 1);
817 
818  if(thiswep.m_muzzlemodel != MDL_Null)
819  {
820  W_MuzzleFlash_Model(wepent, thiswep.m_muzzlemodel);
821  W_MuzzleFlash_Model_AttachToShotorg(wepent, wepent.muzzle_flash, '5 0 0');
822  }
823 }
824 #endif
825 
826 
827 #endif
828 
829 #endif
830 
831 #ifdef SVQC
832 string W_FixWeaponOrder_ForceComplete_AndBuildImpulseList(entity this, string wo)
833 {
834  string o = W_FixWeaponOrder_ForceComplete(wo);
836  return o;
837 }
838 #endif
839 
840 #ifdef CSQC
841 REPLICATE(cvar_cl_accuracy_data_share, bool, "cl_accuracy_data_share");
842 REPLICATE(cvar_cl_accuracy_data_receive, bool, "cl_accuracy_data_receive");
843 #endif
844 
845 #ifdef GAMEQC
846 REPLICATE(cvar_cl_gunalign, int, "cl_gunalign");
847 REPLICATE(cvar_cl_weapon_switch_reload, bool, "cl_weapon_switch_reload");
848 REPLICATE(cvar_cl_weapon_switch_fallback_to_impulse, bool, "cl_weapon_switch_fallback_to_impulse");
849 REPLICATE(cvar_cl_weaponimpulsemode, int, "cl_weaponimpulsemode");
850 REPLICATE(cvar_cl_weaponpriority, string, "cl_weaponpriority", W_FixWeaponOrder_ForceComplete_AndBuildImpulseList);
851 REPLICATE(cvar_cl_weaponpriorities[0], string, "cl_weaponpriority0", W_FixWeaponOrder_AllowIncomplete);
852 REPLICATE(cvar_cl_weaponpriorities[1], string, "cl_weaponpriority1", W_FixWeaponOrder_AllowIncomplete);
853 REPLICATE(cvar_cl_weaponpriorities[2], string, "cl_weaponpriority2", W_FixWeaponOrder_AllowIncomplete);
854 REPLICATE(cvar_cl_weaponpriorities[3], string, "cl_weaponpriority3", W_FixWeaponOrder_AllowIncomplete);
855 REPLICATE(cvar_cl_weaponpriorities[4], string, "cl_weaponpriority4", W_FixWeaponOrder_AllowIncomplete);
856 REPLICATE(cvar_cl_weaponpriorities[5], string, "cl_weaponpriority5", W_FixWeaponOrder_AllowIncomplete);
857 REPLICATE(cvar_cl_weaponpriorities[6], string, "cl_weaponpriority6", W_FixWeaponOrder_AllowIncomplete);
858 REPLICATE(cvar_cl_weaponpriorities[7], string, "cl_weaponpriority7", W_FixWeaponOrder_AllowIncomplete);
859 REPLICATE(cvar_cl_weaponpriorities[8], string, "cl_weaponpriority8", W_FixWeaponOrder_AllowIncomplete);
860 REPLICATE(cvar_cl_weaponpriorities[9], string, "cl_weaponpriority9", W_FixWeaponOrder_AllowIncomplete);
861 #endif
vector WepSet
Definition: weapon.qh:11
vector shotorg
Definition: aim.qh:12
entity GetAmmoItem(Resource ammotype)
Definition: all.qc:234
string W_FixWeaponOrder(string order, float complete)
Definition: all.qc:95
float alpha
Definition: items.qc:14
string string_null
Definition: nil.qh:9
WepSet W_RandomWeapons(entity e, WepSet remaining, int n)
Definition: all.qc:188
const int WEP_FIRST
Definition: all.qh:304
const float STAT_CELLS
Definition: csprogsdefs.qc:209
const int WS_RAISE
raise frame
Definition: weapon.qh:32
vector view_ofs
Definition: progsdefs.qc:151
entity CSQCModel_server2csqc(int i)
Definition: cl_model.qc:314
#define setanim(...)
Definition: anim.qh:45
#define WEP_IMPULSE_BEGIN
Definition: all.qh:315
string GetAmmoPicture(Resource ammotype)
Definition: all.qc:206
const float VF_CL_VIEWANGLES
Definition: csprogsdefs.qc:194
const float RF_VIEWMODEL
Definition: csprogsdefs.qc:166
const int CMD_REQUEST_USAGE
Definition: command.qh:4
#define REGISTER_NET_C2S(id)
Definition: net.qh:94
ERASEABLE void RandomSelection_Init()
Definition: random.qc:4
vector oldorigin
Definition: csprogsdefs.qc:102
entity viewmodels[MAX_WEAPONSLOTS]
Definition: view.qh:104
entity() spawn
#define REGISTRY_GET(id, i)
Definition: registry.qh:43
string GetAmmoName(Resource ammotype)
Definition: all.qc:220
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
vector maxs
Definition: csprogsdefs.qc:113
REPLICATE(cvar_cl_casings, bool, "cl_casings")
#define CS_CVAR(this)
Definition: state.qh:51
#define NET_HANDLE(id, param)
Definition: net.qh:12
ERASEABLE void heapsort(int n, swapfunc_t swap, comparefunc_t cmp, entity pass)
Definition: sort.qh:9
void anim_set(entity e, vector anim, bool looping, bool override, bool restart)
Definition: anim.qc:6
#define WriteRegistered(r, to, it)
Definition: net.qh:294
#define WEP_LAST
Definition: all.qh:305
#define gettaginfo
Definition: post.qh:32
const int WS_DROP
deselecting frame
Definition: weapon.qh:34
int W_GunAlign(entity this, int preferred_align)
entity result
Definition: promise.qc:43
#define CLIENT_COMMAND(id, description)
Definition: cl_cmd.qh:16
string mapPriorityList(string order, string(string) mapfunc)
Definition: util.qc:527
string W_FixWeaponOrder_ForceComplete(string order)
Definition: all.qc:182
#define LOG_HELP(...)
Definition: log.qh:95
vector decompressShotOrigin(int f)
Definition: util.qc:1143
entity owner
Definition: main.qh:73
string model
Definition: csprogsdefs.qc:108
float W_FixWeaponOrder_BuildImpulseList_buf[REGISTRY_MAX(Weapons)]
Definition: all.qc:141
float renderflags
Definition: main.qh:95
#define gettagindex
Definition: dpextensions.qh:16
#define IS_REAL_CLIENT(v)
Definition: utils.qh:17
float compressShotOrigin(vector v)
Definition: util.qc:1121
int weaponslot(.entity weaponentity)
Definition: weapon.qh:16
const float EF_ADDITIVE
Definition: csprogsdefs.qc:300
#define strcpy(this, s)
Definition: string.qh:49
#define setmodel(this, m)
Definition: model.qh:26
#define LOG_WARNF(...)
Definition: log.qh:67
#define RandomSelection_AddEnt(e, weight, priority)
Definition: random.qh:14
string W_NumberWeaponOrder(string order)
Definition: all.qc:136
const float EF_FULLBRIGHT
Definition: csprogsdefs.qc:303
#define IS_SPEC(v)
Definition: utils.qh:10
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition: bits.qh:8
vector movedir
Definition: progsdefs.qc:203
entity msg_entity
Definition: progsdefs.qc:63
vector mins
Definition: csprogsdefs.qc:113
string W_Model(string w_mdl)
Definition: all.qc:288
const float STAT_NAILS
Definition: csprogsdefs.qc:207
#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"))
entity viewmodelforclient
string W_FixWeaponOrder_BuildImpulseList(string o)
Definition: all.qc:162
entity RandomSelection_chosen_ent
Definition: random.qh:5
const float STAT_ROCKETS
Definition: csprogsdefs.qc:208
#define pointparticles
Definition: csprogsdefs.qh:13
int impulse
M: impulse : weapon impulse.
Definition: weapon.qh:50
string W_NameWeaponOrder_MapFunc(string s)
Definition: all.qc:99
#define NULL
Definition: post.qh:17
const int CMD_REQUEST_COMMAND
Definition: command.qh:3
#define strstrofs
Definition: dpextensions.qh:42
string fixPriorityList(string order, float from, float to, float subtract, float complete)
Definition: util.qc:485
string W_FixWeaponOrder_BuildImpulseList_order
Definition: all.qc:142
#define REGISTRY_MAX(id)
Definition: registry.qh:17
const float MASK_NORMAL
Definition: csprogsdefs.qc:164
#define M_ARGV(x, type)
Definition: events.qh:17
float nextthink
Definition: csprogsdefs.qc:121
float player_localentnum
Definition: csprogsdefs.qc:19
WepSet _WepSet_FromWeapon(int a)
Definition: all.qc:53
float scale
Definition: projectile.qc:14
#define ReadRegistered(r)
Definition: net.qh:293
string W_UndeprecateName(string s)
Definition: all.qc:110
vector(float skel, float bonenum) _skel_get_boneabs_hidden
vector v
Definition: ent_cs.qc:116
bool autocvar_r_drawviewmodel
Definition: view.qh:94
string W_Sound(string w_snd)
Definition: all.qc:281
void W_FixWeaponOrder_BuildImpulseList_swap(int i, int j, entity pass)
Definition: all.qc:143
string W_NameWeaponOrder(string order)
Definition: all.qc:125
string W_FixWeaponOrder_AllowIncomplete(entity this, string order)
Definition: all.qc:177
const float STAT_SHELLS
Definition: csprogsdefs.qc:206
entity realowner
Definition: common.qh:25
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
float frame
primary framegroup animation (strength = 1 - lerpfrac - lerpfrac3 - lerpfrac4)
Definition: anim.qh:6
setorigin(ent, v)
#define setthink(e, f)
float W_FixWeaponOrder_BuildImpulseList_cmp(int i, int j, entity pass)
Definition: all.qc:150
#define REGISTER_NET_TEMP(id)
Definition: net.qh:33
vector shotdir
Definition: aim.qh:13
vector angles
Definition: csprogsdefs.qc:104
entity csqcplayer
Definition: cl_player.qh:26
int autocvar_chase_active
Definition: view.qh:17
#define WepSet_FromWeapon(it)
Definition: all.qh:38
void Weapon_whereis(Weapon this, entity cl)
Definition: selection.qc:26
Header file that describes the functions related to game items.
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
#define pass(name, colormin, colormax)
#define FOREACH(list, cond, body)
Definition: iter.qh:19
string weaponorder_byimpulse
Definition: client.qh:60
string W_NumberWeaponOrder_MapFunc(string s)
Definition: all.qc:129