Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
shotgun.qc File Reference
#include "shotgun.qh"
#include <common/items/item/ammo.qh>
Include dependency graph for shotgun.qc:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void W_Shotgun_Attack (Weapon thiswep, entity actor,.entity weaponentity, float isprimary, float ammocount, float damage, float falloff_halflife, float falloff_mindist, float falloff_maxdist, float bullets, float spread, float spread_pattern, float spread_pattern_scale, float spread_pattern_bias, float solidpenetration, float force, float falloff_forcehalflife, entity bullet_trail_effect)
void W_Shotgun_Attack2 (Weapon thiswep, entity actor,.entity weaponentity, int fire)
void W_Shotgun_Attack3_Frame1 (Weapon thiswep, entity actor,.entity weaponentity, int fire)
void W_Shotgun_Attack3_Frame2 (Weapon thiswep, entity actor,.entity weaponentity, int fire)
void W_Shotgun_Melee_Think (entity this)

Variables

float prevric
float shotgun_primarytime
entity swing_alreadyhit
float swing_prev

Function Documentation

◆ W_Shotgun_Attack()

void W_Shotgun_Attack ( Weapon thiswep,
entity actor,
.entity weaponentity,
float isprimary,
float ammocount,
float damage,
float falloff_halflife,
float falloff_mindist,
float falloff_maxdist,
float bullets,
float spread,
float spread_pattern,
float spread_pattern_scale,
float spread_pattern_bias,
float solidpenetration,
float force,
float falloff_forcehalflife,
entity bullet_trail_effect )

Definition at line 8 of file shotgun.qc.

16{
17 W_DecreaseAmmo(thiswep, actor, ammocount, weaponentity);
18
19 W_SetupShot(actor, weaponentity, true, 5, SND_SHOTGUN_FIRE,
20 ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), damage * bullets, thiswep.m_id);
21
22 // TRICK: do the antilag outside the regular fireBullet function,
23 // so it isn't performed unnecessarily on every single bullet!
24 float lag = antilag_getlag(actor);
25 if(lag && bullets > 0)
26 antilag_takeback_all(actor, lag);
27
28 if (spread_pattern && spread_pattern_scale > 0)
29 {
30 vector right, up;
31 right = v_right;
32 up = v_up;
33
34 float fixed_spread_factor = (spread * autocvar_g_weaponspreadfactor) / spread_pattern_scale;
35 spread_pattern_bias = bound(0, spread_pattern_bias, 1);
36 for(int sc = 0; sc < bullets; ++sc)
37 {
38 vector s = W_CalculateSpreadPattern(spread_pattern, spread_pattern_bias, sc, bullets);
39 s = s * fixed_spread_factor;
40 fireBullet_falloff(actor, weaponentity,
41 w_shotorg, w_shotdir + right * s.y + up * s.z,
42 0, solidpenetration, damage,
43 falloff_halflife, falloff_mindist, falloff_maxdist,
44 0, force, falloff_forcehalflife,
45 thiswep.m_id, bullet_trail_effect, false);
46 }
47 }
48 else
49 for(int sc = 0; sc < bullets; ++sc)
50 fireBullet_falloff(actor, weaponentity,
52 spread, solidpenetration, damage,
53 falloff_halflife, falloff_mindist, falloff_maxdist,
54 0, force, falloff_forcehalflife,
55 thiswep.m_id, bullet_trail_effect, false);
56
57 if(lag && bullets > 0)
59
60 W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
61
62 // casing code
63 if(autocvar_g_casings >= 1)
64 {
65 makevectors(actor.v_angle); // for some reason, this is lost
66 //for(int sc = 0; sc < WEP_CVAR_PRI(WEP_SHOTGUN, ammo); ++sc)
67 SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 30) * v_up), vectoangles(v_forward), 1, actor, weaponentity);
68 }
69}
void antilag_takeback_all(entity ignore, float lag)
Definition antilag.qc:125
float antilag_getlag(entity e)
Definition antilag.qc:151
void antilag_restore_all(entity ignore)
Definition antilag.qc:138
vector W_CalculateSpreadPattern(int pattern, float bias, int counter, int total)
float autocvar_g_weaponspreadfactor
void SpawnCasing(vector vel, vector ang, int casingtype, entity casingowner,.entity weaponentity)
Definition casings.qc:17
int autocvar_g_casings
Definition casings.qh:17
int m_id
Definition weapon.qh:45
vector v_up
vector v_right
vector v_forward
float bound(float min, float value, float max)
float random(void)
vector vectoangles(vector v)
#define makevectors
Definition post.qh:21
vector
Definition self.qh:92
const int CH_WEAPON_SINGLE
Definition sound.qh:9
const int CH_WEAPON_A
Definition sound.qh:7
void fireBullet_falloff(entity this,.entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float falloff_halflife, float falloff_mindist, float falloff_maxdist, float headshot_multiplier, float force, float falloff_forcehalflife, float dtype, entity tracer_effect, bool do_antilag)
Definition tracing.qc:364
vector w_shotdir
Definition tracing.qh:20
vector w_shotorg
Definition tracing.qh:19
#define W_SetupShot(ent, wepent, antilag, recoil, snd, chan, maxdamage, deathtype)
Definition tracing.qh:34
void W_MuzzleFlash(Weapon thiswep, entity actor,.entity weaponentity, vector shotorg, vector shotdir)
Definition all.qc:728
void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use,.entity weaponentity)

