Xonotic
weaponsystem.qh File Reference
+ Include dependency graph for weaponsystem.qh:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define ATTACK_FINISHED(ent, w)   ATTACK_FINISHED_FOR(ent, ent.(w).m_weapon.m_id, weaponslot(w))
 
#define ATTACK_FINISHED_FOR(ent, w, slot)   ((ent).(attack_finished_for[((w) - WEP_FIRST) * MAX_WEAPONSLOTS + (slot)]))
 
#define INDEPENDENT_ATTACK_FINISHED   1
 

Functions

void CL_SpawnWeaponentity (entity e,.entity weaponentity)
 
vector CL_Weapon_GetShotOrg (float wpn)
 
 void (Weapon thiswep, entity actor,.entity weaponentity, int fire) weapon_think
 
void W_AttachToShotorg (entity actor,.entity weaponentity, entity flash, vector offset)
 
void w_clear (Weapon thiswep, entity actor,.entity weaponentity, int fire)
 
void W_DecreaseAmmo (Weapon wep, entity actor, float ammo_use,.entity weaponentity)
 
void W_DropEvent (.void(Weapon, entity actor,.entity) event, entity player, float weapon_type, entity weapon_item,.entity weaponentity)
 
void w_ready (Weapon thiswep, entity actor,.entity weaponentity, int fire)
 
void W_Reload (entity actor,.entity weaponentity, float sent_ammo_min, Sound sent_sound)
 
void W_ResetGunAlign (entity player, int preferred_alignment)
 
void W_WeaponFrame (Player actor,.entity weaponentity)
 
float W_WeaponRateFactor (entity this)
 
float W_WeaponSpeedFactor (entity this)
 
bool weapon_prepareattack (Weapon thiswep, entity actor,.entity weaponentity, bool secondary, float attacktime)
 
bool weapon_prepareattack_check (Weapon thiswep, entity actor,.entity weaponentity, float secondary, float attacktime)
 
void weapon_prepareattack_do (entity actor,.entity weaponentity, float secondary, float attacktime)
 
void weapon_thinkf (entity actor,.entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,.entity weaponentity, int fire) func)
 
bool weaponLocked (entity player)
 
bool weaponUseForbidden (entity player)
 

Variables

int ammo_none
 
float attack_finished_for [REGISTRY_MAX(Weapons) *MAX_WEAPONSLOTS]
 
float attack_finished_single [MAX_WEAPONSLOTS]
 
float autocvar_g_weapondamagefactor
 
float autocvar_g_weaponforcefactor
 
float autocvar_g_weaponratefactor
 
float autocvar_g_weaponspeedfactor
 
float autocvar_g_weaponspreadfactor
 
float bulletcounter
 
int clip_load
 
int clip_size
 
float internalteam
 
int old_clip_load
 
const int W_TICSPERFRAME = 2
 
entity weapon_dropevent_item
 
float weapon_load [REGISTRY_MAX(Weapons)]
 
float weapon_nextthink
 
entity weaponentity_fld
 

Macro Definition Documentation

◆ ATTACK_FINISHED

#define ATTACK_FINISHED (   ent,
 
)    ATTACK_FINISHED_FOR(ent, ent.(w).m_weapon.m_id, weaponslot(w))

◆ ATTACK_FINISHED_FOR

#define ATTACK_FINISHED_FOR (   ent,
  w,
  slot 
)    ((ent).(attack_finished_for[((w) - WEP_FIRST) * MAX_WEAPONSLOTS + (slot)]))

Definition at line 38 of file weaponsystem.qh.

Referenced by PlayerDamage().

◆ INDEPENDENT_ATTACK_FINISHED

#define INDEPENDENT_ATTACK_FINISHED   1

Definition at line 11 of file weaponsystem.qh.

Referenced by W_WeaponFrame().

Function Documentation

◆ CL_SpawnWeaponentity()

void CL_SpawnWeaponentity ( entity  e,
.entity  weaponentity 
)

Definition at line 176 of file weaponsystem.qc.

References CL_ExteriorWeaponentity_Think(), CL_Weaponentity_CustomizeEntityForClient(), CL_Weaponentity_Think(), drag_undraggable(), entity(), setmodel, setorigin(), setthink, SOLID_NOT, time, and weaponentities.

Referenced by PutPlayerInServer().

177 {
178  entity w_ent = actor.(weaponentity) = new(weaponentity);
179  w_ent.solid = SOLID_NOT;
180  w_ent.owner = actor;
181  setmodel(w_ent, MDL_Null); // precision set when changed
182  setorigin(w_ent, '0 0 0');
183  w_ent.weaponentity_fld = weaponentity;
185  w_ent.nextthink = time;
186  w_ent.viewmodelforclient = actor;
187  w_ent.draggable = drag_undraggable;
189 
190  wepent_link(w_ent);
191 
192  if (weaponentity == weaponentities[0]) // only one exterior model, thank you very much
193  {
194  entity exterior = actor.exteriorweaponentity = new(exteriorweaponentity);
195  exterior.solid = SOLID_NOT;
196  exterior.owner = actor;
197  exterior.draggable = drag_undraggable;
198  exterior.weaponentity_fld = weaponentity;
199  setorigin(exterior, '0 0 0');
201  exterior.nextthink = time;
202 
203  CSQCMODEL_AUTOINIT(exterior);
204  }
205 }
const float SOLID_NOT
Definition: csprogsdefs.qc:244
void CL_ExteriorWeaponentity_Think(entity this)
entity() spawn
#define setmodel(this, m)
Definition: model.qh:26
void CL_Weaponentity_Think(entity this)
Definition: weaponsystem.qc:79
bool drag_undraggable(entity draggee, entity dragger)
Definition: cheats.qc:897
bool CL_Weaponentity_CustomizeEntityForClient(entity this, entity client)
Definition: weaponsystem.qc:56
entity weaponentities[MAX_WEAPONSLOTS]
Definition: weapon.qh:14
setorigin(ent, v)
#define setthink(e, f)
float time
Definition: csprogsdefs.qc:16
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ CL_Weapon_GetShotOrg()

