quake2ts 0.0.408 → 0.0.412

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 (53) hide show
  1. package/package.json +1 -1
  2. package/packages/client/dist/browser/index.global.js +16 -16
  3. package/packages/client/dist/browser/index.global.js.map +1 -1
  4. package/packages/client/dist/cjs/index.cjs +492 -81
  5. package/packages/client/dist/cjs/index.cjs.map +1 -1
  6. package/packages/client/dist/esm/index.js +492 -81
  7. package/packages/client/dist/esm/index.js.map +1 -1
  8. package/packages/client/dist/tsconfig.tsbuildinfo +1 -1
  9. package/packages/client/dist/types/demo/handler.d.ts +3 -0
  10. package/packages/client/dist/types/demo/handler.d.ts.map +1 -1
  11. package/packages/client/dist/types/effects-system.d.ts +17 -0
  12. package/packages/client/dist/types/effects-system.d.ts.map +1 -0
  13. package/packages/client/dist/types/index.d.ts +2 -0
  14. package/packages/client/dist/types/index.d.ts.map +1 -1
  15. package/packages/client/dist/types/net/connection.d.ts +21 -4
  16. package/packages/client/dist/types/net/connection.d.ts.map +1 -1
  17. package/packages/engine/dist/browser/index.global.js +14 -14
  18. package/packages/engine/dist/browser/index.global.js.map +1 -1
  19. package/packages/engine/dist/cjs/index.cjs +142 -14
  20. package/packages/engine/dist/cjs/index.cjs.map +1 -1
  21. package/packages/engine/dist/esm/index.js +141 -14
  22. package/packages/engine/dist/esm/index.js.map +1 -1
  23. package/packages/engine/dist/tsconfig.tsbuildinfo +1 -1
  24. package/packages/engine/dist/types/assets/headlessLoader.d.ts +11 -0
  25. package/packages/engine/dist/types/assets/headlessLoader.d.ts.map +1 -0
  26. package/packages/engine/dist/types/assets/vfs.d.ts +1 -0
  27. package/packages/engine/dist/types/assets/vfs.d.ts.map +1 -1
  28. package/packages/engine/dist/types/editor/bsp-inspector.d.ts +28 -0
  29. package/packages/engine/dist/types/editor/bsp-inspector.d.ts.map +1 -0
  30. package/packages/engine/dist/types/index.d.ts +1 -1
  31. package/packages/engine/dist/types/index.d.ts.map +1 -1
  32. package/packages/engine/dist/types/render/bsp/generator.d.ts +25 -0
  33. package/packages/engine/dist/types/render/bsp/generator.d.ts.map +1 -0
  34. package/packages/engine/dist/types/render/bsp/geometry.d.ts.map +1 -1
  35. package/packages/engine/dist/types/render/camera.d.ts +15 -0
  36. package/packages/engine/dist/types/render/camera.d.ts.map +1 -1
  37. package/packages/engine/dist/types/render/cameraController.d.ts +28 -0
  38. package/packages/engine/dist/types/render/cameraController.d.ts.map +1 -0
  39. package/packages/engine/dist/types/render/debug.d.ts +20 -0
  40. package/packages/engine/dist/types/render/debug.d.ts.map +1 -0
  41. package/packages/engine/dist/types/render/options.d.ts +9 -0
  42. package/packages/engine/dist/types/render/options.d.ts.map +1 -0
  43. package/packages/engine/dist/types/render/renderer.d.ts +4 -1
  44. package/packages/engine/dist/types/render/renderer.d.ts.map +1 -1
  45. package/packages/engine/dist/types/render/types.d.ts +22 -0
  46. package/packages/engine/dist/types/render/types.d.ts.map +1 -0
  47. package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
  48. package/packages/game/dist/types/editor/metadata.d.ts +31 -0
  49. package/packages/game/dist/types/editor/metadata.d.ts.map +1 -0
  50. package/packages/game/dist/types/editor/search.d.ts +9 -0
  51. package/packages/game/dist/types/editor/search.d.ts.map +1 -0
  52. package/packages/game/dist/types/editor/selection.d.ts +19 -0
  53. package/packages/game/dist/types/editor/selection.d.ts.map +1 -0
@@ -1880,6 +1880,7 @@ var DEG_TO_RAD = Math.PI / 180;
1880
1880
  var DEG2RAD_FACTOR = Math.PI / 180;
1881
1881
  var RAD2DEG_FACTOR = 180 / Math.PI;
1882
1882
  var DEG2RAD = DEG2RAD_FACTOR;
