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 45 of file calculations.qc.

46{
47 // if below 1, the formulas make no sense (and would cause superjumps)
48 if(speedfactor < 1)
49 return explosion_f;
50
51#if 0
52 float m;
53 // find m so that
54 // speedfactor * (1 + e) * m / (1 + m) == 1
55 m = 1 / ((1 + 0) * speedfactor - 1);
56 vector v;
57 v = explosion_calcpush(explosion_f * speedfactor, m, target_v, 1, 0);
58 // the factor we then get is:
59 // 1
60 LOG_INFOF("MASS: %f\nv: %v -> %v\nENERGY BEFORE == %f + %f = %f\nENERGY AFTER >= %f",
61 m,
62 target_v, target_v + v,
63 target_v * target_v, m * explosion_f * speedfactor * explosion_f * speedfactor, target_v * target_v + m * explosion_f * speedfactor * explosion_f * speedfactor,
64 (target_v + v) * (target_v + v));
65 return v;
66#endif
67 return explosion_f * explosion_calcpush_getmultiplier(explosion_f * speedfactor, target_v);
68}
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;
10 a = explosion_v * (explosion_v - target_v);
11
12 if(a <= 0)
13 // target is too fast to be hittable by this
14 return 0;
15
16 a /= (explosion_v * explosion_v);
17 // we know we can divide by this, or above a would be == 0
18
19 return a;
20}

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 238 of file calculations.qc.

239{
240 float sigma;
241 vector v1 = '0 0 0', v2;
242 float dx, dy, r;
244 if (spread <= 0)
245 return (must_normalize ? normalize(dir) : dir);
246
247 switch (spread_style)
248 {
249 case 0:
250 // this is the baseline for the spread value!
251 // standard deviation: sqrt(2/5)
252 // density function: sqrt(1-r^2)
253 v1 = dir + randomvec() * spread;
254 return (must_normalize ? normalize(v1) : v1);
255 case 1:
256 // same thing, basically
257 return normalize(dir + cliptoplane(randomvec() * spread, dir));
258 case 2:
259 // circle spread... has at sigma=1 a standard deviation of sqrt(1/2)
260 sigma = spread * 0.89442719099991587855; // match baseline stddev
262 v2 = cross(dir, v1);
263 // random point on unit circle
264 dx = random() * 2 * M_PI;
265 dy = sin(dx);
266 dx = cos(dx);
267 // radius in our dist function
268 r = random();
269 r = sqrt(r);
270 return normalize(dir + (v1 * dx + v2 * dy) * r * sigma);
271 case 3: // gauss 3d
272 sigma = spread * 0.44721359549996; // match baseline stddev
273 // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
274 v1.x = gsl_ran_ugaussian() * sigma;
275 v1.y = gsl_ran_ugaussian() * sigma;
276 v1.z = gsl_ran_ugaussian() * sigma;
277 if (vlen2(v1) > W_SPREAD_GAUSS_MAX_STDEV ** 2)
279 v2 = dir + v1;
280 return (must_normalize ? normalize(v2) : v2);
281 case 4: // gauss 2d
282 sigma = spread * 0.44721359549996; // match baseline stddev
283 // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
284 v1.x = gsl_ran_ugaussian() * sigma;
285 v1.y = gsl_ran_ugaussian() * sigma;
286 v1.z = gsl_ran_ugaussian() * sigma;
287 if (vlen2(v1) > W_SPREAD_GAUSS_MAX_STDEV ** 2)
289 return normalize(dir + cliptoplane(v1, dir));
290 case 5: // 1-r
291 sigma = spread * 1.154700538379252; // 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 = solve_cubic_abcd(-2, 3, 0, -r) * '0 1 0';
301 return normalize(dir + (v1 * dx + v2 * dy) * r * sigma);
302 case 6: // 1-r^2
303 sigma = spread * 1.095445115010332; // match baseline stddev
305 v2 = cross(dir, v1);
306 // random point on unit circle
307 dx = random() * 2 * M_PI;
308 dy = sin(dx);
309 dx = cos(dx);
310 // radius in our dist function
311 r = random();
312 r = sqrt(1 - r);
313 r = sqrt(1 - r);
314 return normalize(dir + (v1 * dx + v2 * dy) * r * sigma);
315 case 7: // (1-r) (2-r)
316 sigma = spread * 1.224744871391589; // match baseline stddev
318 v2 = cross(dir, v1);
319 // random point on unit circle
320 dx = random() * 2 * M_PI;
321 dy = sin(dx);
322 dx = cos(dx);
323 // radius in our dist function
324 r = random();
325 r = 1 - sqrt(r);
326 r = 1 - sqrt(r);
327 return normalize(dir + (v1 * dx + v2 * dy) * r * sigma);
328 default:
329 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)!");
330 }
331
332 return '0 0 0';
333 /*
334 * how to derive falloff functions:
335 * rho(r) := (2-r) * (1-r);
336 * a : 0;
337 * b : 1;
338 * rhor(r) := r * rho(r);
339 * cr(t) := integrate(rhor(r), r, a, t);
340 * scr(t) := integrate(rhor(r) * r^2, r, a, t);
341 * variance : scr(b) / cr(b);
342 * solve(cr(r) = rand * cr(b), r), programmmode:false;
343 * sqrt(0.4 / variance), numer;
344 */
345}
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 187 of file calculations.qc.

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

139 {
140 if(this.m_gunalign)
141 return this.m_gunalign; // no adjustment needed
142
143 entity own = this.owner;
144
145 if(preferred_align < 1 || preferred_align > 4)
146 preferred_align = 3; // default
147
148 for(int j = 4; j > 1; --j) // > 1 as 1 is just center again
149 {
150 int taken = 0;
151 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
152 {
153 .entity weaponentity = weaponentities[slot];
154 if(own.(weaponentity).m_gunalign == j) // we know it can't be ours thanks to the above check
155 taken |= BIT(j);
156 if(own.(weaponentity).m_gunalign == preferred_align)
157 taken |= BIT(preferred_align);
158 }
159
160 if(!(taken & BIT(preferred_align)))
161 return preferred_align; // prefer the recommended
162 if(!(taken & BIT(j)))
163 return j; // or fall back if it's not available
164 }
165
166 return preferred_align; // return it anyway
167 }
#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:385
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().