vector CL_Weapon_GetShotOrg ( float  wpn)

◆ void()

void ( Weapon  thiswep,
entity  actor,
.entity  weaponentity,
int  fire 
)

◆ W_AttachToShotorg()

void W_AttachToShotorg ( entity  actor,
.entity  weaponentity,
entity  flash,
vector  offset 
)

Definition at line 660 of file weaponsystem.qc.

References copyentity(), entity(), gettagindex, random(), setorigin(), and spawn().

661 {
662  flash.owner = actor;
663  flash.angles_z = random() * 360;
664 
665  entity w_ent = actor.(weaponentity);
666  entity exterior = actor.exteriorweaponentity;
667 
668  if (gettagindex(w_ent, "shot")) setattachment(flash, w_ent, "shot");
669  else setattachment(flash, w_ent, "tag_shot");
670  setorigin(flash, offset);
671 
672  entity xflash = spawn();
673  copyentity(flash, xflash);
674 
675  flash.viewmodelforclient = actor;
676 
677  if (w_ent.oldorigin.x > 0)
678  {
679  setattachment(xflash, exterior, "");
680  setorigin(xflash, w_ent.oldorigin + offset);
681  }
682  else
683  {
684  if (gettagindex(exterior, "shot")) setattachment(xflash, exterior, "shot");
685  else setattachment(xflash, exterior, "tag_shot");
686  setorigin(xflash, offset);
687  }
688 }
entity() spawn
#define gettagindex
Definition: dpextensions.qh:16
setorigin(ent, v)
+ Here is the call graph for this function:

◆ w_clear()

void w_clear ( Weapon  thiswep,
entity  actor,
.entity  weaponentity,
int  fire 
)

Definition at line 208 of file weaponsystem.qc.

References entity(), and WS_CLEAR.

Referenced by W_WeaponFrame().

209 {
210  entity w_ent = actor.(weaponentity);
211  if (w_ent)
212  {
213  w_ent.m_weapon = WEP_Null;
214  w_ent.m_switchingweapon = WEP_Null;
215  w_ent.state = WS_CLEAR;
216  w_ent.effects = 0;
217  }
218 }
const int WS_CLEAR
no weapon selected
Definition: weapon.qh:30
entity() spawn
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ W_DecreaseAmmo()

void W_DecreaseAmmo ( Weapon  wep,
entity  actor,
float  ammo_use,
.entity  weaponentity 
)

Definition at line 690 of file weaponsystem.qc.

References ammo, Weapon::ammo_type, backtrace, entity(), GetAmmoPicture(), GetResource(), M_ARGV, MUTATOR_CALLHOOK, Weapon::netname, SetResource(), and W_DecreaseAmmo().

Referenced by W_DecreaseAmmo().

691 {
692  if (MUTATOR_CALLHOOK(W_DecreaseAmmo, actor, actor.(weaponentity), ammo_use)) return;
693  if ((actor.items & IT_UNLIMITED_AMMO) && !wep.reloading_ammo) return;
694 
695  ammo_use = M_ARGV(2, float);
696 
697  entity w_ent = actor.(weaponentity);
698 
699  // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
700  if (wep.reloading_ammo)
701  {
702  w_ent.clip_load -= ammo_use;
703  w_ent.(weapon_load[w_ent.m_weapon.m_id]) = w_ent.clip_load;
704  }
705  else if (wep.ammo_type != RES_NONE)
706  {
707  float ammo = GetResource(actor, wep.ammo_type);
708  if (ammo < ammo_use)
709  {
710  backtrace(sprintf(
711  "W_DecreaseAmmo(%.2f): '%s' subtracted too much %s from '%s', resulting with '%.2f' left... "
712  "Please notify the developers immediately with a copy of this backtrace!\n",
713  ammo_use, wep.netname, GetAmmoPicture(wep.ammo_type), actor.netname, ammo));
714  }
715  SetResource(actor, wep.ammo_type, ammo - ammo_use);
716  }
717 }
string GetAmmoPicture(Resource ammotype)
Definition: all.qc:206
entity() spawn
string netname
M: refname : reference name name.
Definition: weapon.qh:76
float ammo
Definition: sv_turrets.qh:44
void SetResource(entity e, Resource res_type, float amount)
Sets the current amount of resource the given entity will have.
Definition: cl_resources.qc:26
Resource ammo_type
M: ammotype : main ammo type.
Definition: weapon.qh:48
#define backtrace(msg)
Definition: log.qh:105
#define M_ARGV(x, type)
Definition: events.qh:17
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
Definition: cl_resources.qc:10
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use,.entity weaponentity)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ W_DropEvent()

