Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
calculations.qh File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

vector damage_explosion_calcpush (vector explosion_f, vector target_v, float speedfactor)
float explosion_calcpush_getmultiplier (vector explosion_v, vector target_v)
vector W_CalculateSpread (vector dir, float spread, int spread_style, bool must_normalize)
vector W_CalculateSpreadPattern (int pattern, float bias, int counter, int total)
int W_GunAlign (entity this, int preferred_align)

Variables

float autocvar_g_weaponspreadfactor
const float W_SPREAD_GAUSS_MAX_STDEV = 4

Function Documentation

◆ damage_explosion_calcpush()

vector damage_explosion_calcpush ( vector explosion_f,
vector target_v,
float speedfactor )

Definition at line 39 of file calculations.qc.

40{
41 // if below 1, the formulas make no sense (and would cause superjumps)
42 if (speedfactor < 1)
43 return explosion_f;
44
45#if 0
46 float m;
47 // find m so that
48 // speedfactor * (1 + e) * m / (1 + m) == 1
49 m = 1 / ((1 + 0) * speedfactor - 1);
50 vector v = explosion_calcpush(explosion_f * speedfactor, m, target_v, 1, 0);
51 // the factor we then get is:
52 // 1
53 LOG_INFOF("MASS: %f\nv: %v -> %v\nENERGY BEFORE == %f + %f = %f\nENERGY AFTER >= %f",
54 m,
55 target_v, target_v + v,
56 target_v * target_v, m * explosion_f * speedfactor * explosion_f * speedfactor, target_v * target_v + m * explosion_f * speedfactor * explosion_f * speedfactor,
57 (target_v + v) * (target_v + v));
58 return v;
59#endif
60 return explosion_f * explosion_calcpush_getmultiplier(explosion_f * speedfactor, target_v);
61}
float explosion_calcpush_getmultiplier(vector explosion_v, vector target_v)
#define LOG_INFOF(...)
Definition log.qh:66
vector
Definition self.qh:92

References explosion_calcpush_getmultiplier(), LOG_INFOF, and vector.

Referenced by Damage(), MUTATOR_HOOKFUNCTION(), and NET_HANDLE().

◆ explosion_calcpush_getmultiplier()

float explosion_calcpush_getmultiplier ( vector explosion_v,
vector target_v )

Definition at line 7 of file calculations.qc.

8{
9 float a = explosion_v * (explosion_v - target_v);
10
11 if (a <= 0)
12 // target is too fast to be hittable by this
13 return 0;
14
15 a /= explosion_v * explosion_v;
16 // we know we can divide by this, or above a would be == 0
17 return a;
18}

References vector.

Referenced by damage_explosion_calcpush().

◆ W_CalculateSpread()

vector W_CalculateSpread ( vector dir,
float spread,
int spread_style,
bool must_normalize )

Definition at line 226 of file calculations.qc.