References antilag_getlag(), antilag_restore_all(), antilag_takeback_all(), autocvar_g_casings, autocvar_g_weaponspreadfactor, bound(), CH_WEAPON_A, CH_WEAPON_SINGLE, entity(), fireBullet_falloff(), Weapon::m_id, makevectors, random(), SpawnCasing(), v_forward, v_right, v_up, vectoangles(), vector, W_CalculateSpreadPattern(), W_DecreaseAmmo(), W_MuzzleFlash(), W_SetupShot, w_shotdir, and w_shotorg.

Referenced by W_Shotgun_Attack3_Frame1(), and W_Shotgun_Attack3_Frame2().

◆ W_Shotgun_Attack2()

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

Definition at line 177 of file shotgun.qc.

178{
179 sound(actor, CH_WEAPON_A, SND_SHOTGUN_MELEE, VOL_BASE, ATTEN_NORM);
180 weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(WEP_SHOTGUN, animtime), w_ready);
181
182 entity meleetemp = new_pure(meleetemp);
183 meleetemp.realowner = actor;
185 meleetemp.nextthink = time + WEP_CVAR_SEC(WEP_SHOTGUN, melee_delay) * W_WeaponRateFactor(actor);
186 meleetemp.weaponentity_fld = weaponentity;
187 W_SetupShot_Range(actor, weaponentity, true, 0, SND_Null, 0, WEP_CVAR_SEC(WEP_SHOTGUN, damage), WEP_CVAR_SEC(WEP_SHOTGUN, melee_range), WEP_SHOTGUN.m_id | HITTYPE_SECONDARY);
188}
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float W_WeaponRateFactor(entity this)
float time
const int HITTYPE_SECONDARY
Definition all.qh:29
#define new_pure(class)
purely logical entities (not linked to the area grid)
Definition oo.qh:67
#define setthink(e, f)
void W_Shotgun_Melee_Think(entity this)
Definition shotgun.qc:73
const float VOL_BASE
Definition sound.qh:36
const float ATTEN_NORM
Definition sound.qh:30
#define sound(e, c, s, v, a)
Definition sound.qh:52
#define W_SetupShot_Range(ent, wepent, antilag, recoil, snd, chan, maxdamage, range, deathtype)
Definition tracing.qh:36
#define WEP_CVAR_SEC(wep, name)
Definition all.qh:323
void weapon_thinkf(entity actor,.entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,.entity weaponentity, int fire) func)
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)

References ATTEN_NORM, CH_WEAPON_A, entity(), HITTYPE_SECONDARY, new_pure, setthink, sound, time, VOL_BASE, w_ready(), W_SetupShot_Range, W_Shotgun_Melee_Think(), W_WeaponRateFactor(), weapon_thinkf(), and WEP_CVAR_SEC.