void W_DropEvent ( .void(Weapon, entity actor,.entity event,
entity  player,
float  weapon_type,
entity  weapon_item,
.entity  weaponentity 
)

Definition at line 836 of file weaponsystem.qc.

References REGISTRY_GET, and weapon_dropevent_item.

Referenced by W_ThrowNewWeapon().

837 {
838  Weapon w = REGISTRY_GET(Weapons, weapon_type);
839  weapon_dropevent_item = weapon_item;
840  w.event(w, player, weaponentity);
841 }
#define REGISTRY_GET(id, i)
Definition: registry.qh:43
entity weapon_dropevent_item
Definition: weaponsystem.qh:21
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition: weapon.qh:41
+ Here is the caller graph for this function:

◆ w_ready()

void w_ready ( Weapon  thiswep,
entity  actor,
.entity  weaponentity,
int  fire 
)

Definition at line 220 of file weaponsystem.qc.

References entity(), w_ready(), weapon_thinkf(), and WS_READY.

Referenced by w_ready(), W_ReloadedAndReady(), W_WeaponFrame(), and weapon_thinkf().

221 {
222  entity w_ent = actor.(weaponentity);
223  if (w_ent) w_ent.state = WS_READY;
224  weapon_thinkf(actor, weaponentity, WFRAME_IDLE, 1000000, w_ready);
225 }
entity() spawn
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)
const int WS_READY
idle frame
Definition: weapon.qh:38
void weapon_thinkf(entity actor,.entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,.entity weaponentity, int fire) func)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ W_Reload()

void W_Reload ( entity  actor,
.entity  weaponentity,
float  sent_ammo_min,
Sound  sent_sound 
)

Definition at line 758 of file weaponsystem.qc.

References _sound, ATTEN_NORM, autocvar_g_weaponswitch_debug, CH_WEAPON_SINGLE, clip_load, entity(), GetResource(), IS_REAL_CLIENT, LOG_TRACE, MUTATOR_CALLHOOK, old_clip_load, reload_ammo_amount, SND, Sound_fixpath, sprint(), state, strcat(), strcpy, TC, time, VOL_BASE, W_Reload(), W_ReloadedAndReady(), W_SwitchToOtherWeapon(), weapon_load, weapon_thinkf(), weaponslot(), WEP_FLAG_RELOADABLE, and WS_READY.

Referenced by W_Reload().

759 {
760  TC(Sound, sent_sound);
761  // set global values to work with
762  entity this = actor.(weaponentity);
763  Weapon e = this.m_weapon;
764 
765  if (MUTATOR_CALLHOOK(W_Reload, actor)) return;
766 
767  this.reload_ammo_min = sent_ammo_min;
768  this.reload_ammo_amount = e.reloading_ammo;
769  this.reload_time = e.reloading_time;
770  strcpy(actor.reload_sound, Sound_fixpath(sent_sound));
771 
772  // don't reload weapons that don't have the RELOADABLE flag
773  if (!(e.spawnflags & WEP_FLAG_RELOADABLE))
774  {
775  LOG_TRACE(
776  "Warning: Attempted to reload a weapon that does not have the WEP_FLAG_RELOADABLE flag. Fix your code!\n");
777  return;
778  }
779 
780  // return if reloading is disabled for this weapon
781  if (!this.reload_ammo_amount) return;
782 
783  // our weapon is fully loaded, no need to reload
784  if (this.clip_load >= this.reload_ammo_amount) return;
785 
786  // no ammo, so nothing to load
787  if (e.ammo_type != RES_NONE)
788  {
789  if (!GetResource(actor, e.ammo_type) && this.reload_ammo_min)
790  {
791  if (!(actor.items & IT_UNLIMITED_AMMO))
792  {
793  if (autocvar_g_weaponswitch_debug == 2 && weaponslot(weaponentity) > 0)
794  return; // in this case the primary weapon will do the switching when it runs out of ammo (TODO: do this same check but for other slots)
795  if (IS_REAL_CLIENT(actor) && actor.reload_complain < time)
796  {
797  play2(actor, SND(UNAVAILABLE));
798  sprint(actor, strcat("You don't have enough ammo to reload the ^2", this.m_weapon.m_name, "\n"));
799  actor.reload_complain = time + 1;
800  }
801  // switch away if the amount of ammo is not enough to keep using this weapon
802  if (!(e.wr_checkammo1(e, actor, weaponentity) + e.wr_checkammo2(e, actor, weaponentity)))
803  {
804  this.clip_load = -1; // reload later
805  W_SwitchToOtherWeapon(actor, weaponentity);
806  }
807  return;
808  }
809  }
810  }
811  if (this)
812  {
813  if (this.wframe == WFRAME_RELOAD) return;
814 
815  // allow switching away while reloading, but this will cause a new reload!
816  this.state = WS_READY;
817  }
818 
819  // now begin the reloading process
820 
821  _sound(actor, CH_WEAPON_SINGLE, actor.reload_sound, VOL_BASE, ATTEN_NORM);
822 
823  // do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon,
824  // then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
825  // so your weapon is disabled for a few seconds without reason
826 
827  // ATTACK_FINISHED(actor, weaponentity) = max(time, ATTACK_FINISHED(actor, weaponentity)) + this.reload_time + 1;
828 
829  weapon_thinkf(actor, weaponentity, WFRAME_RELOAD, this.reload_time, W_ReloadedAndReady);
830 
831  if (this.clip_load < 0) this.clip_load = 0;
832  this.old_clip_load = this.clip_load;
833  this.clip_load = this.(weapon_load[this.m_weapon.m_id]) = -1;
834 }
float weapon_load[REGISTRY_MAX(Weapons)]
Definition: weaponsystem.qh:29
const int WEP_FLAG_RELOADABLE
Definition: weapon.qh:201
#define SND(id)
Definition: all.qh:35
void W_SwitchToOtherWeapon(entity this,.entity weaponentity)
Definition: selection.qc:253
#define Sound_fixpath(this)
Definition: sound.qh:141
entity() spawn
void W_ReloadedAndReady(Weapon thiswep, entity actor,.entity weaponentity, int fire)
const int WS_READY
idle frame
Definition: weapon.qh:38
int clip_load
Definition: wepent.qh:14
#define IS_REAL_CLIENT(v)
Definition: utils.qh:17
int weaponslot(.entity weaponentity)
Definition: weapon.qh:16
#define strcpy(this, s)
Definition: string.qh:49
int state
Definition: weaponsystem.qc:29
bool autocvar_g_weaponswitch_debug
Definition: selection.qh:7
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"))
const int CH_WEAPON_SINGLE
Definition: sound.qh:9
const float VOL_BASE
Definition: sound.qh:36
#define TC(T, sym)
Definition: _all.inc:82
Definition: sound.qh:119
const float ATTEN_NORM
Definition: sound.qh:30
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
Definition: cl_resources.qc:10
float reload_ammo_min
#define LOG_TRACE(...)
Definition: log.qh:81
void weapon_thinkf(entity actor,.entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,.entity weaponentity, int fire) func)
#define _sound(e, c, s, v, a)
Definition: sound.qh:50
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
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
float reload_ammo_amount
int old_clip_load
Definition: weaponsystem.qh:32
void W_Reload(entity actor,.entity weaponentity, float sent_ammo_min, Sound sent_sound)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ W_ResetGunAlign()