227{
229 if (spread <= 0)
230 return (must_normalize ? normalize(dir) : dir);
231
232 vector v1 = '0 0 0', v2;
233 float sigma;
234 float dx, dy, r;
235 switch (spread_style)
236 {
237 case 0:
238 // this is the baseline for the spread value!
239 // standard deviation: sqrt(2/5)
240 // density function: sqrt(1-r^2)
241 v1 = dir + randomvec() * spread;
242 return (must_normalize ? normalize(v1) : v1);
243 case 1:
244 // same thing, basically
245 return normalize(dir + cliptoplane(randomvec() * spread, dir));
246 case 2:
247 // circle spread... has at sigma=1 a standard deviation of sqrt(1/2)
248 sigma = spread * 0.89442719099991587855; // match baseline stddev
250 v2 = cross(dir, v1);
251 // random point on unit circle
252 dx = random() * 2 * M_PI;
253 dy = sin(dx);
254 dx = cos(dx);
255 // radius in our dist function
256 r = random();
257 r = sqrt(r);
258 return normalize(dir + (v1 * dx + v2 * dy) * r * sigma);
259 case 3: // gauss 3d
260 sigma = spread * 0.44721359549996; // match baseline stddev
261 // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
262 v1.x = gsl_ran_ugaussian() * sigma;
263 v1.y = gsl_ran_ugaussian() * sigma;
264 v1.z = gsl_ran_ugaussian() * sigma;
265 if (vlen2(v1) > W_SPREAD_GAUSS_MAX_STDEV ** 2)
267 v2 = dir + v1;
268 return (must_normalize ? normalize(v2) : v2);
269 case 4: // gauss 2d
270 sigma = spread * 0.44721359549996; // match baseline stddev
271 // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
272 v1.x = gsl_ran_ugaussian() * sigma;
273 v1.y = gsl_ran_ugaussian() * sigma;
274 v1.z = gsl_ran_ugaussian() * sigma;
275 if (vlen2(v1) > W_SPREAD_GAUSS_MAX_STDEV ** 2)
277 return normalize(dir + cliptoplane(v1, dir));
278 case 5: // 1-r
279 sigma = spread * 1.154700538379252; // match baseline stddev
281 v2 = cross(dir, v1);
282 // random point on unit circle
283 dx = random() * 2 * M_PI;
284 dy = sin(dx);
285 dx = cos(dx);
286 // radius in our dist function
287 r = random();
288 r = solve_cubic_abcd(-2, 3, 0, -r) * '0 1 0';
289 return normalize(dir + (v1 * dx + v2 * dy) * r * sigma);
290 case 6: // 1-r^2
291 sigma = spread * 1.095445115010332; // match baseline stddev
293 v2 = cross(dir, v1);
294 // random point on unit circle
295 dx = random() * 2 * M_PI;
296 dy = sin(dx);
297 dx = cos(dx);
298 // radius in our dist function
299 r = random();
300 r = sqrt(1 - r);
301 r = sqrt(1 - r);
302 return normalize(dir + (v1 * dx + v2 * dy) * r * sigma);
303 case 7: // (1-r) (2-r)
304 sigma = spread * 1.224744871391589; // match baseline stddev
306 v2 = cross(dir, v1);
307 // random point on unit circle
308 dx = random() * 2 * M_PI;
309 dy = sin(dx);
310 dx = cos(dx);
311 // radius in our dist function
312 r = random();
313 r = 1 - sqrt(r);
314 r = 1 - sqrt(r);
315 return normalize(dir + (v1 * dx + v2 * dy) * r * sigma);
316 default:
317 error("g_projectiles_spread_style must be 0 (sphere), 1 (flattened sphere), 2 (circle), 3 (gauss 3D), 4 (gauss plane), 5 (linear falloff), 6 (quadratic falloff), 7 (stronger falloff)!");
318 }
319
320 return '0 0 0';
321 /*
322 * how to derive falloff functions: Maxima:
323 * rho(r) := (2-r) * (1-r);
324 * a : 0;
325 * b : 1;
326 * rhor(r) := r * rho(r);
327 * cr(t) := integrate(rhor(r), r, a, t);
328 * scr(t) := integrate(rhor(r) * r^2, r, a, t);
329 * variance : scr(b) / cr(b);
330 * solve(cr(r) = rand * cr(b), r), programmmode:false;
331 * sqrt(0.4 / variance), numer;
332 */
333}
vector cliptoplane(vector v, vector p)
vector findperpendicular(vector v)
vector solve_cubic_abcd(float a, float b, float c, float d)
float autocvar_g_weaponspreadfactor
const float W_SPREAD_GAUSS_MAX_STDEV
#define M_PI
Definition mathlib.qh:108
float cos(float f)
float random(void)
float sqrt(float f)
vector randomvec(void)
float sin(float f)
vector normalize(vector v)
#define error
Definition pre.qh:6
ERASEABLE float gsl_ran_ugaussian()
Returns a Gaussian random variate, with mean zero and standard deviation sigma 1 From the GNU Scienti...
Definition random.qc:87
int dir
Definition impulse.qc:89
#define vlen2(v)
Definition vector.qh:4
#define cross(a, b)
Definition vector.qh:25

References autocvar_g_weaponspreadfactor, cliptoplane(), cos(), cross, dir, error, findperpendicular(), gsl_ran_ugaussian(), M_PI, normalize(), random(), randomvec(), sin(), solve_cubic_abcd(), sqrt(), vector, vlen2, and W_SPREAD_GAUSS_MAX_STDEV.