◆ W_Shotgun_Attack3_Frame1()

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

Definition at line 219 of file shotgun.qc.

220{
221 if (!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
222 if (!(actor.items & IT_UNLIMITED_AMMO))
223 {
224 W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
225 w_ready(thiswep, actor, weaponentity, fire);
226 return;
227 }
228
229 W_Shotgun_Attack(thiswep, actor, weaponentity, false,
230 WEP_CVAR_PRI(WEP_SHOTGUN, ammo),
231 WEP_CVAR_PRI(WEP_SHOTGUN, damage),
232 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_halflife),
233 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_mindist),
234 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_maxdist),
235 WEP_CVAR_PRI(WEP_SHOTGUN, bullets),
236 WEP_CVAR_PRI(WEP_SHOTGUN, spread),
237 WEP_CVAR_PRI(WEP_SHOTGUN, spread_pattern),
238 WEP_CVAR_PRI(WEP_SHOTGUN, spread_pattern_scale),
239 WEP_CVAR_PRI(WEP_SHOTGUN, spread_pattern_bias),
240 WEP_CVAR_PRI(WEP_SHOTGUN, solidpenetration),
241 WEP_CVAR_PRI(WEP_SHOTGUN, force),
242 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_forcehalflife),
243 EFFECT_BULLET_WEAK);
244 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(WEP_SHOTGUN, alt_animtime), W_Shotgun_Attack3_Frame2);
245}
virtual void wr_checkammo2()
(SERVER) checks ammo for weapon second
Definition weapon.qh:94
const int IT_UNLIMITED_AMMO
Definition item.qh:23
void W_SwitchWeapon_Force(Player this, Weapon w,.entity weaponentity)
Definition selection.qc:246
#define w_getbestweapon(ent, wepent)
Definition selection.qh:23
void W_Shotgun_Attack(Weapon thiswep, entity actor,.entity weaponentity, float isprimary, float ammocount, float damage, float falloff_halflife, float falloff_mindist, float falloff_maxdist, float bullets, float spread, float spread_pattern, float spread_pattern_scale, float spread_pattern_bias, float solidpenetration, float force, float falloff_forcehalflife, entity bullet_trail_effect)
Definition shotgun.qc:8
void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor,.entity weaponentity, int fire)
Definition shotgun.qc:191
float ammo
Definition sv_turrets.qh:43
#define WEP_CVAR_PRI(wep, name)
Definition all.qh:322

References ammo, entity(), IT_UNLIMITED_AMMO, w_getbestweapon, w_ready(), W_Shotgun_Attack(), W_Shotgun_Attack3_Frame2(), W_SwitchWeapon_Force(), weapon_thinkf(), WEP_CVAR_PRI, WEP_CVAR_SEC, and Weapon::wr_checkammo2().

◆ W_Shotgun_Attack3_Frame2()

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

Definition at line 191 of file shotgun.qc.

192{
193 if (!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
194 if (!(actor.items & IT_UNLIMITED_AMMO))
195 {
196 W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
197 w_ready(thiswep, actor, weaponentity, fire);
198 return;
199 }
200
201 sound(actor, CH_WEAPON_SINGLE, SND_Null, VOL_BASE, ATTN_NORM); // kill previous sound
202 W_Shotgun_Attack(thiswep, actor, weaponentity, true,
203 WEP_CVAR_PRI(WEP_SHOTGUN, ammo),
204 WEP_CVAR_PRI(WEP_SHOTGUN, damage),
205 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_halflife),
206 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_mindist),
207 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_maxdist),
208 WEP_CVAR_PRI(WEP_SHOTGUN, bullets),
209 WEP_CVAR_PRI(WEP_SHOTGUN, spread),
210 WEP_CVAR_PRI(WEP_SHOTGUN, spread_pattern),
211 WEP_CVAR_PRI(WEP_SHOTGUN, spread_pattern_scale),
212 WEP_CVAR_PRI(WEP_SHOTGUN, spread_pattern_bias),
213 WEP_CVAR_PRI(WEP_SHOTGUN, solidpenetration),
214 WEP_CVAR_PRI(WEP_SHOTGUN, force),
215 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_forcehalflife),
216 EFFECT_BULLET_WEAK); // actually is secondary, but we trick the last shot into playing full reload sound
217 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(WEP_SHOTGUN, alt_animtime), w_ready);
218}
const float ATTN_NORM