void W_ResetGunAlign ( entity  player,
int  preferred_alignment 
)

Definition at line 436 of file weaponsystem.qc.

References MAX_WEAPONSLOTS, W_DualWielding(), W_GunAlign(), and weaponentities.

Referenced by PlayerThink(), and PutPlayerInServer().

437 {
438  if(W_DualWielding(player))
439  preferred_alignment = 3; // right align, the second gun will default to left
440 
441  // clear current weapon slots' alignments so we can redo the calculations!
442  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
443  {
444  .entity weaponentity = weaponentities[slot];
445  if (player.(weaponentity))
446  player.(weaponentity).m_gunalign = 0;
447  }
448 
449  // now set the new values
450  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
451  {
452  .entity weaponentity = weaponentities[slot];
453  if (player.(weaponentity))
454  player.(weaponentity).m_gunalign = W_GunAlign(player.(weaponentity), preferred_alignment);
455  }
456 }
int W_GunAlign(entity this, int preferred_align)
bool W_DualWielding(entity player)
Definition: common.qc:20
const int MAX_WEAPONSLOTS
Definition: weapon.qh:13
entity weaponentities[MAX_WEAPONSLOTS]
Definition: weapon.qh:14
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ W_WeaponFrame()

void W_WeaponFrame ( Player  actor,
.entity  weaponentity 
)

Definition at line 460 of file weaponsystem.qc.

References ATTACK_FINISHED, ATTN_NORM, autocvar_g_weaponswitch_debug, bprint(), bulletcounter, CH_WEAPON_SINGLE, clip_load, clip_size, entity(), frametime, GetResource(), INDEPENDENT_ATTACK_FINISHED, IS_PLAYER, LOG_WARNF, Weapon::mdl, Client::netname, OFFHAND_HOOK, old_clip_load, PHYS_INPUT_BUTTON_ATCK, PHYS_INPUT_BUTTON_ATCK2, PHYS_INPUT_BUTTON_HOOK, PS, RES_HEALTH, sound, Weapon::spawnflags, state, TC, time, Client::v_angle, v_forward, v_right, v_up, vector(), VOL_BASE, w_clear(), w_getbestweapon, w_ready(), W_SwitchWeapon(), W_SwitchWeapon_Force(), W_TICSPERFRAME, weapon_frametime, weapon_load, weapon_nextthink, weapon_thinkf(), weaponentities, weaponLocked(), weaponslot(), weaponUseForbidden(), WEP_FLAG_DUALWIELD, WEP_FLAG_RELOADABLE, WEPSET, WepSet_FromWeapon, WS_CLEAR, WS_DROP, WS_INUSE, WS_RAISE, and WS_READY.

Referenced by PlayerThink(), and PutPlayerInServer().