Referenced by fireBullet_falloff(), nades_CheckThrow(), and W_SetupProjVelocity_Explicit().

◆ W_CalculateSpreadPattern()

vector W_CalculateSpreadPattern ( int pattern,
float bias,
int counter,
int total )

Definition at line 180 of file calculations.qc.

181{
182 vector s = '0 0 0';
183
184 switch (pattern)
185 {
186 default:
187 case 1:
188 // first is always centered
189 if (counter == 0)
190 return '0 0 0';
191
192 makevectors('0 360 0' * (0.75 + (counter - 0.5) / (total - 1)));
193 s.y = v_forward.x;
194 s.z = v_forward.y;
195 // move outer projectiles randomly towards the center by max <bias> percent radius
196 if (bias)
197 s *= (1 - bias) + random() * bias;
198 return s;
199
200 case 2:
201 // first is always centered
202 if (counter == 0)
203 return '0 0 0';
204
205 // points form a round circle with even distribution
206 // this could be simplified to '0 360 0' * (counter / total)
207 // but it would lose ALL the specific placements
208 // for example with this 2 pellets is center + directly up
209 // while 3 pellets is a horizontal sweep and and 4 is an upside
210 // down Y shape, 5 is a star instead of a pentagram,
211 // 9 is a 3x3 grid and 13 is a circle with center + 3 per quadrant
212 makevectors('0 360 0' * ((0.25 * ((total + 1) % 2)) + (counter / (total - 1))));
213
214 // return transform vector
215 s.y = v_forward.x;
216 s.z = v_forward.y;
217 if (bias)
218 s *= (1 - bias) + random() * bias;
219
220 //else // return original result normal vector
221 //s = v_forward;
222 return s;
223 }
224}
vector v_forward
#define makevectors
Definition post.qh:21

References makevectors, random(), v_forward, and vector.

Referenced by W_Crylink_Attack(), W_Crylink_Attack2(), W_Hagar_Attack2_Load_Release(), and W_Shotgun_Attack().

◆ W_GunAlign()

int W_GunAlign ( entity this,
int preferred_align )

Definition at line 131 of file calculations.qc.

132{
133 if (this.m_gunalign)
134 return this.m_gunalign; // no adjustment needed
135
136 entity own = this.owner;
137
138 if (preferred_align < 1 || preferred_align > 4)
139 preferred_align = 3; // default
140
141 for (int j = 4; j > 1; --j) // > 1 as 1 is just center again
142 {
143 int taken = 0;
144 for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
145 {
146 .entity weaponentity = weaponentities[slot];
147 if (own.(weaponentity).m_gunalign == j) // we know it can't be ours thanks to the above check
148 taken |= BIT(j);
149 if (own.(weaponentity).m_gunalign == preferred_align)
150 taken |= BIT(preferred_align);
151 }
152
153 if (!(taken & BIT(preferred_align)))
154 return preferred_align; // prefer the recommended
155 if (!(taken & BIT(j)))
156 return j; // or fall back if it's not available
157 }
158
159 return preferred_align; // return it anyway
160}
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition bits.qh:8
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
entity owner
Definition main.qh:87
int m_gunalign
Definition all.qh:410
const int MAX_WEAPONSLOTS
Definition weapon.qh:16
entity weaponentities[MAX_WEAPONSLOTS]
Definition weapon.qh:17

References BIT, entity(), m_gunalign, MAX_WEAPONSLOTS, owner, and weaponentities.

Referenced by CL_WeaponEntity_SetModel(), Draw_GrapplingHook(), FireGrapplingHook(), GrapplingHookThink(), NET_HANDLE(), and W_ResetGunAlign().

Variable Documentation

◆ autocvar_g_weaponspreadfactor

float autocvar_g_weaponspreadfactor

◆ W_SPREAD_GAUSS_MAX_STDEV

const float W_SPREAD_GAUSS_MAX_STDEV = 4

Definition at line 5 of file calculations.qh.

Referenced by W_CalculateSpread().