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, bool is_primary, 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,
bool is_primary,
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 (is_primary ? 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 = v_right;
31 vector up = v_up;
32
33 float fixed_spread_factor = (spread * autocvar_g_weaponspreadfactor) / spread_pattern_scale;
34 spread_pattern_bias = bound(0, spread_pattern_bias, 1);
35 for (int sc = 0; sc < bullets; ++sc)
36 {
37 vector s = W_CalculateSpreadPattern(spread_pattern, spread_pattern_bias, sc, bullets);
38 s *= fixed_spread_factor;
39 fireBullet_falloff(actor, weaponentity, w_shotorg, w_shotdir + right * s.y + up * s.z,
40 0,
41 solidpenetration,
42 damage,
43 falloff_halflife,
44 falloff_mindist,
45 falloff_maxdist,
46 0,
47 force,
48 falloff_forcehalflife,
49 thiswep.m_id,
50 bullet_trail_effect,
51 false
52 );
53 }
54 }
55 else
56 for (int sc = 0; sc < bullets; ++sc)
57 fireBullet_falloff(actor, weaponentity, w_shotorg, w_shotdir,
58 spread,
59 solidpenetration,
60 damage,
61 falloff_halflife,
62 falloff_mindist,
63 falloff_maxdist,
64 0,
65 force,
66 falloff_forcehalflife,
67 thiswep.m_id,
68 bullet_trail_effect,
69 false
70 );
71
72 if (lag && bullets > 0)
74
75 W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
76
77 // casing code
78 if (autocvar_g_casings >= 1)
79 {
80 makevectors(actor.v_angle); // for some reason, this is lost
81 //for (int sc = 0; sc < WEP_CVAR_PRI(WEP_SHOTGUN, ammo); ++sc)
82 SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 30) * v_up), vectoangles(v_forward), 1, actor, weaponentity);
83 }
84}
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:43
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:356
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:715
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 193 of file shotgun.qc.

194{
195 sound(actor, CH_WEAPON_A, SND_SHOTGUN_MELEE, VOL_BASE, ATTEN_NORM);
196 weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(WEP_SHOTGUN, animtime), w_ready);
197
198 entity meleetemp = new_pure(meleetemp);
199 meleetemp.realowner = actor;
201 meleetemp.nextthink = time + WEP_CVAR_SEC(WEP_SHOTGUN, melee_delay) * W_WeaponRateFactor(actor);
202 meleetemp.weaponentity_fld = weaponentity;
203 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);
204}
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:88
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:339
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 236 of file shotgun.qc.

237{
238 if (!thiswep.wr_checkammo2(thiswep, actor, weaponentity)
239 && !(actor.items & IT_UNLIMITED_AMMO))
240 {
241 W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
242 w_ready(thiswep, actor, weaponentity, fire);
243 return;
244 }
245
246 W_Shotgun_Attack(thiswep, actor, weaponentity, false,
247 WEP_CVAR_PRI(WEP_SHOTGUN, ammo),
248 WEP_CVAR_PRI(WEP_SHOTGUN, damage),
249 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_halflife),
250 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_mindist),
251 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_maxdist),
252 WEP_CVAR_PRI(WEP_SHOTGUN, bullets),
253 WEP_CVAR_PRI(WEP_SHOTGUN, spread),
254 WEP_CVAR_PRI(WEP_SHOTGUN, spread_pattern),
255 WEP_CVAR_PRI(WEP_SHOTGUN, spread_pattern_scale),
256 WEP_CVAR_PRI(WEP_SHOTGUN, spread_pattern_bias),
257 WEP_CVAR_PRI(WEP_SHOTGUN, solidpenetration),
258 WEP_CVAR_PRI(WEP_SHOTGUN, force),
259 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_forcehalflife),
260 EFFECT_BULLET_WEAK
261 );
262 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(WEP_SHOTGUN, alt_animtime), W_Shotgun_Attack3_Frame2);
263}
virtual void wr_checkammo2()
(SERVER) checks ammo for weapon second
Definition weapon.qh:105
const int IT_UNLIMITED_AMMO
Definition item.qh:23
void W_SwitchWeapon_Force(Player this, Weapon w,.entity weaponentity)
Definition selection.qc:237
#define w_getbestweapon(ent, wepent)
Definition selection.qh:23
void W_Shotgun_Attack(Weapon thiswep, entity actor,.entity weaponentity, bool is_primary, 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:207
float ammo
Definition sv_turrets.qh:43
#define WEP_CVAR_PRI(wep, name)
Definition all.qh:338

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 207 of file shotgun.qc.

208{
209 if (!thiswep.wr_checkammo2(thiswep, actor, weaponentity)
210 && !(actor.items & IT_UNLIMITED_AMMO))
211 {
212 W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
213 w_ready(thiswep, actor, weaponentity, fire);
214 return;
215 }
216
217 sound(actor, CH_WEAPON_SINGLE, SND_Null, VOL_BASE, ATTN_NORM); // kill previous sound
218 W_Shotgun_Attack(thiswep, actor, weaponentity, true,
219 WEP_CVAR_PRI(WEP_SHOTGUN, ammo),
220 WEP_CVAR_PRI(WEP_SHOTGUN, damage),
221 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_halflife),
222 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_mindist),
223 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_maxdist),
224 WEP_CVAR_PRI(WEP_SHOTGUN, bullets),
225 WEP_CVAR_PRI(WEP_SHOTGUN, spread),
226 WEP_CVAR_PRI(WEP_SHOTGUN, spread_pattern),
227 WEP_CVAR_PRI(WEP_SHOTGUN, spread_pattern_scale),
228 WEP_CVAR_PRI(WEP_SHOTGUN, spread_pattern_bias),
229 WEP_CVAR_PRI(WEP_SHOTGUN, solidpenetration),
230 WEP_CVAR_PRI(WEP_SHOTGUN, force),
231 WEP_CVAR_PRI(WEP_SHOTGUN, damagefalloff_forcehalflife),
232 EFFECT_BULLET_WEAK
233 ); // actually is secondary, but we trick the last shot into playing full reload sound
234 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(WEP_SHOTGUN, alt_animtime), w_ready);
235}
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 88 of file shotgun.qc.