461 {
462  TC(Player, actor);
463  TC(PlayerState, PS(actor));
464  entity this = actor.(weaponentity);
466 
467  if (!this || GetResource(actor, RES_HEALTH) < 1) return; // Dead player can't use weapons and injure impulse commands
468 
469  int button_atck = PHYS_INPUT_BUTTON_ATCK(actor);
470  int button_atck2 = PHYS_INPUT_BUTTON_ATCK2(actor);
471 
472  if (weaponUseForbidden(actor))
473  button_atck = button_atck2 = 0; // forbid primary and secondary fire, switching is allowed
474 
475  if (weaponLocked(actor))
476  {
477  if (this.state != WS_CLEAR)
478  {
479  Weapon wpn = this.m_weapon;
480  w_ready(wpn, actor, weaponentity, button_atck | (button_atck2 << 1));
481  return;
482  }
483  }
484 
485  if(autocvar_g_weaponswitch_debug == 2 && weaponslot(weaponentity) > 0)
486  {
487  .entity wepe1 = weaponentities[0];
488  entity wep1 = actor.(wepe1);
489  this.m_switchweapon = wep1.m_switchweapon;
490  entity store = IS_PLAYER(actor) ? PS(actor) : actor;
491  if(!(this.m_switchweapon.spawnflags & WEP_FLAG_DUALWIELD) && !(store.dual_weapons & wep1.m_switchweapon.m_wepset))
492  {
493  this.m_weapon = WEP_Null;
494  this.m_switchingweapon = WEP_Null;
495  this.m_switchweapon = WEP_Null;
496  this.state = WS_CLEAR;
497  this.weaponname = "";
498  this.clip_load = this.clip_size = this.old_clip_load = 0;
499  return;
500  }
501  }
502 
503  if (this.m_switchweapon == WEP_Null)
504  {
505  if (this.state != WS_CLEAR)
506  w_ready(this.m_weapon, actor, weaponentity, button_atck | (button_atck2 << 1));
507  this.m_weapon = WEP_Null;
508  this.m_switchingweapon = WEP_Null;
509  this.state = WS_CLEAR;
510  this.weaponname = "";
511  this.clip_load = this.clip_size = this.old_clip_load = 0;
512  return;
513  }
514 
515  vector fo, ri, up;
516  MAKE_VECTORS(actor.v_angle, fo, ri, up);
517 
518  // Change weapon
519  if (this.m_weapon != this.m_switchweapon)
520  {
521  switch (this.state)
522  {
523  default:
524  LOG_WARNF("unhandled weaponentity (%i) state for player (%i): %d", this, actor, this.state);
525  break;
526  case WS_INUSE:
527  case WS_RAISE:
528  break;
529  case WS_CLEAR:
530  {
531  // end switching!
532  Weapon newwep = this.m_switchweapon;
533  this.m_switchingweapon = newwep;
534 
535  // the two weapon entities will notice this has changed and update their models
536  this.m_weapon = newwep;
537  this.weaponname = newwep.mdl;
538  this.bulletcounter = 0;
539  newwep.wr_setup(newwep, actor, weaponentity);
540  this.state = WS_RAISE;
541 
542  // set our clip load to the load of the weapon we switched to, if it's reloadable
543  if ((newwep.spawnflags & WEP_FLAG_RELOADABLE) && newwep.reloading_ammo) // prevent accessing undefined cvars
544  {
545  this.clip_load = this.(weapon_load[this.m_switchweapon.m_id]);
546  this.clip_size = newwep.reloading_ammo;
547  }
548  else
549  {
550  this.clip_load = this.clip_size = 0;
551  }
552 
553  weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, newwep.switchdelay_raise, w_ready);
554  break;
555  }
556  case WS_DROP:
557  {
558  // in dropping phase we can switch at any time
559  this.m_switchingweapon = this.m_switchweapon;
560  break;
561  }
562  case WS_READY:
563  {
564  // start switching!
565  this.m_switchingweapon = this.m_switchweapon;
566  entity oldwep = this.m_weapon;
567 
568  // set up weapon switch think in the future, and start drop anim
569  if (INDEPENDENT_ATTACK_FINISHED || ATTACK_FINISHED(actor, weaponentity) <= time + this.weapon_frametime * 0.5)
570  {
571  sound(actor, CH_WEAPON_SINGLE, SND_WEAPON_SWITCH, VOL_BASE, ATTN_NORM);
572  this.state = WS_DROP;
573  weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, oldwep.switchdelay_drop, w_clear);
574  }
575  break;
576  }
577  }
578  }
579 
580  // LordHavoc: network timing test code
581  // if (actor.button0)
582  // print(ftos(frametime), " ", ftos(time), " >= ", ftos(ATTACK_FINISHED(actor, weaponentity)), " >= ", ftos(this.weapon_nextthink), "\n");
583 
584  Weapon w = this.m_weapon;
585 
586  // call the think code which may fire the weapon
587  // and do so multiple times to resolve framerate dependency issues if the
588  // server framerate is very low and the weapon fire rate very high
589  for (int c = 0; c < W_TICSPERFRAME; ++c)
590  {
591  if (w != WEP_Null && !(STAT(WEAPONS, actor) & WepSet_FromWeapon(w)))
592  {
593  if (this.m_weapon == this.m_switchweapon)
594  W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
595  w = WEP_Null;
596  }
597 
598  v_forward = fo;
599  v_right = ri;
600  v_up = up;
601 
602  bool block_weapon = false;
603  {
604  bool key_pressed = PHYS_INPUT_BUTTON_HOOK(actor) && !actor.vehicle;
605  if (weaponUseForbidden(actor))
606  key_pressed = false;
607 
608  Weapon off = actor.offhand;
609  if (off && (!(STAT(WEAPONS, actor) & WEPSET(HOOK)) || off != OFFHAND_HOOK))
610  {
611  if (off.offhand_think) off.offhand_think(off, actor, key_pressed);
612  }
613  else
614  {
615  if (key_pressed && this.m_switchweapon != WEP_HOOK && !actor.hook_switchweapon)
616  W_SwitchWeapon(actor, WEP_HOOK, weaponentity);
617  actor.hook_switchweapon = key_pressed;
618  Weapon h = WEP_HOOK;
619  block_weapon = (this.m_weapon == h && (button_atck || key_pressed));
620  h.wr_think(h, actor, weaponentity, block_weapon ? 1 : 0);
621  }
622  }
623 
624  v_forward = fo;
625  v_right = ri;
626  v_up = up;
627 
628  if (!block_weapon)
629  {
630  Weapon e = this.m_weapon;
631  TC(Weapon, e);
632  if (w != WEP_Null)
633  {
634  e.wr_think(e, actor, weaponentity, button_atck | (button_atck2 << 1));
635  }
636  else if (e)
637  {
638  e.wr_gonethink(e, actor, weaponentity);
639  }
640  }
641 
642  if (time + this.weapon_frametime * 0.5 >= this.weapon_nextthink)
643  {
644  if (this.weapon_think)
645  {
646  v_forward = fo;
647  v_right = ri;
648  v_up = up;
649  Weapon wpn = this.m_weapon;
650  this.weapon_think(wpn, actor, weaponentity, button_atck | (button_atck2 << 1));
651  }
652  else
653  {
654  bprint("\{1}^1ERROR: undefined weapon think function for ", actor.netname, "\n");
655  }
656  }
657  }
658 }
#define PHYS_INPUT_BUTTON_ATCK2(s)
Definition: player.qh:148
OffhandHook OFFHAND_HOOK
Definition: hook.qh:67
#define WEPSET(id)
Definition: all.qh:37
float weapon_load[REGISTRY_MAX(Weapons)]
Definition: weaponsystem.qh:29
float weapon_frametime
Definition: weaponsystem.qc:31
const int WEP_FLAG_RELOADABLE
Definition: weapon.qh:201
void W_SwitchWeapon_Force(Player this, Weapon w,.entity weaponentity)
Definition: selection.qc:243
const int WS_RAISE
raise frame
Definition: weapon.qh:32
#define PHYS_INPUT_BUTTON_HOOK(s)
Definition: player.qh:151
bool weaponUseForbidden(entity player)
#define w_getbestweapon(ent, wepent)
Definition: selection.qh:23
const int WS_CLEAR
no weapon selected
Definition: weapon.qh:30
entity() spawn
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)
#define PS(this)
Definition: state.qh:18
vector v_angle
Definition: client.qh:144
const int WS_DROP
deselecting frame
Definition: weapon.qh:34
const int WS_READY
idle frame
Definition: weapon.qh:38
int clip_load
Definition: wepent.qh:14
float weapon_nextthink
Definition: view.qc:273
float bulletcounter
Definition: weaponsystem.qh:25
int clip_size
Definition: wepent.qh:15
int weaponslot(.entity weaponentity)
Definition: weapon.qh:16
#define INDEPENDENT_ATTACK_FINISHED
Definition: weaponsystem.qh:11
const float ATTN_NORM
Definition: csprogsdefs.qc:226
#define LOG_WARNF(...)
Definition: log.qh:67
int spawnflags
M: flags : WEPSPAWNFLAG_...
Definition: weapon.qh:52
RES_HEALTH
Definition: ent_cs.qc:126
bool weaponLocked(entity player)
int state
Definition: weaponsystem.qc:29
bool autocvar_g_weaponswitch_debug
Definition: selection.qh:7
vector v_up
Definition: csprogsdefs.qc:31
const int CH_WEAPON_SINGLE
Definition: sound.qh:9
float frametime
Definition: csprogsdefs.qc:17
const float VOL_BASE
Definition: sound.qh:36
#define TC(T, sym)
Definition: _all.inc:82
#define PHYS_INPUT_BUTTON_ATCK(s)
Definition: player.qh:146
Purpose: common player state, usable on client and server Client: singleton representing the viewed p...
Definition: state.qh:8
vector(float skel, float bonenum) _skel_get_boneabs_hidden
const int WS_INUSE
fire state
Definition: weapon.qh:36
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
Definition: cl_resources.qc:10
void weapon_thinkf(entity actor,.entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,.entity weaponentity, int fire) func)
bool W_SwitchWeapon(entity this, Weapon w,.entity weaponentity)
Definition: selection.qc:272
vector v_right
Definition: csprogsdefs.qc:31
entity weaponentities[MAX_WEAPONSLOTS]
Definition: weapon.qh:14
void w_clear(Weapon thiswep, entity actor,.entity weaponentity, int fire)
#define ATTACK_FINISHED(ent, w)
Definition: weaponsystem.qh:42
#define WepSet_FromWeapon(it)
Definition: all.qh:38
#define sound(e, c, s, v, a)
Definition: sound.qh:52
const int WEP_FLAG_DUALWIELD
Definition: weapon.qh:206
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
string netname
Client name.
Definition: client.qh:90
string mdl
M: modelname : name of model (without g_ v_ or h_ prefixes)
Definition: weapon.qh:58
int old_clip_load
Definition: weaponsystem.qh:32
#define IS_PLAYER(v)
Definition: utils.qh:9
const int W_TICSPERFRAME
Definition: weaponsystem.qh:14
vector v_forward
Definition: csprogsdefs.qc:31
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ W_WeaponRateFactor()

