quake2ts 0.0.193 → 0.0.195

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/package.json +1 -1
  2. package/packages/cgame/dist/index.cjs +769 -103
  3. package/packages/cgame/dist/index.cjs.map +1 -1
  4. package/packages/cgame/dist/index.d.cts +83 -2
  5. package/packages/cgame/dist/index.d.ts +83 -2
  6. package/packages/cgame/dist/index.js +766 -105
  7. package/packages/cgame/dist/index.js.map +1 -1
  8. package/packages/client/dist/browser/index.global.js +5 -5
  9. package/packages/client/dist/browser/index.global.js.map +1 -1
  10. package/packages/client/dist/cjs/index.cjs +56 -502
  11. package/packages/client/dist/cjs/index.cjs.map +1 -1
  12. package/packages/client/dist/esm/index.js +55 -497
  13. package/packages/client/dist/esm/index.js.map +1 -1
  14. package/packages/client/dist/tsconfig.tsbuildinfo +1 -1
  15. package/packages/client/dist/types/demo/handler.d.ts +1 -1
  16. package/packages/client/dist/types/demo/handler.d.ts.map +1 -1
  17. package/packages/client/dist/types/index.d.ts +4 -5
  18. package/packages/client/dist/types/index.d.ts.map +1 -1
  19. package/packages/engine/dist/tsconfig.tsbuildinfo +1 -1
  20. package/packages/game/dist/browser/index.global.js +2 -2
  21. package/packages/game/dist/browser/index.global.js.map +1 -1
  22. package/packages/game/dist/cjs/index.cjs +14 -2
  23. package/packages/game/dist/cjs/index.cjs.map +1 -1
  24. package/packages/game/dist/esm/index.js +14 -2
  25. package/packages/game/dist/esm/index.js.map +1 -1
  26. package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
  27. package/packages/game/dist/types/index.d.ts +5 -0
  28. package/packages/game/dist/types/index.d.ts.map +1 -1
  29. package/packages/server/dist/index.cjs +7 -1
  30. package/packages/server/dist/index.js +7 -1
  31. package/packages/shared/dist/tsconfig.tsbuildinfo +1 -1
  32. package/packages/shared/dist/types/protocol/player-state.d.ts +5 -0
  33. package/packages/shared/dist/types/protocol/player-state.d.ts.map +1 -1
  34. package/packages/tools/dist/tsconfig.tsbuildinfo +1 -1
  35. package/packages/client/dist/types/prediction.d.ts +0 -51
  36. package/packages/client/dist/types/prediction.d.ts.map +0 -1
  37. package/packages/client/dist/types/view-effects.d.ts +0 -41
  38. package/packages/client/dist/types/view-effects.d.ts.map +0 -1
  39. package/packages/client/dist/types/view.d.ts +0 -4
  40. package/packages/client/dist/types/view.d.ts.map +0 -1
@@ -1,4 +1,10 @@
1
- import { WeaponId } from '@quake2ts/shared';
1
+ import { angleVectors, clampViewAngles, ZERO_VEC3, hasPmFlag, PmFlag, dotVec3, WaterLevel, PmType, angleMod, applyPmoveFriction, buildWaterWish, buildAirGroundWish, applyPmoveAccelerate, applyPmoveAirAccelerate, addVec3, scaleVec3, PlayerStat, G_GetAmmoStat } from '@quake2ts/shared';
2
+
3
+ var __defProp = Object.defineProperty;
4
+ var __export = (target, all) => {
5
+ for (var name in all)
6
+ __defProp(target, name, { get: all[name], enumerable: true });
7
+ };
2
8
 
3
9
  // src/hud/crosshair.ts
4
10
  var crosshairPic = null;
@@ -108,7 +114,7 @@ var Init_Damage = (cgi3) => {
108
114
  }
109
115
  };