89{
90 if (!this.cnt) // set start time of melee
91 {
92 this.cnt = time;
94 }
95
96 makevectors(this.realowner.v_angle); // update values for v_* vectors
97
98 // calculate swing percentage based on time
99 float meleetime = WEP_CVAR_SEC(WEP_SHOTGUN, melee_time) * W_WeaponRateFactor(this.realowner);
100 float swing = bound(0, (this.cnt + meleetime - time) / meleetime, 10);
101 float f = ((1 - swing) * WEP_CVAR_SEC(WEP_SHOTGUN, melee_traces));
102
103 // check to see if we can still continue, otherwise give up now
104 if (IS_DEAD(this.realowner) && WEP_CVAR_SEC(WEP_SHOTGUN, melee_no_doubleslap))
105 {
106 delete(this);
107 return;
108 }
109
110 vector melee_path = (v_up * WEP_CVAR_SEC(WEP_SHOTGUN, melee_swing_up))
111 + (v_right * WEP_CVAR_SEC(WEP_SHOTGUN, melee_swing_side));
112 // if okay, perform the traces needed for this frame
113 entity target_victim;
114 vector targpos;
115 float swing_factor, swing_damage, i;
116 for (i = this.swing_prev; i < f; ++i)
117 {
118 swing_factor = (1 - (i / WEP_CVAR_SEC(WEP_SHOTGUN, melee_traces))) * 2 - 1;
119
120 targpos = this.realowner.origin + this.realowner.view_ofs
121 + (melee_path * swing_factor)
122 + (v_forward * WEP_CVAR_SEC(WEP_SHOTGUN, melee_range));
123
124 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));
125
126 Send_Effect(EFFECT_SHOTGUN_WOOSH, trace_endpos, -melee_path, 1);
127
128 // draw lightning beams for debugging
129 #ifdef SHOTGUN_MELEEDEBUG
130 te_lightning2(NULL, targpos, this.realowner.origin + this.realowner.view_ofs + v_forward * 5 - v_up * 5);
131 te_customflash(targpos, 40, 2, '1 1 1');
132 #endif
133
134 bool is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body" || IS_MONSTER(trace_ent));
135
136 if (trace_fraction < 1 // if trace is good, apply the damage and remove this
137 && trace_ent.takedamage != DAMAGE_NO
138 && trace_ent != this.swing_alreadyhit
139 && (is_player || WEP_CVAR_SEC(WEP_SHOTGUN, melee_nonplayerdamage)))
140 {
141 target_victim = trace_ent; // so it persists through other calls
142
143 if (is_player) // this allows us to be able to nerf the non-player damage done in e.g. assault or onslaught.
144 swing_damage = (WEP_CVAR_SEC(WEP_SHOTGUN, damage) * min(1, swing_factor + 1));
145 else
146 swing_damage = (WEP_CVAR_SEC(WEP_SHOTGUN, melee_nonplayerdamage) * min(1, swing_factor + 1));
147
148 //print(strcat(this.realowner.netname, " hitting ", target_victim.netname, " with ", strcat(ftos(swing_damage), " damage (factor: ", ftos(swing_factor), ") at "), ftos(time), " seconds.\n"));
149
150 Damage(target_victim, this.realowner, this.realowner,
151 swing_damage,
152 WEP_SHOTGUN.m_id | HITTYPE_SECONDARY,
153 this.weaponentity_fld,
154 this.realowner.origin + this.realowner.view_ofs,
155 v_forward * WEP_CVAR_SEC(WEP_SHOTGUN, force)
156 );
157
158 if (accuracy_isgooddamage(this.realowner, target_victim))
159 accuracy_add(this.realowner, WEP_SHOTGUN, 0, swing_damage, 0); // add to hit
160
161 // draw large red flash for debugging
162 #ifdef SHOTGUN_MELEEDEBUG
163 te_customflash(targpos, 200, 2, '15 0 0');
164 #endif
165
166 if (WEP_CVAR_SEC(WEP_SHOTGUN, melee_multihit)) // allow multiple hits with one swing, but not against the same player twice.
167 {
168 this.swing_alreadyhit = target_victim;
169 continue; // move along to next trace
170 }
171 else
172 {
173 delete(this);
174 return;
175 }
176 }
177 }
178
179 if (time >= this.cnt + meleetime)
180 {
181 // melee is finished
182 delete(this);
183 return;
184 }
185 else
186 {
187 // set up next frame
188 this.swing_prev = i;
189 this.nextthink = time;
190 }
191}
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:241
#define IS_DEAD(s)
Definition player.qh:244
#define IS_PLAYER(s)
Definition player.qh:242
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:493
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:120
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:86
entity swing_alreadyhit
Definition shotgun.qc:87
const int DAMAGE_NO
Definition subs.qh:79
entity realowner
#define IS_MONSTER(v)
Definition utils.qh:23

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 398 of file shotgun.qc.

◆ shotgun_primarytime

float shotgun_primarytime

Definition at line 265 of file shotgun.qc.

◆ swing_alreadyhit

entity swing_alreadyhit

Definition at line 87 of file shotgun.qc.

Referenced by W_Shotgun_Melee_Think().

◆ swing_prev

float swing_prev

Definition at line 86 of file shotgun.qc.

Referenced by W_Shotgun_Melee_Think().