float W_WeaponRateFactor ( entity  this)

Definition at line 33 of file weaponsystem.qc.

References autocvar_g_weaponratefactor, M_ARGV, and MUTATOR_CALLHOOK.

Referenced by weapon_prepareattack_do(), and weapon_thinkf().

34 {
35  float t = 1;
38 
39  MUTATOR_CALLHOOK(WeaponRateFactor, t, this);
40  t = M_ARGV(0, float);
41 
42  return t;
43 }
float autocvar_g_weaponratefactor
Definition: weaponsystem.qh:8
#define M_ARGV(x, type)
Definition: events.qh:17
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
+ Here is the caller graph for this function:

◆ W_WeaponSpeedFactor()

float W_WeaponSpeedFactor ( entity  this)

Definition at line 45 of file weaponsystem.qc.

References autocvar_g_weaponspeedfactor, M_ARGV, and MUTATOR_CALLHOOK.

Referenced by bot_aim(), and W_CalculateProjectileVelocity().

46 {
47  float t = 1.0 * autocvar_g_weaponspeedfactor;
48 
49  MUTATOR_CALLHOOK(WeaponSpeedFactor, t, this);
50  t = M_ARGV(0, float);
51 
52  return t;
53 }
#define M_ARGV(x, type)
Definition: events.qh:17
float autocvar_g_weaponspeedfactor
Definition: weaponsystem.qh:9
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
+ Here is the caller graph for this function:

◆ weapon_prepareattack()

bool weapon_prepareattack ( Weapon  thiswep,
entity  actor,
.entity  weaponentity,
bool  secondary,
float  attacktime 
)

Definition at line 342 of file weaponsystem.qc.

References weapon_prepareattack_check(), and weapon_prepareattack_do().

343 {
344  if (weapon_prepareattack_check(thiswep, actor, weaponentity, secondary, attacktime))
345  {
346  weapon_prepareattack_do(actor, weaponentity, secondary, attacktime);
347  return true;
348  }
349  return false;
350 }
bool weapon_prepareattack_check(Weapon thiswep, entity actor,.entity weaponentity, bool secondary, float attacktime)
void weapon_prepareattack_do(entity actor,.entity weaponentity, bool secondary, float attacktime)
+ Here is the call graph for this function:

◆ weapon_prepareattack_check()

bool weapon_prepareattack_check ( Weapon  thiswep,
entity  actor,
.entity  weaponentity,
float  secondary,
float  attacktime 
)

◆ weapon_prepareattack_do()

void weapon_prepareattack_do ( entity  actor,
.entity  weaponentity,
float  secondary,
float  attacktime 
)

◆ weapon_thinkf()

void weapon_thinkf ( entity  actor,
.entity  weaponentity,
WFRAME  fr,
float  t,
void(Weapon thiswep, entity actor,.entity weaponentity, int fire)  func 
)
Parameters
tdefer thinking until time + t
funcnext think function

Definition at line 356 of file weaponsystem.qc.

References ANIMACTION_MELEE, ANIMACTION_SHOOT, animdecide_setaction(), autocvar_g_weaponratefactor, backtrace, boolean, entity(), FOREACH_CLIENT, IS_SPEC, NULL, state, time, w_ready(), W_WeaponRateFactor(), weapon_frametime, weapon_nextthink, WEP_TYPE_MELEE_PRI, WEP_TYPE_MELEE_SEC, and WS_RAISE.

Referenced by w_ready(), W_Reload(), and W_WeaponFrame().

358 {
359  entity this = actor.(weaponentity);
360  if (this == NULL) return;
361  bool restartanim;
362  if (fr == WFRAME_DONTCHANGE)
363  {
364  // this can happen when the weapon entity is newly spawned, since it has a clear state and no previous weapon frame
365  if (this.wframe == WFRAME_DONTCHANGE)
366  this.wframe = WFRAME_IDLE;
367  fr = this.wframe;
368  restartanim = false;
369  }
370  else
371  {
372  restartanim = fr != WFRAME_IDLE;
373  }
374 
375  this.wframe = fr;
376 
377  if (this.weapon_think == w_ready && func != w_ready && this.state == WS_RAISE)
378  backtrace("Tried to override initial weapon think function - should this really happen?");
379 
380  t *= W_WeaponRateFactor(actor);
381 
382  // VorteX: haste can be added here
383  if (this.weapon_think == w_ready)
384  {
385  this.weapon_nextthink = time;
386  // dprint("started firing at ", ftos(time), "\n");
387  }
388  float w_frametime_limit = this.weapon_frametime * 1.5;
389  if (this.weapon_nextthink < time - w_frametime_limit || this.weapon_nextthink > time + w_frametime_limit)
390  {
391  this.weapon_nextthink = time;
392  // dprint("reset weapon animation timer at ", ftos(time), "\n");
393  }
394  this.weapon_nextthink += t;
395  this.weapon_think = func;
396  // dprint("next ", ftos(this.weapon_nextthink), "\n");
397 
398  if (this)
399  {
400  FOREACH_CLIENT(true, {
401  if(it == actor || (IS_SPEC(it) && it.enemy == actor))
402  wframe_send(it, this, fr, autocvar_g_weaponratefactor, restartanim);
403  });
404  }
405 
406  if ((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t)
407  {
408  bool primary_melee = boolean(fr == WFRAME_FIRE1 && (this.m_weapon.spawnflags & WEP_TYPE_MELEE_PRI));
409  bool secondary_melee = boolean(fr == WFRAME_FIRE2 && (this.m_weapon.spawnflags & WEP_TYPE_MELEE_SEC));
410  int act = (primary_melee || secondary_melee) ? ANIMACTION_MELEE : ANIMACTION_SHOOT;
411  animdecide_setaction(actor, act, restartanim);
412  }
413  else if (actor.anim_upper_action == ANIMACTION_SHOOT || actor.anim_upper_action == ANIMACTION_MELEE)
414  {
415  actor.anim_upper_action = 0;
416  }
417 }
float weapon_frametime
Definition: weaponsystem.qc:31
float autocvar_g_weaponratefactor
Definition: weaponsystem.qh:8
const int WS_RAISE
raise frame
Definition: weapon.qh:32
entity() spawn
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)
float weapon_nextthink
Definition: view.qc:273
#define IS_SPEC(v)
Definition: utils.qh:10
int state
Definition: weaponsystem.qc:29
void animdecide_setaction(entity e, float action, float restart)
Definition: animdecide.qc:338
const int WEP_TYPE_MELEE_SEC
Definition: weapon.qh:205
#define NULL
Definition: post.qh:17
#define backtrace(msg)
Definition: log.qh:105
const int ANIMACTION_SHOOT
Definition: animdecide.qh:145
const int ANIMACTION_MELEE
Definition: animdecide.qh:147
float time
Definition: csprogsdefs.qc:16
float W_WeaponRateFactor(entity this)
Definition: weaponsystem.qc:33
#define boolean(value)
Definition: bool.qh:9
const int WEP_TYPE_MELEE_PRI
Definition: weapon.qh:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ weaponLocked()