110
116
  var Draw_Damage = (cgi3, ps, width, height) => {
111
- if (!ps.damage_yaw && !ps.damage_pitch && !ps.damage_alpha) {
117
+ if ((!ps.damageAlpha || ps.damageAlpha <= 0) && (!ps.damageIndicators || ps.damageIndicators.length === 0)) {
112
118
  return;
113
119
  }
114
120
  };
@@ -210,87 +216,35 @@ var Draw_Number = (cgi3, x, y, value, pics, width, color) => {
210
216
  const digit = parseInt(s[i]);
211
217
  const pic = pics[digit];
212
218
  if (pic) {
213
- {
219
+ if (color) {
220
+ cgi3.SCR_DrawColorPic(x + i * width, y, pic, { x: color[0], y: color[1], z: color[2] }, color[3]);
221
+ } else {
214
222
  cgi3.SCR_DrawPic(x + i * width, y, pic);
215
223
  }
216
224
  }
217
225
  }
218
226
  };
219
- var WEAPON_ICON_MAP = {
220
- [WeaponId.Blaster]: "w_blaster",
221
- [WeaponId.Shotgun]: "w_shotgun",
222
- [WeaponId.SuperShotgun]: "w_sshotgun",
223
- [WeaponId.Machinegun]: "w_machinegun",
224
- [WeaponId.Chaingun]: "w_chaingun",
225
- [WeaponId.GrenadeLauncher]: "w_glauncher",
226
- [WeaponId.RocketLauncher]: "w_rlauncher",
227
- [WeaponId.HyperBlaster]: "w_hyperblaster",
228
- [WeaponId.Railgun]: "w_railgun",
229
- [WeaponId.BFG10K]: "w_bfg",
230
- [WeaponId.Grapple]: "w_grapple",
231
- [WeaponId.ChainFist]: "w_chainfist",
232
- [WeaponId.EtfRifle]: "w_etf_rifle",
233
- [WeaponId.ProxLauncher]: "w_prox_launcher",
234
- [WeaponId.IonRipper]: "w_ionripper",
235
- [WeaponId.PlasmaBeam]: "w_plasmabeam",
236
- [WeaponId.Phalanx]: "w_phalanx",
237
- [WeaponId.Disruptor]: "w_disruptor"
238
- };
239
- var KEY_ICON_MAP = {
240
- "blue": "k_bluekey",
241
- "red": "k_redkey",
242
- "green": "k_security",
243
- "yellow": "k_pyramid"
244
- };
245
- var Draw_StatusBar = (cgi3, client, health, armor, ammo, hudNumberPics2, numberWidth2, timeMs, layout) => {
227
+ var Draw_StatusBar = (cgi3, ps, hudNumberPics2, numberWidth2, timeMs, layout) => {
228
+ const health = ps.stats[PlayerStat.STAT_HEALTH] || 0;
229
+ const armor = ps.stats[PlayerStat.STAT_ARMOR] || 0;
230
+ const ammo = ps.stats[PlayerStat.STAT_AMMO] ? G_GetAmmoStat(ps.stats[PlayerStat.STAT_AMMO]) : 0;
231
+ ps.stats[PlayerStat.STAT_ARMOR_ICON] || 0;
232
+ ps.stats[PlayerStat.STAT_AMMO_ICON] || 0;
233
+ let healthColor = void 0;
234
+ if (health <= 25) {
235
+ {
236
+ healthColor = [1, 0, 0, 1];
237
+ }
238
+ }
246
239
  if (hudNumberPics2.length > 0) {
247
- Draw_Number(cgi3, layout.HEALTH_X, layout.HEALTH_Y, health, hudNumberPics2, numberWidth2);
240
+ Draw_Number(cgi3, layout.HEALTH_X, layout.HEALTH_Y, health, hudNumberPics2, numberWidth2, healthColor);
248
241
  Draw_Number(cgi3, layout.ARMOR_X, layout.ARMOR_Y, armor, hudNumberPics2, numberWidth2);
249
242
  Draw_Number(cgi3, layout.AMMO_X, layout.AMMO_Y, ammo, hudNumberPics2, numberWidth2);
250
243
  }
251
- const armorItem = client.inventory.armor;
252
- if (armorItem && armorItem.armorCount > 0) {
253
- const iconName = `i_${armorItem.armorType}armor`;
254
- const icon = iconPics.get(iconName);
244
+ if (ps.pickupIcon) {
245
+ const icon = cgi3.Draw_RegisterPic(ps.pickupIcon);
255
246
  if (icon) {
256
- cgi3.SCR_DrawPic(layout.ARMOR_X - 24, layout.ARMOR_Y - 2, icon);
257
- }
258
- }
259
- const currentWeapon = client.inventory.currentWeapon;
260
- if (currentWeapon) {
261
- const iconName = WEAPON_ICON_MAP[currentWeapon];
262
- if (iconName) {
263
- const icon = iconPics.get(iconName);
264
- if (icon) {
265
- cgi3.SCR_DrawPic(layout.WEAPON_ICON_X, layout.WEAPON_ICON_Y, icon);
266
- }
267
- }
268
- }
269
- const keys = Array.from(client.inventory.keys).sort();
270
- let keyY = layout.WEAPON_ICON_Y - 150 * layout.scale;
271
- for (const key of keys) {
272
- const iconName = KEY_ICON_MAP[key];
273
- if (iconName) {
274
- const icon = iconPics.get(iconName);
275
- if (icon) {
276
- const size = cgi3.Draw_GetPicSize(icon);
277
- cgi3.SCR_DrawPic(layout.WEAPON_ICON_X, keyY, icon);
278
- keyY += size.height + 2;
279
- }
280
- }
281
- }
282
- let powerupX = layout.POWERUP_X;
283
- for (const [powerup, expiresAt] of Array.from(client.inventory.powerups.entries())) {
284
- if (expiresAt && expiresAt > timeMs) {
285
- const iconName = `p_${powerup}`;
286
- const icon = iconPics.get(iconName);
287
- if (icon) {
288
- const size = cgi3.Draw_GetPicSize(icon);
289
- cgi3.SCR_DrawPic(powerupX, layout.POWERUP_Y, icon);
290
- const remainingSeconds = Math.ceil((expiresAt - timeMs) / 1e3);
291
- Draw_Number(cgi3, powerupX + size.width + 2, layout.POWERUP_Y, remainingSeconds, hudNumberPics2, numberWidth2);
292
- powerupX -= size.width + numberWidth2 * remainingSeconds.toString().length + 8;
293
- }
247
+ cgi3.SCR_DrawPic(layout.WEAPON_ICON_X, layout.WEAPON_ICON_Y, icon);
294
248
  }
295
249
  }
296
250
  };
@@ -301,26 +255,26 @@ var REFERENCE_HEIGHT = 480;
301
255
  var getHudLayout = (width, height) => {
302
256
  const scaleX = width / REFERENCE_WIDTH;
303
257
  const scaleY = height / REFERENCE_HEIGHT;
304
- const scale = Math.min(scaleX, scaleY);
258
+ const scale2 = Math.min(scaleX, scaleY);
305
259
  return {
306
260
  // Status bar numbers - Anchored Bottom-Left / Center / Right
307
- HEALTH_X: 100 * scale,
308
- HEALTH_Y: height - (REFERENCE_HEIGHT - 450) * scale,
309
- ARMOR_X: 200 * scale,
310
- ARMOR_Y: height - (REFERENCE_HEIGHT - 450) * scale,
311
- AMMO_X: width - (REFERENCE_WIDTH - 540) * scale,
261
+ HEALTH_X: 100 * scale2,
262
+ HEALTH_Y: height - (REFERENCE_HEIGHT - 450) * scale2,
263
+ ARMOR_X: 200 * scale2,
264
+ ARMOR_Y: height - (REFERENCE_HEIGHT - 450) * scale2,
265
+ AMMO_X: width - (REFERENCE_WIDTH - 540) * scale2,
312
266
  // Anchor right? 540 is near right (640)
313
- AMMO_Y: height - (REFERENCE_HEIGHT - 450) * scale,
267
+ AMMO_Y: height - (REFERENCE_HEIGHT - 450) * scale2,
314
268
  // Center print messages - Center
315
269
  CENTER_PRINT_X: width / 2,
316
- CENTER_PRINT_Y: 100 * scale,
270
+ CENTER_PRINT_Y: 100 * scale2,
317
271
  // Top anchor
318
272
  // Weapon and powerup icons
319
- WEAPON_ICON_X: 10 * scale,
320
- WEAPON_ICON_Y: height - (REFERENCE_HEIGHT - 450) * scale,
321
- POWERUP_X: width - (REFERENCE_WIDTH - 610) * scale,
322
- POWERUP_Y: height - (REFERENCE_HEIGHT - 450) * scale,
323
- scale
273
+ WEAPON_ICON_X: 10 * scale2,
274
+ WEAPON_ICON_Y: height - (REFERENCE_HEIGHT - 450) * scale2,
275
+ POWERUP_X: width - (REFERENCE_WIDTH - 610) * scale2,
276
+ POWERUP_Y: height - (REFERENCE_HEIGHT - 450) * scale2,
277
+ scale: scale2
324
278
  };
325
279
  };
326
280
 
@@ -352,7 +306,7 @@ function CG_TouchPics() {
352
306
  Init_Icons(cgi);
353
307
  Init_Damage(cgi);
354
308
  }
355
- function CG_DrawHUD(isplit, data, hud_vrect, hud_safe, scale, playernum, ps) {
309
+ function CG_DrawHUD(isplit, data, hud_vrect, hud_safe, scale2, playernum, ps) {
356
310
  if (!cgi) {
357
311
  console.error("CG_DrawHUD: cgame imports not initialized");
358
312
  return;
@@ -360,19 +314,7 @@ function CG_DrawHUD(isplit, data, hud_vrect, hud_safe, scale, playernum, ps) {
360
314
  const timeMs = cgi.CL_ClientTime();
361
315
  const layout = getHudLayout(hud_vrect.width, hud_vrect.height);
362
316
  Draw_Blends(cgi, ps, hud_vrect.width, hud_vrect.height);
363
- const tempClientState = {
364
- inventory: {
365
- armor: null,
366
- // TODO: Map from ps.stats
367
- powerups: /* @__PURE__ */ new Map(),
368
- // TODO: Map from ps.stats
369
- keys: /* @__PURE__ */ new Set(),
370
- // TODO: Map from ps.stats
371
- currentWeapon: void 0
372
- // TODO: Map from ps.stats/gunindex
373
- }
374
- };
375
- Draw_StatusBar(cgi, tempClientState, 100, 0, 0, hudNumberPics, numberWidth, timeMs, layout);
317
+ Draw_StatusBar(cgi, ps, hudNumberPics, numberWidth, timeMs, layout);
376
318
  Draw_Pickup(cgi, ps, hud_vrect.width, hud_vrect.height);
377
319
  Draw_Damage(cgi, ps, hud_vrect.width, hud_vrect.height);
378
320
  if (ps.centerPrint) {
@@ -389,6 +331,725 @@ function CG_GetMessageSystem() {
389
331
  return messageSystem;
390
332
  }
391
333
 
334
+ // ../../node_modules/.pnpm/gl-matrix@3.4.4/node_modules/gl-matrix/esm/common.js
335
+ var EPSILON = 1e-6;
336
+ var ARRAY_TYPE = typeof Float32Array !== "undefined" ? Float32Array : Array;
337
+ var RANDOM = Math.random;
338
+ function round(a) {
339
+ if (a >= 0) return Math.round(a);
340
+ return a % 0.5 === 0 ? Math.floor(a) : Math.round(a);
341
+ }
342
+
343
+ // ../../node_modules/.pnpm/gl-matrix@3.4.4/node_modules/gl-matrix/esm/vec3.js
344
+ var vec3_exports = {};
345
+ __export(vec3_exports, {
346
+ add: () => add,
347
+ angle: () => angle,
348
+ bezier: () => bezier,
349
+ ceil: () => ceil,
350
+ clone: () => clone,
351
+ copy: () => copy,
352
+ create: () => create,
353
+ cross: () => cross,
354
+ dist: () => dist,
355
+ distance: () => distance,
356
+ div: () => div,
357
+ divide: () => divide,
358
+ dot: () => dot,
359
+ equals: () => equals,
360
+ exactEquals: () => exactEquals,
361
+ floor: () => floor,
362
+ forEach: () => forEach,
363
+ fromValues: () => fromValues,
364
+ hermite: () => hermite,
365
+ inverse: () => inverse,
366
+ len: () => len,
367
+ length: () => length,
368
+ lerp: () => lerp,
369
+ max: () => max,
370
+ min: () => min,
371
+ mul: () => mul,
372
+ multiply: () => multiply,
373
+ negate: () => negate,
374
+ normalize: () => normalize,
375
+ random: () => random,
376
+ rotateX: () => rotateX,
377
+ rotateY: () => rotateY,
378
+ rotateZ: () => rotateZ,
379
+ round: () => round2,
380
+ scale: () => scale,
381
+ scaleAndAdd: () => scaleAndAdd,
382
+ set: () => set,
383
+ slerp: () => slerp,
384
+ sqrDist: () => sqrDist,
385
+ sqrLen: () => sqrLen,
386
+ squaredDistance: () => squaredDistance,
387
+ squaredLength: () => squaredLength,
388
+ str: () => str,
389
+ sub: () => sub,
390
+ subtract: () => subtract,
391
+ transformMat3: () => transformMat3,
392
+ transformMat4: () => transformMat4,
393
+ transformQuat: () => transformQuat,
394
+ zero: () => zero
395
+ });
396
+ function create() {
397
+ var out = new ARRAY_TYPE(3);
398
+ if (ARRAY_TYPE != Float32Array) {
399
+ out[0] = 0;
400
+ out[1] = 0;
401
+ out[2] = 0;
402
+ }
403
+ return out;
404
+ }
405
+ function clone(a) {
406
+ var out = new ARRAY_TYPE(3);
407
+ out[0] = a[0];
408
+ out[1] = a[1];
409
+ out[2] = a[2];
410
+ return out;
411
+ }
412
+ function length(a) {
413
+ var x = a[0];
414
+ var y = a[1];
415
+ var z = a[2];
416
+ return Math.sqrt(x * x + y * y + z * z);
417
+ }
418
+ function fromValues(x, y, z) {
419
+ var out = new ARRAY_TYPE(3);
420
+ out[0] = x;
421
+ out[1] = y;
422
+ out[2] = z;
423
+ return out;
424
+ }
425
+ function copy(out, a) {
426
+ out[0] = a[0];
427
+ out[1] = a[1];
428
+ out[2] = a[2];
429
+ return out;
430
+ }
431
+ function set(out, x, y, z) {
432
+ out[0] = x;
433
+ out[1] = y;
434
+ out[2] = z;
435
+ return out;
436
+ }
437
+ function add(out, a, b) {
438
+ out[0] = a[0] + b[0];
439
+ out[1] = a[1] + b[1];
440
+ out[2] = a[2] + b[2];
441
+ return out;
442
+ }
443
+ function subtract(out, a, b) {
444
+ out[0] = a[0] - b[0];
445
+ out[1] = a[1] - b[1];
446
+ out[2] = a[2] - b[2];
447
+ return out;
448
+ }
449
+ function multiply(out, a, b) {
450
+ out[0] = a[0] * b[0];
451
+ out[1] = a[1] * b[1];
452
+ out[2] = a[2] * b[2];
453
+ return out;
454
+ }
455
+ function divide(out, a, b) {
456
+ out[0] = a[0] / b[0];
457
+ out[1] = a[1] / b[1];
458
+ out[2] = a[2] / b[2];
459
+ return out;
460
+ }
461
+ function ceil(out, a) {
462
+ out[0] = Math.ceil(a[0]);
463
+ out[1] = Math.ceil(a[1]);
464
+ out[2] = Math.ceil(a[2]);
465
+ return out;
466
+ }
467
+ function floor(out, a) {
468
+ out[0] = Math.floor(a[0]);
469
+ out[1] = Math.floor(a[1]);
470
+ out[2] = Math.floor(a[2]);
471
+ return out;
472
+ }
473
+ function min(out, a, b) {
474
+ out[0] = Math.min(a[0], b[0]);
475
+ out[1] = Math.min(a[1], b[1]);
476
+ out[2] = Math.min(a[2], b[2]);
477
+ return out;
478
+ }
479
+ function max(out, a, b) {
480
+ out[0] = Math.max(a[0], b[0]);
481
+ out[1] = Math.max(a[1], b[1]);
482
+ out[2] = Math.max(a[2], b[2]);
483
+ return out;
484
+ }
485
+ function round2(out, a) {
486
+ out[0] = round(a[0]);
487
+ out[1] = round(a[1]);
488
+ out[2] = round(a[2]);
489
+ return out;
490
+ }
491
+ function scale(out, a, b) {
492
+ out[0] = a[0] * b;
493
+ out[1] = a[1] * b;
494
+ out[2] = a[2] * b;
495
+ return out;
496
+ }
497
+ function scaleAndAdd(out, a, b, scale2) {
498
+ out[0] = a[0] + b[0] * scale2;
499
+ out[1] = a[1] + b[1] * scale2;
500
+ out[2] = a[2] + b[2] * scale2;
501
+ return out;
502
+ }
503
+ function distance(a, b) {
504
+ var x = b[0] - a[0];
505
+ var y = b[1] - a[1];
506
+ var z = b[2] - a[2];
507
+ return Math.sqrt(x * x + y * y + z * z);
508
+ }
509
+ function squaredDistance(a, b) {
510
+ var x = b[0] - a[0];
511
+ var y = b[1] - a[1];
512
+ var z = b[2] - a[2];
513
+ return x * x + y * y + z * z;
514
+ }
515
+ function squaredLength(a) {
516
+ var x = a[0];
517
+ var y = a[1];
518
+ var z = a[2];
519
+ return x * x + y * y + z * z;
520
+ }
521
+ function negate(out, a) {
522
+ out[0] = -a[0];
523
+ out[1] = -a[1];
524
+ out[2] = -a[2];
525
+ return out;
526
+ }
527
+ function inverse(out, a) {
528
+ out[0] = 1 / a[0];
529
+ out[1] = 1 / a[1];
530
+ out[2] = 1 / a[2];
531
+ return out;
532
+ }
533
+ function normalize(out, a) {
534
+ var x = a[0];
535
+ var y = a[1];
536
+ var z = a[2];
537
+ var len2 = x * x + y * y + z * z;
538
+ if (len2 > 0) {
539
+ len2 = 1 / Math.sqrt(len2);
540
+ }
541
+ out[0] = a[0] * len2;
542
+ out[1] = a[1] * len2;
543
+ out[2] = a[2] * len2;
544
+ return out;
545
+ }
546
+ function dot(a, b) {
547
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
548
+ }
549
+ function cross(out, a, b) {
550
+ var ax = a[0], ay = a[1], az = a[2];
551
+ var bx = b[0], by = b[1], bz = b[2];
552
+ out[0] = ay * bz - az * by;
553
+ out[1] = az * bx - ax * bz;
554
+ out[2] = ax * by - ay * bx;
555
+ return out;
556
+ }
557
+ function lerp(out, a, b, t) {
558
+ var ax = a[0];
559
+ var ay = a[1];
560
+ var az = a[2];
561
+ out[0] = ax + t * (b[0] - ax);
562
+ out[1] = ay + t * (b[1] - ay);
563
+ out[2] = az + t * (b[2] - az);
564
+ return out;
565
+ }
566
+ function slerp(out, a, b, t) {
567
+ var angle2 = Math.acos(Math.min(Math.max(dot(a, b), -1), 1));
568
+ var sinTotal = Math.sin(angle2);
569
+ var ratioA = Math.sin((1 - t) * angle2) / sinTotal;
570
+ var ratioB = Math.sin(t * angle2) / sinTotal;
571
+ out[0] = ratioA * a[0] + ratioB * b[0];
572
+ out[1] = ratioA * a[1] + ratioB * b[1];
573
+ out[2] = ratioA * a[2] + ratioB * b[2];
574
+ return out;
575
+ }
576
+ function hermite(out, a, b, c, d, t) {
577
+ var factorTimes2 = t * t;
578
+ var factor1 = factorTimes2 * (2 * t - 3) + 1;
579
+ var factor2 = factorTimes2 * (t - 2) + t;
580
+ var factor3 = factorTimes2 * (t - 1);
581
+ var factor4 = factorTimes2 * (3 - 2 * t);
582
+ out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
583
+ out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
584
+ out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
585
+ return out;
586
+ }
587
+ function bezier(out, a, b, c, d, t) {
588
+ var inverseFactor = 1 - t;
589
+ var inverseFactorTimesTwo = inverseFactor * inverseFactor;
590
+ var factorTimes2 = t * t;
591
+ var factor1 = inverseFactorTimesTwo * inverseFactor;
592
+ var factor2 = 3 * t * inverseFactorTimesTwo;
593
+ var factor3 = 3 * factorTimes2 * inverseFactor;
594
+ var factor4 = factorTimes2 * t;
595
+ out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
596
+ out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
597
+ out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
598
+ return out;
599
+ }
600
+ function random(out, scale2) {
601
+ scale2 = scale2 === void 0 ? 1 : scale2;
602
+ var r = RANDOM() * 2 * Math.PI;
603
+ var z = RANDOM() * 2 - 1;
604
+ var zScale = Math.sqrt(1 - z * z) * scale2;
605
+ out[0] = Math.cos(r) * zScale;
606
+ out[1] = Math.sin(r) * zScale;
607
+ out[2] = z * scale2;
608
+ return out;
609
+ }
610
+ function transformMat4(out, a, m) {
611
+ var x = a[0], y = a[1], z = a[2];
612
+ var w = m[3] * x + m[7] * y + m[11] * z + m[15];
613
+ w = w || 1;
614
+ out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
615
+ out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
616
+ out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
617
+ return out;
618
+ }
619
+ function transformMat3(out, a, m) {
620
+ var x = a[0], y = a[1], z = a[2];
621
+ out[0] = x * m[0] + y * m[3] + z * m[6];
622
+ out[1] = x * m[1] + y * m[4] + z * m[7];
623
+ out[2] = x * m[2] + y * m[5] + z * m[8];
624
+ return out;
625
+ }
626
+ function transformQuat(out, a, q) {
627
+ var qx = q[0], qy = q[1], qz = q[2], qw = q[3];
628
+ var vx = a[0], vy = a[1], vz = a[2];
629
+ var tx = qy * vz - qz * vy;
630
+ var ty = qz * vx - qx * vz;
631
+ var tz = qx * vy - qy * vx;
632
+ tx = tx + tx;
633
+ ty = ty + ty;
634
+ tz = tz + tz;
635
+ out[0] = vx + qw * tx + qy * tz - qz * ty;
636
+ out[1] = vy + qw * ty + qz * tx - qx * tz;
637
+ out[2] = vz + qw * tz + qx * ty - qy * tx;
638
+ return out;
639
+ }
640
+ function rotateX(out, a, b, rad) {
641
+ var p = [], r = [];
642
+ p[0] = a[0] - b[0];
643
+ p[1] = a[1] - b[1];
644
+ p[2] = a[2] - b[2];
645
+ r[0] = p[0];
646
+ r[1] = p[1] * Math.cos(rad) - p[2] * Math.sin(rad);
647
+ r[2] = p[1] * Math.sin(rad) + p[2] * Math.cos(rad);
648
+ out[0] = r[0] + b[0];
649
+ out[1] = r[1] + b[1];
650
+ out[2] = r[2] + b[2];
651
+ return out;
652
+ }
653
+ function rotateY(out, a, b, rad) {
654
+ var p = [], r = [];
655
+ p[0] = a[0] - b[0];
656
+ p[1] = a[1] - b[1];
657
+ p[2] = a[2] - b[2];
658
+ r[0] = p[2] * Math.sin(rad) + p[0] * Math.cos(rad);
659
+ r[1] = p[1];
660
+ r[2] = p[2] * Math.cos(rad) - p[0] * Math.sin(rad);
661
+ out[0] = r[0] + b[0];
662
+ out[1] = r[1] + b[1];
663
+ out[2] = r[2] + b[2];
664
+ return out;
665
+ }
666
+ function rotateZ(out, a, b, rad) {
667
+ var p = [], r = [];
668
+ p[0] = a[0] - b[0];
669
+ p[1] = a[1] - b[1];
670
+ p[2] = a[2] - b[2];
671
+ r[0] = p[0] * Math.cos(rad) - p[1] * Math.sin(rad);
672
+ r[1] = p[0] * Math.sin(rad) + p[1] * Math.cos(rad);
673
+ r[2] = p[2];
674
+ out[0] = r[0] + b[0];
675
+ out[1] = r[1] + b[1];
676
+ out[2] = r[2] + b[2];
677
+ return out;
678
+ }
679
+ function angle(a, b) {
680
+ var ax = a[0], ay = a[1], az = a[2], bx = b[0], by = b[1], bz = b[2], mag = Math.sqrt((ax * ax + ay * ay + az * az) * (bx * bx + by * by + bz * bz)), cosine = mag && dot(a, b) / mag;
681
+ return Math.acos(Math.min(Math.max(cosine, -1), 1));
682
+ }
683
+ function zero(out) {
684
+ out[0] = 0;
685
+ out[1] = 0;
686
+ out[2] = 0;
687
+ return out;
688
+ }
689
+ function str(a) {
690
+ return "vec3(" + a[0] + ", " + a[1] + ", " + a[2] + ")";
691
+ }
692
+ function exactEquals(a, b) {
693
+ return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];
694
+ }
695
+ function equals(a, b) {
696
+ var a0 = a[0], a1 = a[1], a2 = a[2];
697
+ var b0 = b[0], b1 = b[1], b2 = b[2];
698
+ return Math.abs(a0 - b0) <= EPSILON * Math.max(1, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1, Math.abs(a2), Math.abs(b2));
699
+ }
700
+ var sub = subtract;
701
+ var mul = multiply;
702
+ var div = divide;
703
+ var dist = distance;
704
+ var sqrDist = squaredDistance;
705
+ var len = length;
706
+ var sqrLen = squaredLength;
707
+ var forEach = (function() {
708
+ var vec = create();
709
+ return function(a, stride, offset, count, fn, arg) {
710
+ var i, l;
711
+ if (!stride) {
712
+ stride = 3;
713
+ }
714
+ if (!offset) {
715
+ offset = 0;
716
+ }
717
+ if (count) {
718
+ l = Math.min(count * stride + offset, a.length);
719
+ } else {
720
+ l = a.length;
721
+ }
722
+ for (i = offset; i < l; i += stride) {
723
+ vec[0] = a[i];
724
+ vec[1] = a[i + 1];
725
+ vec[2] = a[i + 2];
726
+ fn(vec, vec, arg);
727
+ a[i] = vec[0];
728
+ a[i + 1] = vec[1];
729
+ a[i + 2] = vec[2];
730
+ }
731
+ return a;
732
+ };
733
+ })();
734
+
735
+ // src/view/camera.ts
736
+ var toGlMatrixVec3 = (v) => {
737
+ return vec3_exports.fromValues(v.x, v.y, v.z);
738
+ };
739
+ var updateCamera = (camera, viewSample) => {
740
+ camera.bobAngles = toGlMatrixVec3(viewSample.angles);
741
+ camera.bobOffset = toGlMatrixVec3(viewSample.offset);
742
+ };
743
+ var DEFAULT_SETTINGS = {
744
+ runPitch: 2e-3,
745
+ runRoll: 0.01,
746
+ // Changed from 0.005 to match Quake 2 slope (2.0 / 200.0)
747
+ bobUp: 5e-3,
748
+ bobPitch: 2e-3,
749
+ bobRoll: 2e-3,
750
+ maxBobHeight: 6,
751
+ maxBobAngle: 1.2
752
+ };
753
+ function clampViewOffset(offset) {
754
+ return {
755
+ x: Math.max(-14, Math.min(14, offset.x)),
756
+ y: Math.max(-14, Math.min(14, offset.y)),
757
+ z: Math.max(-22, Math.min(30, offset.z))
758
+ };
759
+ }
760
+ function computeBobMove(xyspeed, onGround, frameTimeMs) {
761
+ if (!onGround) return 0;
762
+ if (xyspeed > 210) return frameTimeMs / 400;
763
+ if (xyspeed > 100) return frameTimeMs / 800;
764
+ return frameTimeMs / 1600;
765
+ }
766
+ function computeBobValues(previousBobTime, xyspeed, pmFlags, onGround, frameTimeMs) {
767
+ if (xyspeed < 5) {
768
+ return { bobTime: 0, bobCycle: 0, bobCycleRun: 0, bobFracSin: 0 };
769
+ }
770
+ const bobMove = computeBobMove(xyspeed, onGround, frameTimeMs);
771
+ const bobTimeRun = previousBobTime + bobMove;
772
+ const crouched = hasPmFlag(pmFlags, PmFlag.Ducked) && onGround;
773
+ const bobTime = crouched ? bobTimeRun * 4 : bobTimeRun;
774
+ return {
775
+ bobTime: bobTimeRun,
776
+ bobCycle: Math.floor(bobTime),
777
+ bobCycleRun: Math.floor(bobTimeRun),
778
+ bobFracSin: Math.abs(Math.sin(bobTime * Math.PI))
779
+ };
780
+ }
781
+ var ViewEffects = class {
782
+ constructor(settings = {}) {
783
+ this.bobTime = 0;
784
+ this.bobCycle = 0;
785
+ this.bobCycleRun = 0;
786
+ this.bobFracSin = 0;
787
+ this.settings = { ...DEFAULT_SETTINGS, ...settings };
788
+ }
789
+ addKick(kick) {
790
+ if (kick.durationMs <= 0) return;
791
+ this.kick = { ...kick, remainingMs: kick.durationMs };
792
+ }
793
+ get last() {
794
+ return this.lastSample;
795
+ }
796
+ sample(state, frameTimeMs) {
797
+ const { forward, right } = angleVectors(
798
+ clampViewAngles({ pmFlags: state.pmFlags, cmdAngles: state.viewAngles, deltaAngles: state.deltaAngles ?? ZERO_VEC3 }).viewangles
799
+ );
800
+ const xyspeed = Math.sqrt(state.velocity.x * state.velocity.x + state.velocity.y * state.velocity.y);
801
+ const onGround = hasPmFlag(state.pmFlags, PmFlag.OnGround);
802
+ const bobValues = computeBobValues(this.bobTime, xyspeed, state.pmFlags, onGround, frameTimeMs);
803
+ this.bobTime = bobValues.bobTime;
804
+ this.bobCycle = bobValues.bobCycle;
805
+ this.bobCycleRun = bobValues.bobCycleRun;
806
+ this.bobFracSin = bobValues.bobFracSin;
807
+ let pitchTilt = dotVec3(state.velocity, forward) * this.settings.runPitch;
808
+ const side = dotVec3(state.velocity, right);
809
+ const sign = side < 0 ? -1 : 1;
810
+ const absSide = Math.abs(side);
811
+ let rollTilt = absSide * this.settings.runRoll;
812
+ if (rollTilt > 2) {
813
+ rollTilt = 2;
814
+ }
815
+ rollTilt *= sign;
816
+ let pitchDelta = this.bobFracSin * this.settings.bobPitch * xyspeed;
817
+ let rollDelta = this.bobFracSin * this.settings.bobRoll * xyspeed;
818
+ if (hasPmFlag(state.pmFlags, PmFlag.Ducked) && onGround) {
819
+ pitchDelta *= 6;
820
+ rollDelta *= 6;
821
+ }
822
+ pitchTilt += Math.min(pitchDelta, this.settings.maxBobAngle);
823
+ rollDelta = Math.min(rollDelta, this.settings.maxBobAngle);
824
+ if (this.bobCycle & 1) rollDelta = -rollDelta;
825
+ rollTilt += rollDelta;
826
+ const bobHeight = Math.min(this.bobFracSin * xyspeed * this.settings.bobUp, this.settings.maxBobHeight);
827
+ let kickPitch = 0;
828
+ let kickRoll = 0;
829
+ if (this.kick && this.kick.remainingMs > 0) {
830
+ const ratio = Math.max(0, Math.min(1, this.kick.remainingMs / this.kick.durationMs));
831
+ kickPitch += ratio * this.kick.pitch;
832
+ kickRoll += ratio * this.kick.roll;
833
+ this.kick.remainingMs = Math.max(0, this.kick.remainingMs - frameTimeMs);
834
+ if (this.kick.remainingMs === 0) this.kick = void 0;
835
+ }
836
+ const angles = { x: pitchTilt + kickPitch, y: 0, z: rollTilt + kickRoll };
837
+ const offset = { x: 0, y: 0, z: bobHeight };
838
+ const sample = {
839
+ angles,
840
+ offset: clampViewOffset(offset),
841
+ bobCycle: this.bobCycle,
842
+ bobCycleRun: this.bobCycleRun,
843
+ bobFracSin: this.bobFracSin,
844
+ xyspeed
845
+ };
846
+ this.lastSample = sample;
847
+ return sample;
848
+ }
849
+ };
850
+ var DEFAULTS = {
851
+ pmFriction: 6,
852
+ pmStopSpeed: 100,
853
+ pmAccelerate: 10,
854
+ pmAirAccelerate: 1,
855
+ pmWaterAccelerate: 4,
856
+ pmWaterFriction: 1,
857
+ pmMaxSpeed: 300,
858
+ pmDuckSpeed: 100,
859
+ pmWaterSpeed: 400,
860
+ groundIsSlick: false
861
+ };
862
+ var DEFAULT_GRAVITY = 800;
863
+ var ZERO_VEC32 = { x: 0, y: 0, z: 0 };
864
+ var MSEC_MAX = 250;
865
+ function defaultPredictionState() {
866
+ return {
867
+ origin: ZERO_VEC32,
868
+ velocity: ZERO_VEC32,
869
+ viewAngles: ZERO_VEC32,
870
+ onGround: false,
871
+ // Physics fields
872
+ pmFlags: PmFlag.OnGround,
873
+ pmType: PmType.Normal,
874
+ waterLevel: WaterLevel.None,
875
+ gravity: DEFAULT_GRAVITY,
876
+ deltaAngles: ZERO_VEC32,
877
+ // Bounds
878
+ mins: { x: -16, y: -16, z: -24 },
879
+ maxs: { x: 16, y: 16, z: 32 },
880
+ // Visual/Game fields
881
+ damageAlpha: 0,
882
+ damageIndicators: [],
883
+ blend: [0, 0, 0, 0],
884
+ stats: [],
885
+ kick_angles: ZERO_VEC32,
886
+ gunoffset: ZERO_VEC32,
887
+ gunangles: ZERO_VEC32,
888
+ gunindex: 0,
889
+ // Optional fields
890
+ pickupIcon: void 0,
891
+ centerPrint: void 0,
892
+ notify: void 0,
893
+ client: void 0,
894
+ health: 0,
895
+ armor: 0,
896
+ ammo: 0
897
+ };
898
+ }
899
+ function normalizeState(state) {
900
+ if (!state) return defaultPredictionState();
901
+ return {
902
+ ...defaultPredictionState(),
903
+ ...state,
904
+ origin: { ...state.origin },
905
+ velocity: { ...state.velocity },
906
+ viewAngles: { ...state.viewAngles },
907
+ deltaAngles: state.deltaAngles ? { ...state.deltaAngles } : ZERO_VEC32,
908
+ blend: state.blend ? [...state.blend] : [0, 0, 0, 0],
909
+ damageIndicators: state.damageIndicators ? [...state.damageIndicators] : [],
910
+ stats: state.stats ? [...state.stats] : []
911
+ };
912
+ }
913
+ function lerp2(a, b, t) {
914
+ return a + (b - a) * t;
915
+ }
916
+ function lerpAngle(a, b, t) {
917
+ let delta = angleMod(b - a);
918
+ if (delta > 180) {
919
+ delta -= 360;
920
+ }
921
+ return angleMod(a + delta * t);
922
+ }
923
+ function interpolatePredictionState(previous, latest, alpha) {
924
+ const clamped = Math.max(0, Math.min(alpha, 1));
925
+ return {
926
+ ...latest,
927
+ // Default to latest for discrete fields
928
+ origin: {
929
+ x: lerp2(previous.origin.x, latest.origin.x, clamped),
930
+ y: lerp2(previous.origin.y, latest.origin.y, clamped),
931
+ z: lerp2(previous.origin.z, latest.origin.z, clamped)
932
+ },
933
+ velocity: {
934
+ x: lerp2(previous.velocity.x, latest.velocity.x, clamped),
935
+ y: lerp2(previous.velocity.y, latest.velocity.y, clamped),
936
+ z: lerp2(previous.velocity.z, latest.velocity.z, clamped)
937
+ },
938
+ viewAngles: {
939
+ x: lerpAngle(previous.viewAngles.x, latest.viewAngles.x, clamped),
940
+ y: lerpAngle(previous.viewAngles.y, latest.viewAngles.y, clamped),
941
+ z: lerpAngle(previous.viewAngles.z, latest.viewAngles.z, clamped)
942
+ },
943
+ damageAlpha: lerp2(previous.damageAlpha, latest.damageAlpha, clamped),
944
+ blend: [
945
+ lerp2(previous.blend[0], latest.blend[0], clamped),
946
+ lerp2(previous.blend[1], latest.blend[1], clamped),
947
+ lerp2(previous.blend[2], latest.blend[2], clamped),
948
+ lerp2(previous.blend[3], latest.blend[3], clamped)
949
+ ],
950
+ // Interpolate health/armor for smooth HUD? Usually step.
951
+ health: lerp2(previous.health || 0, latest.health || 0, clamped),
952
+ armor: lerp2(previous.armor || 0, latest.armor || 0, clamped),
953
+ ammo: lerp2(previous.ammo || 0, latest.ammo || 0, clamped)
954
+ };
955
+ }
956
+ function simulateCommand(state, cmd, settings, trace) {
957
+ const frametime = Math.min(Math.max(cmd.msec, 0), MSEC_MAX) / 1e3;
958
+ const onGround = hasPmFlag(state.pmFlags, PmFlag.OnGround);
959
+ const onLadder = hasPmFlag(state.pmFlags, PmFlag.OnLadder);
960
+ let velocity = applyPmoveFriction({
961
+ velocity: state.velocity,
962
+ frametime,
963
+ onGround,
964
+ groundIsSlick: settings.groundIsSlick,
965
+ onLadder,
966
+ waterlevel: state.waterLevel,
967
+ pmFriction: settings.pmFriction,
968
+ pmStopSpeed: settings.pmStopSpeed,
969
+ pmWaterFriction: settings.pmWaterFriction
970
+ });
971
+ const { viewangles, forward, right } = clampViewAngles({
972
+ pmFlags: state.pmFlags,
973
+ cmdAngles: cmd.angles,
974
+ deltaAngles: state.deltaAngles ?? ZERO_VEC32
975
+ });
976
+ const wish = state.waterLevel > WaterLevel.None ? buildWaterWish({ forward, right, cmd, maxSpeed: settings.pmWaterSpeed }) : buildAirGroundWish({ forward, right, cmd, maxSpeed: settings.pmMaxSpeed });
977
+ if (state.waterLevel > WaterLevel.None) {
978
+ velocity = applyPmoveAccelerate({
979
+ velocity,
980
+ wishdir: wish.wishdir,
981
+ wishspeed: wish.wishspeed,
982
+ accel: settings.pmWaterAccelerate,
983
+ frametime
984
+ });
985
+ } else if (onGround || onLadder) {
986
+ const maxSpeed = hasPmFlag(state.pmFlags, PmFlag.Ducked) ? settings.pmDuckSpeed : settings.pmMaxSpeed;
987
+ const clampedWish = wish.wishspeed > maxSpeed ? {
988
+ wishdir: wish.wishdir,
989
+ wishspeed: maxSpeed
990
+ } : wish;
991
+ velocity = applyPmoveAccelerate({
992
+ velocity,
993
+ wishdir: clampedWish.wishdir,
994
+ wishspeed: clampedWish.wishspeed,
995
+ accel: settings.pmAccelerate,
996
+ frametime
997
+ });
998
+ } else {
999
+ velocity = applyPmoveAirAccelerate({
1000
+ velocity,
1001
+ wishdir: wish.wishdir,
1002
+ wishspeed: wish.wishspeed,
1003
+ accel: settings.pmAirAccelerate,
1004
+ frametime
1005
+ });
1006
+ velocity = { ...velocity, z: velocity.z - (state.gravity ?? DEFAULT_GRAVITY) * frametime };
1007
+ }
1008
+ const traceResult = trace(state.origin, addVec3(state.origin, scaleVec3(velocity, frametime)));
1009
+ const origin = traceResult.endpos;
1010
+ return {
1011
+ ...state,
1012
+ origin,
1013
+ velocity,
1014
+ viewAngles: viewangles
1015
+ };
1016
+ }
1017
+ var ClientPrediction = class {
1018
+ constructor(trace, settings = {}) {
1019
+ this.baseFrame = {
1020
+ frame: 0,
1021
+ timeMs: 0,
1022
+ state: defaultPredictionState()
1023
+ };
1024
+ this.commands = [];
1025
+ this.predicted = defaultPredictionState();
1026
+ this.settings = { ...DEFAULTS, ...settings };
1027
+ this.trace = trace;
1028
+ this.predicted = this.baseFrame.state ?? defaultPredictionState();
1029
+ }
1030
+ setAuthoritative(frame) {
1031
+ const normalized = normalizeState(frame.state);
1032
+ this.baseFrame = { ...frame, state: normalized };
1033
+ this.commands = this.commands.filter((cmd) => (cmd.serverFrame ?? Number.MAX_SAFE_INTEGER) > frame.frame);
1034
+ return this.recompute();
1035
+ }
1036
+ enqueueCommand(cmd) {
1037
+ this.commands.push(cmd);
1038
+ return this.recompute();
1039
+ }
1040
+ getPredictedState() {
1041
+ return this.predicted;
1042
+ }
1043
+ recompute() {
1044
+ let state = normalizeState(this.baseFrame.state);
1045
+ for (const cmd of this.commands) {
1046
+ state = simulateCommand(state, cmd, this.settings, this.trace);
1047
+ }
1048
+ this.predicted = state;
1049
+ return state;
1050
+ }
1051
+ };
1052
+
392
1053
  // src/index.ts
393
1054
  var cgi2 = null;
394
1055
  function Init() {
@@ -406,8 +1067,8 @@ function Shutdown() {
406
1067
  }
407
1068
  cgi2 = null;
408
1069
  }
409
- function DrawHUD(isplit, data, hud_vrect, hud_safe, scale, playernum, ps) {
410
- CG_DrawHUD(isplit, data, hud_vrect, hud_safe, scale, playernum, ps);
1070
+ function DrawHUD(isplit, data, hud_vrect, hud_safe, scale2, playernum, ps) {
1071
+ CG_DrawHUD(isplit, data, hud_vrect, hud_safe, scale2, playernum, ps);
411
1072
  }
412
1073
  function TouchPics() {
413
1074
  CG_TouchPics();
@@ -434,10 +1095,10 @@ function Pmove(pmove) {
434
1095
  }
435
1096
  function ParseConfigString(i, s) {
436
1097
  }
437
- function ParseCenterPrint(str, isplit, instant) {
1098
+ function ParseCenterPrint(str2, isplit, instant) {
438
1099
  if (!cgi2) return;
439
1100
  const messageSystem2 = CG_GetMessageSystem();
440
- messageSystem2.setCenterPrint(str, cgi2.CL_ClientTime());
1101
+ messageSystem2.setCenterPrint(str2, cgi2.CL_ClientTime());
441
1102
  }
442
1103
  function NotifyMessage(isplit, msg, is_chat) {
443
1104
  if (!cgi2) return;
@@ -492,6 +1153,6 @@ function GetCGameAPI(imports) {
492
1153
  };
493
1154
  }
494
1155
 
495
- export { GetCGameAPI };
1156
+ export { ClientPrediction, GetCGameAPI, ViewEffects, defaultPredictionState, interpolatePredictionState, updateCamera };
496
1157
  //# sourceMappingURL=index.js.map
497
1158
  //# sourceMappingURL=index.js.map