References ammo, ATTN_NORM, CH_WEAPON_SINGLE, entity(), IT_UNLIMITED_AMMO, sound, VOL_BASE, w_getbestweapon, w_ready(), W_Shotgun_Attack(), W_SwitchWeapon_Force(), weapon_thinkf(), WEP_CVAR_PRI, WEP_CVAR_SEC, and Weapon::wr_checkammo2().

Referenced by W_Shotgun_Attack3_Frame1().

◆ W_Shotgun_Melee_Think()

void W_Shotgun_Melee_Think ( entity this)

Definition at line 73 of file shotgun.qc.

74{
75 // declarations
76 float i, f, swing, swing_factor, swing_damage, meleetime, is_player;
77 entity target_victim;
78 vector targpos, melee_path;
79
80 if(!this.cnt) // set start time of melee
81 {
82 this.cnt = time;
84 }
85
86 makevectors(this.realowner.v_angle); // update values for v_* vectors
87
88 // calculate swing percentage based on time
89 meleetime = WEP_CVAR_SEC(WEP_SHOTGUN, melee_time) * W_WeaponRateFactor(this.realowner);
90 swing = bound(0, (this.cnt + meleetime - time) / meleetime, 10);
91 f = ((1 - swing) * WEP_CVAR_SEC(WEP_SHOTGUN, melee_traces));
92
93 // check to see if we can still continue, otherwise give up now
94 if(IS_DEAD(this.realowner) && WEP_CVAR_SEC(WEP_SHOTGUN, melee_no_doubleslap))
95 {
96 delete(this);
97 return;
98 }
99
100 melee_path = (v_up * WEP_CVAR_SEC(WEP_SHOTGUN, melee_swing_up))
101 + (v_right * WEP_CVAR_SEC(WEP_SHOTGUN, melee_swing_side));
102 // if okay, perform the traces needed for this frame
103 for(i=this.swing_prev; i < f; ++i)
104 {
105 swing_factor = ((1 - (i / WEP_CVAR_SEC(WEP_SHOTGUN, melee_traces))) * 2 - 1);
106
107 targpos = this.realowner.origin + this.realowner.view_ofs
108 + (melee_path * swing_factor)
109 + (v_forward * WEP_CVAR_SEC(WEP_SHOTGUN, melee_range));
110
111 WarpZone_traceline_antilag(this.realowner, this.realowner.origin + this.realowner.view_ofs, targpos, false, this.realowner, ((IS_CLIENT(this.realowner)) ? ANTILAG_LATENCY(this.realowner) : 0));
112
113 Send_Effect(EFFECT_SHOTGUN_WOOSH, trace_endpos, -melee_path, 1);
114
115 // draw lightning beams for debugging
116 #ifdef SHOTGUN_MELEEDEBUG
117 te_lightning2(NULL, targpos, this.realowner.origin + this.realowner.view_ofs + v_forward * 5 - v_up * 5);
118 te_customflash(targpos, 40, 2, '1 1 1');
119 #endif
120
121 is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body" || IS_MONSTER(trace_ent));
122
123 if((trace_fraction < 1) // if trace is good, apply the damage and remove this
124 && (trace_ent.takedamage != DAMAGE_NO)
125 && (trace_ent != this.swing_alreadyhit)
126 && (is_player || WEP_CVAR_SEC(WEP_SHOTGUN, melee_nonplayerdamage)))
127 {
128 target_victim = trace_ent; // so it persists through other calls
129
130 if(is_player) // this allows us to be able to nerf the non-player damage done in e.g. assault or onslaught.
131 swing_damage = (WEP_CVAR_SEC(WEP_SHOTGUN, damage) * min(1, swing_factor + 1));
132 else
133 swing_damage = (WEP_CVAR_SEC(WEP_SHOTGUN, melee_nonplayerdamage) * min(1, swing_factor + 1));
134
135 //print(strcat(this.realowner.netname, " hitting ", target_victim.netname, " with ", strcat(ftos(swing_damage), " damage (factor: ", ftos(swing_factor), ") at "), ftos(time), " seconds.\n"));
136
137 Damage(target_victim, this.realowner, this.realowner,
138 swing_damage, WEP_SHOTGUN.m_id | HITTYPE_SECONDARY, this.weaponentity_fld,
139 this.realowner.origin + this.realowner.view_ofs,
140 v_forward * WEP_CVAR_SEC(WEP_SHOTGUN, force));
141
142 if(accuracy_isgooddamage(this.realowner, target_victim))
143 accuracy_add(this.realowner, WEP_SHOTGUN, 0, swing_damage, 0); // add to hit
144
145 // draw large red flash for debugging
146 #ifdef SHOTGUN_MELEEDEBUG
147 te_customflash(targpos, 200, 2, '15 0 0');
148 #endif
149
150 if(WEP_CVAR_SEC(WEP_SHOTGUN, melee_multihit)) // allow multiple hits with one swing, but not against the same player twice.
151 {
152 this.swing_alreadyhit = target_victim;
153 continue; // move along to next trace
154 }
155 else
156 {
157 delete(this);
158 return;
159 }
160 }
161 }
162
163 if(time >= this.cnt + meleetime)
164 {
165 // melee is finished
166 delete(this);
167 return;
168 }
169 else
170 {
171 // set up next frame
172 this.swing_prev = i;
173 this.nextthink = time;
174 }
175}
void accuracy_add(entity this, Weapon w, float fired, float hit, float real)
update accuracy stats
Definition accuracy.qc:102
bool accuracy_isgooddamage(entity attacker, entity targ)
does this damage count towards accuracy stats?
Definition accuracy.qc:133
void WarpZone_traceline_antilag(entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
Definition antilag.qc:221
#define ANTILAG_LATENCY(e)
Definition antilag.qh:19
float cnt
Definition powerups.qc:24
#define IS_CLIENT(s)
Definition player.qh:242
#define IS_DEAD(s)
Definition player.qh:245
#define IS_PLAYER(s)
Definition player.qh:243
entity trace_ent
vector trace_endpos
float nextthink
float trace_fraction
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition damage.qc:503
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:124
float min(float f,...)
#define NULL
Definition post.qh:14
void W_PlayStrengthSound(entity player)
Definition common.qc:40
float swing_prev
Definition shotgun.qc:71
entity swing_alreadyhit
Definition shotgun.qc:72
const int DAMAGE_NO
Definition subs.qh:79
entity realowner
#define IS_MONSTER(v)
Definition utils.qh:21

References accuracy_add(), accuracy_isgooddamage(), ANTILAG_LATENCY, bound(), cnt, Damage(), DAMAGE_NO, entity(), HITTYPE_SECONDARY, IS_CLIENT, IS_DEAD, IS_MONSTER, IS_PLAYER, makevectors, min(), nextthink, NULL, realowner, Send_Effect(), swing_alreadyhit, swing_prev, time, trace_endpos, trace_ent, trace_fraction, v_forward, v_right, v_up, vector, W_PlayStrengthSound(), W_WeaponRateFactor(), WarpZone_traceline_antilag(), and WEP_CVAR_SEC.

Referenced by W_Shotgun_Attack2().

Variable Documentation

◆ prevric

float prevric

Definition at line 381 of file shotgun.qc.

◆ shotgun_primarytime

float shotgun_primarytime

Definition at line 247 of file shotgun.qc.

◆ swing_alreadyhit

entity swing_alreadyhit

Definition at line 72 of file shotgun.qc.

Referenced by W_Shotgun_Melee_Think().

◆ swing_prev

float swing_prev

Definition at line 71 of file shotgun.qc.

Referenced by W_Shotgun_Melee_Think().