1883
+ var RAD2DEG = RAD2DEG_FACTOR;
1883
1884
  var ANORMS = [
1884
1885
  [-0.525731, 0, 0.850651],
1885
1886
  [-0.442863, 0.238856, 0.864188],
@@ -2220,72 +2221,72 @@ var ServerCommand = /* @__PURE__ */ ((ServerCommand22) => {
2220
2221
  ServerCommand22[ServerCommand22["achievement"] = 33] = "achievement";
2221
2222
  return ServerCommand22;
2222
2223
  })(ServerCommand || {});
2223
- var TempEntity = /* @__PURE__ */ ((TempEntity2) => {
2224
- TempEntity2[TempEntity2["GUNSHOT"] = 0] = "GUNSHOT";
2225
- TempEntity2[TempEntity2["BLOOD"] = 1] = "BLOOD";
2226
- TempEntity2[TempEntity2["BLASTER"] = 2] = "BLASTER";
2227
- TempEntity2[TempEntity2["RAILTRAIL"] = 3] = "RAILTRAIL";
2228
- TempEntity2[TempEntity2["SHOTGUN"] = 4] = "SHOTGUN";
2229
- TempEntity2[TempEntity2["EXPLOSION1"] = 5] = "EXPLOSION1";
2230
- TempEntity2[TempEntity2["EXPLOSION2"] = 6] = "EXPLOSION2";
2231
- TempEntity2[TempEntity2["ROCKET_EXPLOSION"] = 7] = "ROCKET_EXPLOSION";
2232
- TempEntity2[TempEntity2["GRENADE_EXPLOSION"] = 8] = "GRENADE_EXPLOSION";
2233
- TempEntity2[TempEntity2["SPARKS"] = 9] = "SPARKS";
2234
- TempEntity2[TempEntity2["SPLASH"] = 10] = "SPLASH";
2235
- TempEntity2[TempEntity2["BUBBLETRAIL"] = 11] = "BUBBLETRAIL";
2236
- TempEntity2[TempEntity2["SCREEN_SPARKS"] = 12] = "SCREEN_SPARKS";
2237
- TempEntity2[TempEntity2["SHIELD_SPARKS"] = 13] = "SHIELD_SPARKS";
2238
- TempEntity2[TempEntity2["BULLET_SPARKS"] = 14] = "BULLET_SPARKS";
2239
- TempEntity2[TempEntity2["LASER_SPARKS"] = 15] = "LASER_SPARKS";
2240
- TempEntity2[TempEntity2["PARASITE_ATTACK"] = 16] = "PARASITE_ATTACK";
2241
- TempEntity2[TempEntity2["ROCKET_EXPLOSION_WATER"] = 17] = "ROCKET_EXPLOSION_WATER";
2242
- TempEntity2[TempEntity2["GRENADE_EXPLOSION_WATER"] = 18] = "GRENADE_EXPLOSION_WATER";
2243
- TempEntity2[TempEntity2["MEDIC_CABLE_ATTACK"] = 19] = "MEDIC_CABLE_ATTACK";
2244
- TempEntity2[TempEntity2["BFG_EXPLOSION"] = 20] = "BFG_EXPLOSION";
2245
- TempEntity2[TempEntity2["BFG_BIGEXPLOSION"] = 21] = "BFG_BIGEXPLOSION";
2246
- TempEntity2[TempEntity2["BOSSTPORT"] = 22] = "BOSSTPORT";
2247
- TempEntity2[TempEntity2["BFG_LASER"] = 23] = "BFG_LASER";
2248
- TempEntity2[TempEntity2["GRAPPLE_CABLE"] = 24] = "GRAPPLE_CABLE";
2249
- TempEntity2[TempEntity2["WELDING_SPARKS"] = 25] = "WELDING_SPARKS";
2250
- TempEntity2[TempEntity2["GREENBLOOD"] = 26] = "GREENBLOOD";
2251
- TempEntity2[TempEntity2["BLUEHYPERBLASTER"] = 27] = "BLUEHYPERBLASTER";
2252
- TempEntity2[TempEntity2["PLASMA_EXPLOSION"] = 28] = "PLASMA_EXPLOSION";
2253
- TempEntity2[TempEntity2["TUNNEL_SPARKS"] = 29] = "TUNNEL_SPARKS";
2254
- TempEntity2[TempEntity2["BLASTER2"] = 30] = "BLASTER2";
2255
- TempEntity2[TempEntity2["RAILTRAIL2"] = 31] = "RAILTRAIL2";
2256
- TempEntity2[TempEntity2["FLAME"] = 32] = "FLAME";
2257
- TempEntity2[TempEntity2["LIGHTNING"] = 33] = "LIGHTNING";
2258
- TempEntity2[TempEntity2["DEBUGTRAIL"] = 34] = "DEBUGTRAIL";
2259
- TempEntity2[TempEntity2["PLAIN_EXPLOSION"] = 35] = "PLAIN_EXPLOSION";
2260
- TempEntity2[TempEntity2["FLASHLIGHT"] = 36] = "FLASHLIGHT";
2261
- TempEntity2[TempEntity2["FORCEWALL"] = 37] = "FORCEWALL";
2262
- TempEntity2[TempEntity2["HEATBEAM"] = 38] = "HEATBEAM";
2263
- TempEntity2[TempEntity2["MONSTER_HEATBEAM"] = 39] = "MONSTER_HEATBEAM";
2264
- TempEntity2[TempEntity2["STEAM"] = 40] = "STEAM";
2265
- TempEntity2[TempEntity2["BUBBLETRAIL2"] = 41] = "BUBBLETRAIL2";
2266
- TempEntity2[TempEntity2["MOREBLOOD"] = 42] = "MOREBLOOD";
2267
- TempEntity2[TempEntity2["HEATBEAM_SPARKS"] = 43] = "HEATBEAM_SPARKS";
2268
- TempEntity2[TempEntity2["HEATBEAM_STEAM"] = 44] = "HEATBEAM_STEAM";
2269
- TempEntity2[TempEntity2["CHAINFIST_SMOKE"] = 45] = "CHAINFIST_SMOKE";
2270
- TempEntity2[TempEntity2["ELECTRIC_SPARKS"] = 46] = "ELECTRIC_SPARKS";
2271
- TempEntity2[TempEntity2["TRACKER_EXPLOSION"] = 47] = "TRACKER_EXPLOSION";
2272
- TempEntity2[TempEntity2["TELEPORT_EFFECT"] = 48] = "TELEPORT_EFFECT";
2273
- TempEntity2[TempEntity2["DBALL_GOAL"] = 49] = "DBALL_GOAL";
2274
- TempEntity2[TempEntity2["WIDOWBEAMOUT"] = 50] = "WIDOWBEAMOUT";
2275
- TempEntity2[TempEntity2["NUKEBLAST"] = 51] = "NUKEBLAST";
2276
- TempEntity2[TempEntity2["WIDOWSPLASH"] = 52] = "WIDOWSPLASH";
2277
- TempEntity2[TempEntity2["EXPLOSION1_BIG"] = 53] = "EXPLOSION1_BIG";
2278
- TempEntity2[TempEntity2["EXPLOSION1_NP"] = 54] = "EXPLOSION1_NP";
2279
- TempEntity2[TempEntity2["FLECHETTE"] = 55] = "FLECHETTE";
2280
- TempEntity2[TempEntity2["BLUEHYPERBLASTER_KEX"] = 56] = "BLUEHYPERBLASTER_KEX";
2281
- TempEntity2[TempEntity2["BFG_ZAP"] = 57] = "BFG_ZAP";
2282
- TempEntity2[TempEntity2["BERSERK_SLAM"] = 58] = "BERSERK_SLAM";
2283
- TempEntity2[TempEntity2["GRAPPLE_CABLE_2"] = 59] = "GRAPPLE_CABLE_2";
2284
- TempEntity2[TempEntity2["POWER_SPLASH"] = 60] = "POWER_SPLASH";
2285
- TempEntity2[TempEntity2["LIGHTNING_BEAM"] = 61] = "LIGHTNING_BEAM";
2286
- TempEntity2[TempEntity2["EXPLOSION1_NL"] = 62] = "EXPLOSION1_NL";
2287
- TempEntity2[TempEntity2["EXPLOSION2_NL"] = 63] = "EXPLOSION2_NL";
2288
- return TempEntity2;
2224
+ var TempEntity = /* @__PURE__ */ ((TempEntity22) => {
2225
+ TempEntity22[TempEntity22["GUNSHOT"] = 0] = "GUNSHOT";
2226
+ TempEntity22[TempEntity22["BLOOD"] = 1] = "BLOOD";
2227
+ TempEntity22[TempEntity22["BLASTER"] = 2] = "BLASTER";
2228
+ TempEntity22[TempEntity22["RAILTRAIL"] = 3] = "RAILTRAIL";
2229
+ TempEntity22[TempEntity22["SHOTGUN"] = 4] = "SHOTGUN";
2230
+ TempEntity22[TempEntity22["EXPLOSION1"] = 5] = "EXPLOSION1";
2231
+ TempEntity22[TempEntity22["EXPLOSION2"] = 6] = "EXPLOSION2";
2232
+ TempEntity22[TempEntity22["ROCKET_EXPLOSION"] = 7] = "ROCKET_EXPLOSION";
2233
+ TempEntity22[TempEntity22["GRENADE_EXPLOSION"] = 8] = "GRENADE_EXPLOSION";
2234
+ TempEntity22[TempEntity22["SPARKS"] = 9] = "SPARKS";
2235
+ TempEntity22[TempEntity22["SPLASH"] = 10] = "SPLASH";
2236
+ TempEntity22[TempEntity22["BUBBLETRAIL"] = 11] = "BUBBLETRAIL";
2237
+ TempEntity22[TempEntity22["SCREEN_SPARKS"] = 12] = "SCREEN_SPARKS";
2238
+ TempEntity22[TempEntity22["SHIELD_SPARKS"] = 13] = "SHIELD_SPARKS";
2239
+ TempEntity22[TempEntity22["BULLET_SPARKS"] = 14] = "BULLET_SPARKS";
2240
+ TempEntity22[TempEntity22["LASER_SPARKS"] = 15] = "LASER_SPARKS";
2241
+ TempEntity22[TempEntity22["PARASITE_ATTACK"] = 16] = "PARASITE_ATTACK";
2242
+ TempEntity22[TempEntity22["ROCKET_EXPLOSION_WATER"] = 17] = "ROCKET_EXPLOSION_WATER";
2243
+ TempEntity22[TempEntity22["GRENADE_EXPLOSION_WATER"] = 18] = "GRENADE_EXPLOSION_WATER";
2244
+ TempEntity22[TempEntity22["MEDIC_CABLE_ATTACK"] = 19] = "MEDIC_CABLE_ATTACK";
2245
+ TempEntity22[TempEntity22["BFG_EXPLOSION"] = 20] = "BFG_EXPLOSION";
2246
+ TempEntity22[TempEntity22["BFG_BIGEXPLOSION"] = 21] = "BFG_BIGEXPLOSION";
2247
+ TempEntity22[TempEntity22["BOSSTPORT"] = 22] = "BOSSTPORT";
2248
+ TempEntity22[TempEntity22["BFG_LASER"] = 23] = "BFG_LASER";
2249
+ TempEntity22[TempEntity22["GRAPPLE_CABLE"] = 24] = "GRAPPLE_CABLE";
2250
+ TempEntity22[TempEntity22["WELDING_SPARKS"] = 25] = "WELDING_SPARKS";
2251
+ TempEntity22[TempEntity22["GREENBLOOD"] = 26] = "GREENBLOOD";
2252
+ TempEntity22[TempEntity22["BLUEHYPERBLASTER"] = 27] = "BLUEHYPERBLASTER";
2253
+ TempEntity22[TempEntity22["PLASMA_EXPLOSION"] = 28] = "PLASMA_EXPLOSION";
2254
+ TempEntity22[TempEntity22["TUNNEL_SPARKS"] = 29] = "TUNNEL_SPARKS";
2255
+ TempEntity22[TempEntity22["BLASTER2"] = 30] = "BLASTER2";
2256
+ TempEntity22[TempEntity22["RAILTRAIL2"] = 31] = "RAILTRAIL2";
2257
+ TempEntity22[TempEntity22["FLAME"] = 32] = "FLAME";
2258
+ TempEntity22[TempEntity22["LIGHTNING"] = 33] = "LIGHTNING";
2259
+ TempEntity22[TempEntity22["DEBUGTRAIL"] = 34] = "DEBUGTRAIL";
2260
+ TempEntity22[TempEntity22["PLAIN_EXPLOSION"] = 35] = "PLAIN_EXPLOSION";
2261
+ TempEntity22[TempEntity22["FLASHLIGHT"] = 36] = "FLASHLIGHT";
2262
+ TempEntity22[TempEntity22["FORCEWALL"] = 37] = "FORCEWALL";
2263
+ TempEntity22[TempEntity22["HEATBEAM"] = 38] = "HEATBEAM";
2264
+ TempEntity22[TempEntity22["MONSTER_HEATBEAM"] = 39] = "MONSTER_HEATBEAM";
2265
+ TempEntity22[TempEntity22["STEAM"] = 40] = "STEAM";
2266
+ TempEntity22[TempEntity22["BUBBLETRAIL2"] = 41] = "BUBBLETRAIL2";
2267
+ TempEntity22[TempEntity22["MOREBLOOD"] = 42] = "MOREBLOOD";
2268
+ TempEntity22[TempEntity22["HEATBEAM_SPARKS"] = 43] = "HEATBEAM_SPARKS";
2269
+ TempEntity22[TempEntity22["HEATBEAM_STEAM"] = 44] = "HEATBEAM_STEAM";
2270
+ TempEntity22[TempEntity22["CHAINFIST_SMOKE"] = 45] = "CHAINFIST_SMOKE";
2271
+ TempEntity22[TempEntity22["ELECTRIC_SPARKS"] = 46] = "ELECTRIC_SPARKS";
2272
+ TempEntity22[TempEntity22["TRACKER_EXPLOSION"] = 47] = "TRACKER_EXPLOSION";
2273
+ TempEntity22[TempEntity22["TELEPORT_EFFECT"] = 48] = "TELEPORT_EFFECT";
2274
+ TempEntity22[TempEntity22["DBALL_GOAL"] = 49] = "DBALL_GOAL";
2275
+ TempEntity22[TempEntity22["WIDOWBEAMOUT"] = 50] = "WIDOWBEAMOUT";
2276
+ TempEntity22[TempEntity22["NUKEBLAST"] = 51] = "NUKEBLAST";
2277
+ TempEntity22[TempEntity22["WIDOWSPLASH"] = 52] = "WIDOWSPLASH";
2278
+ TempEntity22[TempEntity22["EXPLOSION1_BIG"] = 53] = "EXPLOSION1_BIG";
2279
+ TempEntity22[TempEntity22["EXPLOSION1_NP"] = 54] = "EXPLOSION1_NP";
2280
+ TempEntity22[TempEntity22["FLECHETTE"] = 55] = "FLECHETTE";
2281
+ TempEntity22[TempEntity22["BLUEHYPERBLASTER_KEX"] = 56] = "BLUEHYPERBLASTER_KEX";
2282
+ TempEntity22[TempEntity22["BFG_ZAP"] = 57] = "BFG_ZAP";
2283
+ TempEntity22[TempEntity22["BERSERK_SLAM"] = 58] = "BERSERK_SLAM";
2284
+ TempEntity22[TempEntity22["GRAPPLE_CABLE_2"] = 59] = "GRAPPLE_CABLE_2";
2285
+ TempEntity22[TempEntity22["POWER_SPLASH"] = 60] = "POWER_SPLASH";
2286
+ TempEntity22[TempEntity22["LIGHTNING_BEAM"] = 61] = "LIGHTNING_BEAM";
2287
+ TempEntity22[TempEntity22["EXPLOSION1_NL"] = 62] = "EXPLOSION1_NL";
2288
+ TempEntity22[TempEntity22["EXPLOSION2_NL"] = 63] = "EXPLOSION2_NL";
2289
+ return TempEntity22;
2289
2290
  })(TempEntity || {});
2290
2291
  var AMMO_MAX = 12;
2291
2292
  var NUM_BITS_FOR_AMMO = 9;
@@ -3096,6 +3097,43 @@ var BSP_VERTEX_LAYOUT = [
3096
3097
  { index: 2, size: 2, type: 5126, stride: STRIDE, offset: 5 * FLOAT_BYTES }
3097
3098
  ];
3098
3099
  var MAX_DLIGHTS = 32;
3100
+ var DynamicLightManager = class {
3101
+ constructor() {
3102
+ this.lights = [];
3103
+ }
3104
+ /**
3105
+ * Adds a dynamic light or updates an existing one with the same key.
3106
+ */
3107
+ addLight(dlight, time) {
3108
+ if (dlight.key !== void 0) {
3109
+ const index = this.lights.findIndex((l) => l.key === dlight.key);
3110
+ if (index !== -1) {
3111
+ this.lights[index] = dlight;
3112
+ return;
3113
+ }
3114
+ }
3115
+ this.lights.push(dlight);
3116
+ }
3117
+ /**
3118
+ * Clears all lights (e.g., map change).
3119
+ */
3120
+ clear() {
3121
+ this.lights = [];
3122
+ }
3123
+ /**
3124
+ * Updates the list of active lights, removing expired ones.
3125
+ * @param time Current game time in seconds.
3126
+ */
3127
+ update(time) {
3128
+ this.lights = this.lights.filter((l) => l.die > time);
3129
+ }
3130
+ /**
3131
+ * Returns the current list of active lights.
3132
+ */
3133
+ getActiveLights() {
3134
+ return this.lights;
3135
+ }
3136
+ };
3099
3137
  var BSP_SURFACE_FRAGMENT_SOURCE = `#version 300 es
3100
3138
  precision highp float;
3101
3139
 
@@ -3403,15 +3441,21 @@ var Camera = class {
3403
3441
  return this._position;
3404
3442
  }
3405
3443
  set position(value) {
3406
- vec3_exports.copy(this._position, value);
3407
- this._dirty = true;
3444
+ if (!vec3_exports.equals(this._position, value)) {
3445
+ vec3_exports.copy(this._position, value);
3446
+ this._dirty = true;
3447
+ this.triggerMoveEvent();
3448
+ }
3408
3449
  }
3409
3450
  get angles() {
3410
3451
  return this._angles;
3411
3452
  }
3412
3453
  set angles(value) {
3413
- vec3_exports.copy(this._angles, value);
3414
- this._dirty = true;
3454
+ if (!vec3_exports.equals(this._angles, value)) {
3455
+ vec3_exports.copy(this._angles, value);
3456
+ this._dirty = true;
3457
+ this.triggerMoveEvent();
3458
+ }
3415
3459
  }
3416
3460
  get bobAngles() {
3417
3461
  return this._bobAngles;
@@ -3455,6 +3499,47 @@ var Camera = class {
3455
3499
  this._aspect = value;
3456
3500
  this._dirty = true;
3457
3501
  }
3502
+ // API Methods
3503
+ setPosition(x, y, z) {
3504
+ const newPos = vec3_exports.fromValues(x, y, z);
3505
+ if (!vec3_exports.equals(this._position, newPos)) {
3506
+ vec3_exports.copy(this._position, newPos);
3507
+ this._dirty = true;
3508
+ this.triggerMoveEvent();
3509
+ }
3510
+ }
3511
+ setRotation(pitch, yaw, roll) {
3512
+ const newAngles = vec3_exports.fromValues(pitch, yaw, roll);
3513
+ if (!vec3_exports.equals(this._angles, newAngles)) {
3514
+ vec3_exports.copy(this._angles, newAngles);
3515
+ this._dirty = true;
3516
+ this.triggerMoveEvent();
3517
+ }
3518
+ }
3519
+ setFov(fov) {
3520
+ this.fov = fov;
3521
+ }
3522
+ setAspectRatio(aspect) {
3523
+ this.aspect = aspect;
3524
+ }
3525
+ lookAt(target) {
3526
+ const direction = vec3_exports.create();
3527
+ vec3_exports.subtract(direction, target, this._position);
3528
+ const len2 = vec3_exports.length(direction);
3529
+ if (len2 < 1e-3) return;
3530
+ const yaw = Math.atan2(direction[1], direction[0]) * RAD2DEG;
3531
+ const hyp = Math.hypot(direction[0], direction[1]);
3532
+ const pitch = -Math.atan2(direction[2], hyp) * RAD2DEG;
3533
+ this.setRotation(pitch, yaw, 0);
3534
+ }
3535
+ triggerMoveEvent() {
3536
+ if (this.onCameraMove) {
3537
+ this.onCameraMove({
3538
+ position: vec3_exports.clone(this._position),
3539
+ angles: vec3_exports.clone(this._angles)
3540
+ });
3541
+ }
3542
+ }
3458
3543
  get viewMatrix() {
3459
3544
  this.updateMatrices();
3460
3545
  return this._viewMatrix;
@@ -3478,6 +3563,25 @@ var Camera = class {
3478
3563
  );
3479
3564
  return projectionMatrix;
3480
3565
  }
3566
+ screenToWorldRay(screenX, screenY) {
3567
+ const ndcX = screenX * 2 - 1;
3568
+ const ndcY = 1 - screenY * 2;
3569
+ const clipStart = vec3_exports.fromValues(ndcX, ndcY, -1);
3570
+ const clipEnd = vec3_exports.fromValues(ndcX, ndcY, 1);
3571
+ const invViewProj = mat4_exports.create();
3572
+ mat4_exports.invert(invViewProj, this.viewProjectionMatrix);
3573
+ const worldStart = vec3_exports.create();
3574
+ const worldEnd = vec3_exports.create();
3575
+ vec3_exports.transformMat4(worldStart, clipStart, invViewProj);
3576
+ vec3_exports.transformMat4(worldEnd, clipEnd, invViewProj);
3577
+ const direction = vec3_exports.create();
3578
+ vec3_exports.subtract(direction, worldEnd, worldStart);
3579
+ vec3_exports.normalize(direction, direction);
3580
+ return {
3581
+ origin: vec3_exports.clone(this._position),
3582
+ direction
3583
+ };
3584
+ }
3481
3585
  updateMatrices() {
3482
3586
  if (!this._dirty) {
3483
3587
  return;
@@ -3490,21 +3594,21 @@ var Camera = class {
3490
3594
  this._far
3491
3595
  );
3492
3596
  const quakeToGl = mat4_exports.fromValues(
3597
+ 0,
3493
3598
  0,
3494
3599
  -1,
3495
3600
  0,
3601
+ // column 0: Quake X -> WebGL -Z
3602
+ -1,
3496
3603
  0,
3497
- // column 0: Quake X -> WebGL (0, -1, 0)
3498
3604
  0,
3499
3605
  0,
3500
- 1,
3501
- 0,
3502
- // column 1: Quake Y -> WebGL (0, 0, 1)
3503
- -1,
3606
+ // column 1: Quake Y -> WebGL -X
3504
3607
  0,
3608
+ 1,
3505
3609
  0,
3506
3610
  0,
3507
- // column 2: Quake Z -> WebGL (-1, 0, 0)
3611
+ // column 2: Quake Z -> WebGL Y
3508
3612
  0,
3509
3613
  0,
3510
3614
  0,
@@ -3529,12 +3633,12 @@ var Camera = class {
3529
3633
  const rotatedPosQuake = vec3_exports.create();
3530
3634
  vec3_exports.transformMat4(rotatedPosQuake, negativePosition, rotationQuake);
3531
3635
  const translationGl = vec3_exports.fromValues(
3532
- rotatedPosQuake[1] || 0,
3533
- // Y in Quake -> X in WebGL (negation already applied above)
3636
+ rotatedPosQuake[1] ? -rotatedPosQuake[1] : 0,
3637
+ // Y in Quake -> -X in WebGL
3534
3638
  rotatedPosQuake[2] || 0,
3535
3639
  // Z in Quake -> Y in WebGL
3536
- rotatedPosQuake[0] || 0
3537
- // X in Quake -> Z in WebGL (negation already applied above)
3640
+ rotatedPosQuake[0] ? -rotatedPosQuake[0] : 0
3641
+ // X in Quake -> -Z in WebGL
3538
3642
  );
3539
3643
  mat4_exports.copy(this._viewMatrix, rotationGl);
3540
3644
  this._viewMatrix[12] = translationGl[0];
@@ -9895,6 +9999,73 @@ var ClientCommand = /* @__PURE__ */ ((ClientCommand2) => {
9895
9999
  ClientCommand2[ClientCommand2["stringcmd"] = 4] = "stringcmd";
9896
10000
  return ClientCommand2;
9897
10001
  })(ClientCommand || {});
10002
+ var TempEntity2 = /* @__PURE__ */ ((TempEntity22) => {
10003
+ TempEntity22[TempEntity22["GUNSHOT"] = 0] = "GUNSHOT";
10004
+ TempEntity22[TempEntity22["BLOOD"] = 1] = "BLOOD";
10005
+ TempEntity22[TempEntity22["BLASTER"] = 2] = "BLASTER";
10006
+ TempEntity22[TempEntity22["RAILTRAIL"] = 3] = "RAILTRAIL";
10007
+ TempEntity22[TempEntity22["SHOTGUN"] = 4] = "SHOTGUN";
10008
+ TempEntity22[TempEntity22["EXPLOSION1"] = 5] = "EXPLOSION1";
10009
+ TempEntity22[TempEntity22["EXPLOSION2"] = 6] = "EXPLOSION2";
10010
+ TempEntity22[TempEntity22["ROCKET_EXPLOSION"] = 7] = "ROCKET_EXPLOSION";
10011
+ TempEntity22[TempEntity22["GRENADE_EXPLOSION"] = 8] = "GRENADE_EXPLOSION";
10012
+ TempEntity22[TempEntity22["SPARKS"] = 9] = "SPARKS";
10013
+ TempEntity22[TempEntity22["SPLASH"] = 10] = "SPLASH";
10014
+ TempEntity22[TempEntity22["BUBBLETRAIL"] = 11] = "BUBBLETRAIL";
10015
+ TempEntity22[TempEntity22["SCREEN_SPARKS"] = 12] = "SCREEN_SPARKS";
10016
+ TempEntity22[TempEntity22["SHIELD_SPARKS"] = 13] = "SHIELD_SPARKS";
10017
+ TempEntity22[TempEntity22["BULLET_SPARKS"] = 14] = "BULLET_SPARKS";
10018
+ TempEntity22[TempEntity22["LASER_SPARKS"] = 15] = "LASER_SPARKS";
10019
+ TempEntity22[TempEntity22["PARASITE_ATTACK"] = 16] = "PARASITE_ATTACK";
10020
+ TempEntity22[TempEntity22["ROCKET_EXPLOSION_WATER"] = 17] = "ROCKET_EXPLOSION_WATER";
10021
+ TempEntity22[TempEntity22["GRENADE_EXPLOSION_WATER"] = 18] = "GRENADE_EXPLOSION_WATER";
10022
+ TempEntity22[TempEntity22["MEDIC_CABLE_ATTACK"] = 19] = "MEDIC_CABLE_ATTACK";
10023
+ TempEntity22[TempEntity22["BFG_EXPLOSION"] = 20] = "BFG_EXPLOSION";
10024
+ TempEntity22[TempEntity22["BFG_BIGEXPLOSION"] = 21] = "BFG_BIGEXPLOSION";
10025
+ TempEntity22[TempEntity22["BOSSTPORT"] = 22] = "BOSSTPORT";
10026
+ TempEntity22[TempEntity22["BFG_LASER"] = 23] = "BFG_LASER";
10027
+ TempEntity22[TempEntity22["GRAPPLE_CABLE"] = 24] = "GRAPPLE_CABLE";
10028
+ TempEntity22[TempEntity22["WELDING_SPARKS"] = 25] = "WELDING_SPARKS";
10029
+ TempEntity22[TempEntity22["GREENBLOOD"] = 26] = "GREENBLOOD";
10030
+ TempEntity22[TempEntity22["BLUEHYPERBLASTER"] = 27] = "BLUEHYPERBLASTER";
10031
+ TempEntity22[TempEntity22["PLASMA_EXPLOSION"] = 28] = "PLASMA_EXPLOSION";
10032
+ TempEntity22[TempEntity22["TUNNEL_SPARKS"] = 29] = "TUNNEL_SPARKS";
10033
+ TempEntity22[TempEntity22["BLASTER2"] = 30] = "BLASTER2";
10034
+ TempEntity22[TempEntity22["RAILTRAIL2"] = 31] = "RAILTRAIL2";
10035
+ TempEntity22[TempEntity22["FLAME"] = 32] = "FLAME";
10036
+ TempEntity22[TempEntity22["LIGHTNING"] = 33] = "LIGHTNING";
10037
+ TempEntity22[TempEntity22["DEBUGTRAIL"] = 34] = "DEBUGTRAIL";
10038
+ TempEntity22[TempEntity22["PLAIN_EXPLOSION"] = 35] = "PLAIN_EXPLOSION";
10039
+ TempEntity22[TempEntity22["FLASHLIGHT"] = 36] = "FLASHLIGHT";
10040
+ TempEntity22[TempEntity22["FORCEWALL"] = 37] = "FORCEWALL";
10041
+ TempEntity22[TempEntity22["HEATBEAM"] = 38] = "HEATBEAM";
10042
+ TempEntity22[TempEntity22["MONSTER_HEATBEAM"] = 39] = "MONSTER_HEATBEAM";
10043
+ TempEntity22[TempEntity22["STEAM"] = 40] = "STEAM";
10044
+ TempEntity22[TempEntity22["BUBBLETRAIL2"] = 41] = "BUBBLETRAIL2";
10045
+ TempEntity22[TempEntity22["MOREBLOOD"] = 42] = "MOREBLOOD";
10046
+ TempEntity22[TempEntity22["HEATBEAM_SPARKS"] = 43] = "HEATBEAM_SPARKS";
10047
+ TempEntity22[TempEntity22["HEATBEAM_STEAM"] = 44] = "HEATBEAM_STEAM";
10048
+ TempEntity22[TempEntity22["CHAINFIST_SMOKE"] = 45] = "CHAINFIST_SMOKE";
10049
+ TempEntity22[TempEntity22["ELECTRIC_SPARKS"] = 46] = "ELECTRIC_SPARKS";
10050
+ TempEntity22[TempEntity22["TRACKER_EXPLOSION"] = 47] = "TRACKER_EXPLOSION";
10051
+ TempEntity22[TempEntity22["TELEPORT_EFFECT"] = 48] = "TELEPORT_EFFECT";
10052
+ TempEntity22[TempEntity22["DBALL_GOAL"] = 49] = "DBALL_GOAL";
10053
+ TempEntity22[TempEntity22["WIDOWBEAMOUT"] = 50] = "WIDOWBEAMOUT";
10054
+ TempEntity22[TempEntity22["NUKEBLAST"] = 51] = "NUKEBLAST";
10055
+ TempEntity22[TempEntity22["WIDOWSPLASH"] = 52] = "WIDOWSPLASH";
10056
+ TempEntity22[TempEntity22["EXPLOSION1_BIG"] = 53] = "EXPLOSION1_BIG";
10057
+ TempEntity22[TempEntity22["EXPLOSION1_NP"] = 54] = "EXPLOSION1_NP";
10058
+ TempEntity22[TempEntity22["FLECHETTE"] = 55] = "FLECHETTE";
10059
+ TempEntity22[TempEntity22["BLUEHYPERBLASTER_KEX"] = 56] = "BLUEHYPERBLASTER_KEX";
10060
+ TempEntity22[TempEntity22["BFG_ZAP"] = 57] = "BFG_ZAP";
10061
+ TempEntity22[TempEntity22["BERSERK_SLAM"] = 58] = "BERSERK_SLAM";
10062
+ TempEntity22[TempEntity22["GRAPPLE_CABLE_2"] = 59] = "GRAPPLE_CABLE_2";
10063
+ TempEntity22[TempEntity22["POWER_SPLASH"] = 60] = "POWER_SPLASH";
10064
+ TempEntity22[TempEntity22["LIGHTNING_BEAM"] = 61] = "LIGHTNING_BEAM";
10065
+ TempEntity22[TempEntity22["EXPLOSION1_NL"] = 62] = "EXPLOSION1_NL";
10066
+ TempEntity22[TempEntity22["EXPLOSION2_NL"] = 63] = "EXPLOSION2_NL";
10067
+ return TempEntity22;
10068
+ })(TempEntity2 || {});
9898
10069
  var CMD_BACKUP = 64;
9899
10070
  var MZ_BLASTER = 0;
9900
10071
  var MZ_MACHINEGUN = 1;
@@ -9908,6 +10079,7 @@ var MZ_GRENADE = 8;
9908
10079
  var MZ_SSHOTGUN = 11;
9909
10080
  var MZ_BFG = 12;
9910
10081
  var MZ_HYPERBLASTER = 13;
10082
+ var MZ_BLUEHYPERBLASTER = 17;
9911
10083
  function readUint16LE(stats, startIndex, byteOffset) {
9912
10084
  const elementIndex = Math.floor(byteOffset / 2);
9913
10085
  const isOdd = byteOffset % 2 !== 0;
@@ -11654,6 +11826,9 @@ var ClientNetworkHandler = class {
11654
11826
  }
11655
11827
  }
11656
11828
  onTempEntity(type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt) {
11829
+ if (this.callbacks?.onTempEntity) {
11830
+ this.callbacks.onTempEntity(type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt);
11831
+ }
11657
11832
  }
11658
11833
  onLayout(layout) {
11659
11834
  }
@@ -11661,8 +11836,14 @@ var ClientNetworkHandler = class {
11661
11836
  this.inventory = [...inventory];
11662
11837
  }
11663
11838
  onMuzzleFlash(ent, weapon) {
11839
+ if (this.callbacks?.onMuzzleFlash) {
11840
+ this.callbacks.onMuzzleFlash(ent, weapon);
11841
+ }
11664
11842
  }
11665
11843
  onMuzzleFlash2(ent, weapon) {
11844
+ if (this.callbacks?.onMuzzleFlash2) {
11845
+ this.callbacks.onMuzzleFlash2(ent, weapon);
11846
+ }
11666
11847
  }
11667
11848
  onMuzzleFlash3(ent, weapon) {
11668
11849
  const isLocalPlayer = ent === this.playerNum + 1;
@@ -13170,6 +13351,7 @@ var MultiplayerConnection = class {
13170
13351
  this.levelName = "";
13171
13352
  this.configStrings = /* @__PURE__ */ new Map();
13172
13353
  this.baselines = /* @__PURE__ */ new Map();
13354
+ this.entities = /* @__PURE__ */ new Map();
13173
13355
  this.challenge = 0;
13174
13356
  this.connectPacketCount = 0;
13175
13357
  this.connectPacketTime = 0;
@@ -13200,6 +13382,9 @@ var MultiplayerConnection = class {
13200
13382
  setDemoRecorder(recorder) {
13201
13383
  this.demoRecorder = recorder;
13202
13384
  }
13385
+ setEffectSystem(system) {
13386
+ this.effectSystem = system;
13387
+ }
13203
13388
  async connectToServer(address, port) {
13204
13389
  const url = `ws://${address}:${port}`;
13205
13390
  return this.connect(url);
@@ -13235,6 +13420,7 @@ var MultiplayerConnection = class {
13235
13420
  cleanup() {
13236
13421
  this.configStrings.clear();
13237
13422
  this.baselines.clear();
13423
+ this.entities.clear();
13238
13424
  this.commandHistory = [];
13239
13425
  this.latestServerFrame = 0;
13240
13426
  this.parser = null;
@@ -13369,6 +13555,13 @@ var MultiplayerConnection = class {
13369
13555
  if (frame.serverFrame > this.latestServerFrame) {
13370
13556
  this.latestServerFrame = frame.serverFrame;
13371
13557
  }
13558
+ const packetEntities = frame.packetEntities;
13559
+ if (!packetEntities.delta) {
13560
+ this.entities.clear();
13561
+ }
13562
+ for (const ent of packetEntities.entities) {
13563
+ this.entities.set(ent.number, ent);
13564
+ }
13372
13565
  if (this.prediction && frame.playerState) {
13373
13566
  const ps = frame.playerState;
13374
13567
  const predState = {
@@ -13397,15 +13590,29 @@ var MultiplayerConnection = class {
13397
13590
  onSound(flags, soundNum, volume, attenuation, offset, ent, pos) {
13398
13591
  }
13399
13592
  onTempEntity(type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt) {
13593
+ if (this.effectSystem) {
13594
+ const time = Date.now() / 1e3;
13595
+ this.effectSystem.onTempEntity(type, pos, time);
13596
+ }
13400
13597
  }
13401
13598
  onLayout(layout) {
13402
13599
  }
13403
13600
  onInventory(inventory) {
13404
13601
  }
13405
13602
  onMuzzleFlash(ent, weapon) {
13603
+ if (this.effectSystem) {
13604
+ const time = Date.now() / 1e3;
13605
+ this.effectSystem.onMuzzleFlash(ent, weapon, time);
13606
+ }
13406
13607
  }
13407
13608
  onMuzzleFlash2(ent, weapon) {
13408
13609
  }
13610
+ onMuzzleFlash3(ent, weapon) {
13611
+ if (this.effectSystem) {
13612
+ const time = Date.now() / 1e3;
13613
+ this.effectSystem.onMuzzleFlash(ent, weapon, time);
13614
+ }
13615
+ }
13409
13616
  onDisconnect() {
13410
13617
  this.disconnect();
13411
13618
  }
@@ -13413,6 +13620,31 @@ var MultiplayerConnection = class {
13413
13620
  }
13414
13621
  onDownload(size, percent, data) {
13415
13622
  }
13623
+ // New handlers stubs
13624
+ onSplitClient(clientNum) {
13625
+ }
13626
+ onConfigBlast(index, data) {
13627
+ }
13628
+ onSpawnBaselineBlast(entity) {
13629
+ }
13630
+ onLevelRestart() {
13631
+ }
13632
+ onDamage(indicators) {
13633
+ }
13634
+ onLocPrint(flags, base, args) {
13635
+ }
13636
+ onFog(data) {
13637
+ }
13638
+ onWaitingForPlayers(count) {
13639
+ }
13640
+ onBotChat(msg) {
13641
+ }
13642
+ onPoi(flags, pos) {
13643
+ }
13644
+ onHelpPath(pos) {
13645
+ }
13646
+ onAchievement(id) {
13647
+ }
13416
13648
  };
13417
13649
 
13418
13650
  // src/ui/demo-controls.ts
@@ -13560,6 +13792,152 @@ function processEntityEffects(entity, dlights, time) {
13560
13792
  }
13561
13793
  }
13562
13794
 
13795
+ // src/effects-system.ts
13796
+ var copyVec3 = (v) => ({ x: v.x, y: v.y, z: v.z });
13797
+ var vectorMA = (start, scale3, dir) => ({
13798
+ x: start.x + dir.x * scale3,
13799
+ y: start.y + dir.y * scale3,
13800
+ z: start.z + dir.z * scale3
13801
+ });
13802
+ var ClientEffectSystem = class {
13803
+ constructor(dlightManager, engine, entityProvider) {
13804
+ this.dlightManager = dlightManager;
13805
+ this.engine = engine;
13806
+ this.entityProvider = entityProvider;
13807
+ }
13808
+ // Helper to add dlight
13809
+ addLight(key, origin, color, radius, minLight, time) {
13810
+ this.dlightManager.addLight({
13811
+ key,
13812
+ origin: copyVec3(origin),
13813
+ color,
13814
+ intensity: radius,
13815
+ minLight,
13816
+ die: time
13817
+ }, 0);
13818
+ }
13819
+ playSound(pos, ent, soundName, vol = 1, attn = 1) {
13820
+ if (!this.engine.audio) return;
13821
+ const index = this.engine.audio.soundindex(soundName);
13822
+ if (index === 0) return;
13823
+ if (pos) {
13824
+ this.engine.audio.positioned_sound(pos, index, vol, attn);
13825
+ } else {
13826
+ this.engine.audio.sound(ent, 0, index, vol, attn, 0);
13827
+ }
13828
+ }
13829
+ onMuzzleFlash(entNum, weapon, time) {
13830
+ const ent = this.entityProvider.getEntity(entNum);
13831
+ if (!ent) return;
13832
+ const origin = { x: ent.origin.x, y: ent.origin.y, z: ent.origin.z };
13833
+ const angles = { x: ent.angles.x, y: ent.angles.y, z: ent.angles.z };
13834
+ const vectors = angleVectors(angles);
13835
+ let flashOrigin = vectorMA(origin, 18, vectors.forward);
13836
+ flashOrigin = vectorMA(flashOrigin, 16, vectors.right);
13837
+ const silenced = (weapon & 128) !== 0;
13838
+ weapon &= ~128;
13839
+ let radius = silenced ? 100 + Math.random() * 31 : 200 + Math.random() * 31;
13840
+ const minLight = 32;
13841
+ const duration = 0.1;
13842
+ const die = time + duration;
13843
+ const volume = silenced ? 0.2 : 1;
13844
+ let color = { x: 1, y: 1, z: 0 };
13845
+ switch (weapon) {
13846
+ case MZ_BLASTER:
13847
+ case MZ_HYPERBLASTER:
13848
+ case MZ_MACHINEGUN:
13849
+ case MZ_SHOTGUN:
13850
+ case MZ_SSHOTGUN:
13851
+ case MZ_CHAINGUN1:
13852
+ case MZ_CHAINGUN2:
13853
+ case MZ_CHAINGUN3:
13854
+ color = { x: 1, y: 1, z: 0 };
13855
+ break;
13856
+ case MZ_BLUEHYPERBLASTER:
13857
+ color = { x: 0, y: 0, z: 1 };
13858
+ break;
13859
+ case MZ_RAILGUN:
13860
+ color = { x: 0.5, y: 0.5, z: 1 };
13861
+ break;
13862
+ case MZ_ROCKET:
13863
+ case MZ_GRENADE:
13864
+ color = { x: 1, y: 0.5, z: 0.2 };
13865
+ break;
13866
+ case MZ_BFG:
13867
+ color = { x: 0, y: 1, z: 0 };
13868
+ break;
13869
+ }
13870
+ this.addLight(entNum, flashOrigin, color, radius, minLight, die);
13871
+ let soundName = "";
13872
+ switch (weapon) {
13873
+ case MZ_BLASTER:
13874
+ soundName = "weapons/blastf1a.wav";
13875
+ break;
13876
+ case MZ_SHOTGUN:
13877
+ soundName = "weapons/shotgf1b.wav";
13878
+ break;
13879
+ case MZ_SSHOTGUN:
13880
+ soundName = "weapons/sshotf1b.wav";
13881
+ break;
13882
+ case MZ_MACHINEGUN:
13883
+ soundName = `weapons/machgf${Math.floor(Math.random() * 5) + 1}b.wav`;
13884
+ break;
13885
+ case MZ_RAILGUN:
13886
+ soundName = "weapons/railgf1a.wav";
13887
+ break;
13888
+ case MZ_ROCKET:
13889
+ soundName = "weapons/rocklf1a.wav";
13890
+ break;
13891
+ case MZ_GRENADE:
13892
+ soundName = "weapons/grenlf1a.wav";
13893
+ break;
13894
+ case MZ_BFG:
13895
+ soundName = "weapons/bfg__f1y.wav";
13896
+ break;
13897
+ case MZ_HYPERBLASTER:
13898
+ soundName = "weapons/hyprbf1a.wav";
13899
+ break;
13900
+ case MZ_BLUEHYPERBLASTER:
13901
+ soundName = "weapons/hyprbf1a.wav";
13902
+ break;
13903
+ case MZ_CHAINGUN1:
13904
+ case MZ_CHAINGUN2:
13905
+ case MZ_CHAINGUN3:
13906
+ soundName = `weapons/machgf${Math.floor(Math.random() * 5) + 1}b.wav`;
13907
+ break;
13908
+ }
13909
+ if (soundName) {
13910
+ this.playSound(null, entNum, soundName, volume, 1);
13911
+ }
13912
+ }
13913
+ onTempEntity(type, pos, time) {
13914
+ switch (type) {
13915
+ case TempEntity2.EXPLOSION1:
13916
+ case TempEntity2.EXPLOSION1_BIG:
13917
+ case TempEntity2.EXPLOSION1_NP:
13918
+ case TempEntity2.ROCKET_EXPLOSION:
13919
+ case TempEntity2.GRENADE_EXPLOSION:
13920
+ case TempEntity2.ROCKET_EXPLOSION_WATER:
13921
+ case TempEntity2.GRENADE_EXPLOSION_WATER:
13922
+ {
13923
+ const color = { x: 1, y: 0.5, z: 0.2 };
13924
+ const duration = 0.5;
13925
+ this.addLight(void 0, pos, color, 300, 0, time + duration);
13926
+ this.playSound(pos, 0, "weapons/rocklx1a.wav", 1, 0.5);
13927
+ }
13928
+ break;
13929
+ case TempEntity2.BFG_EXPLOSION:
13930
+ case TempEntity2.BFG_BIGEXPLOSION:
13931
+ {
13932
+ const color = { x: 0, y: 1, z: 0 };
13933
+ this.addLight(void 0, pos, color, 300, 0, time + 0.5);
13934
+ this.playSound(pos, 0, "weapons/bfg__x1b.wav", 1, 0.5);
13935
+ }
13936
+ break;
13937
+ }
13938
+ }
13939
+ };
13940
+
13563
13941
  // src/input/bindings.ts
13564
13942
  var DEFAULT_BINDINGS = [
13565
13943
  { code: "KeyW", command: "+forward" },
@@ -14221,6 +14599,23 @@ function createClient(imports) {
14221
14599
  const demoHandler = new ClientNetworkHandler(imports);
14222
14600
  const demoRecorder = new DemoRecorder();
14223
14601
  demoHandler.setView(view);
14602
+ const dlightManager = new DynamicLightManager();
14603
+ const entityProvider = {
14604
+ getEntity(entNum) {
14605
+ if (isDemoPlaying) {
14606
+ return demoHandler.entities.get(entNum);
14607
+ } else {
14608
+ if (multiplayer.isConnected()) {
14609
+ return multiplayer.entities.get(entNum);
14610
+ }
14611
+ }
14612
+ return void 0;
14613
+ },
14614
+ getPlayerNum() {
14615
+ return multiplayer.playerNum;
14616
+ }
14617
+ };
14618
+ const effectSystem = new ClientEffectSystem(dlightManager, imports.engine, entityProvider);
14224
14619
  let isDemoPlaying = false;
14225
14620
  let currentDemoName = null;
14226
14621
  let clientMode = 0 /* Normal */;
@@ -14283,6 +14678,7 @@ function createClient(imports) {
14283
14678
  }
14284
14679
  });
14285
14680
  multiplayer.setDemoRecorder(demoRecorder);
14681
+ multiplayer.setEffectSystem(effectSystem);
14286
14682
  const multiplayerFactory = new MultiplayerMenuFactory(menuSystem, multiplayer);
14287
14683
  demoHandler.setCallbacks({
14288
14684
  onCenterPrint: (msg) => cg.ParseCenterPrint(msg, 0, false),
@@ -14297,6 +14693,19 @@ function createClient(imports) {
14297
14693
  } else {
14298
14694
  demoPlayback.setFrameDuration(100);
14299
14695
  }
14696
+ },
14697
+ // New hooks for effects
14698
+ onMuzzleFlash: (ent, weapon) => {
14699
+ const time = demoPlayback.getCurrentTime() / 1e3;
14700
+ effectSystem.onMuzzleFlash(ent, weapon, time);
14701
+ },
14702
+ onMuzzleFlash2: (ent, weapon) => {
14703
+ },
14704
+ onTempEntity: (type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt) => {
14705
+ const time = demoPlayback.getCurrentTime() / 1e3;
14706
+ if (pos) {
14707
+ effectSystem.onTempEntity(type, pos, time);
14708
+ }
14300
14709
  }
14301
14710
  });
14302
14711
  demoPlayback.setHandler(demoHandler);
@@ -14410,6 +14819,7 @@ function createClient(imports) {
14410
14819
  const clientExports = {
14411
14820
  loadingScreen,
14412
14821
  errorDialog,
14822
+ dlightManager,
14413
14823
  init(initial) {
14414
14824
  this.Init(initial);
14415
14825
  },
@@ -14608,8 +15018,9 @@ function createClient(imports) {
14608
15018
  const frameTimeMs = sample.latest && sample.previous ? Math.max(0, sample.latest.timeMs - sample.previous.timeMs) : 0;
14609
15019
  lastView = view.sample(lastRendered, frameTimeMs);
14610
15020
  const command = {};
14611
- const dlights = [];
14612
15021
  const timeSeconds = sample.nowMs / 1e3;
15022
+ dlightManager.update(timeSeconds);
15023
+ const dlights = [...dlightManager.getActiveLights()];
14613
15024
  for (const ent of currentPacketEntities) {
14614
15025
  processEntityEffects(ent, dlights, timeSeconds);
14615
15026
  }