bool weaponLocked ( entity  player)

Definition at line 426 of file weaponsystem.qc.

References MUTATOR_CALLHOOK, sv_ready_restart_after_countdown, and time.

Referenced by FireGrapplingHook(), IMPULSE(), MUTATOR_HOOKFUNCTION(), vehicles_touch(), W_SwitchWeapon(), and W_WeaponFrame().

427 {
428  if (time < game_starttime && !sv_ready_restart_after_countdown) return true;
429  if (player.player_blocked) return true;
430  if (game_stopped) return true;
431  if (STAT(FROZEN, player)) return true;
432  if (MUTATOR_CALLHOOK(LockWeapon, player)) return true;
433  return false;
434 }
bool sv_ready_restart_after_countdown
Definition: world.qh:119
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
float time
Definition: csprogsdefs.qc:16
+ Here is the caller graph for this function:

◆ weaponUseForbidden()

bool weaponUseForbidden ( entity  player)

Definition at line 419 of file weaponsystem.qc.

References MUTATOR_CALLHOOK, round_handler_IsActive, and round_handler_IsRoundStarted.

Referenced by W_WeaponFrame().

420 {
421  if (round_handler_IsActive() && !round_handler_IsRoundStarted()) return true;
422  if (MUTATOR_CALLHOOK(ForbidWeaponUse, player)) return true;
423  return false;
424 }
#define round_handler_IsActive()
#define round_handler_IsRoundStarted()
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
+ Here is the caller graph for this function:

Variable Documentation

◆ ammo_none

int ammo_none

Definition at line 30 of file weaponsystem.qh.

◆ attack_finished_for

float attack_finished_for[REGISTRY_MAX(Weapons) *MAX_WEAPONSLOTS]

Definition at line 35 of file weaponsystem.qh.

◆ attack_finished_single

◆ autocvar_g_weapondamagefactor

float autocvar_g_weapondamagefactor

Definition at line 7 of file weaponsystem.qh.

Referenced by Damage().

◆ autocvar_g_weaponforcefactor

float autocvar_g_weaponforcefactor

Definition at line 6 of file weaponsystem.qh.

Referenced by Damage().

◆ autocvar_g_weaponratefactor

float autocvar_g_weaponratefactor

Definition at line 8 of file weaponsystem.qh.

Referenced by W_WeaponRateFactor(), and weapon_thinkf().

◆ autocvar_g_weaponspeedfactor

float autocvar_g_weaponspeedfactor

Definition at line 9 of file weaponsystem.qh.

Referenced by W_WeaponSpeedFactor().

◆ autocvar_g_weaponspreadfactor

float autocvar_g_weaponspreadfactor

Definition at line 5 of file weaponsystem.qh.

Referenced by W_SetupProjVelocity_Explicit().

◆ bulletcounter

float bulletcounter

Definition at line 25 of file weaponsystem.qh.

Referenced by W_WeaponFrame(), and weapon_prepareattack_do().

◆ clip_load

int clip_load

Definition at line 31 of file weaponsystem.qh.

◆ clip_size

int clip_size

Definition at line 33 of file weaponsystem.qh.

◆ internalteam

float internalteam

Definition at line 20 of file weaponsystem.qh.

Referenced by weapon_defaultspawnfunc().

◆ old_clip_load

int old_clip_load

Definition at line 32 of file weaponsystem.qh.

Referenced by W_Reload(), and W_WeaponFrame().

◆ W_TICSPERFRAME

const int W_TICSPERFRAME = 2

Definition at line 14 of file weaponsystem.qh.

Referenced by PlayerThink(), and W_WeaponFrame().

◆ weapon_dropevent_item

entity weapon_dropevent_item

Definition at line 21 of file weaponsystem.qh.

Referenced by W_DropEvent().

◆ weapon_load

◆ weapon_nextthink

float weapon_nextthink

Definition at line 17 of file weaponsystem.qh.

◆ weaponentity_fld