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
@@ -1915,6 +1915,7 @@ var DEG_TO_RAD = Math.PI / 180;
1915
1915
  var DEG2RAD_FACTOR = Math.PI / 180;
1916
1916
  var RAD2DEG_FACTOR = 180 / Math.PI;
1917
1917
  var DEG2RAD = DEG2RAD_FACTOR;
1918
+ var RAD2DEG = RAD2DEG_FACTOR;
1918
1919
  var ANORMS = [
1919
1920
  [-0.525731, 0, 0.850651],
1920
1921
  [-0.442863, 0.238856, 0.864188],
@@ -2255,72 +2256,72 @@ var ServerCommand = /* @__PURE__ */ ((ServerCommand22) => {
2255
2256
  ServerCommand22[ServerCommand22["achievement"] = 33] = "achievement";
2256
2257
  return ServerCommand22;
2257
2258
  })(ServerCommand || {});
2258
- var TempEntity = /* @__PURE__ */ ((TempEntity2) => {
2259
- TempEntity2[TempEntity2["GUNSHOT"] = 0] = "GUNSHOT";
2260
- TempEntity2[TempEntity2["BLOOD"] = 1] = "BLOOD";
2261
- TempEntity2[TempEntity2["BLASTER"] = 2] = "BLASTER";
2262
- TempEntity2[TempEntity2["RAILTRAIL"] = 3] = "RAILTRAIL";
2263
- TempEntity2[TempEntity2["SHOTGUN"] = 4] = "SHOTGUN";
2264
- TempEntity2[TempEntity2["EXPLOSION1"] = 5] = "EXPLOSION1";
2265
- TempEntity2[TempEntity2["EXPLOSION2"] = 6] = "EXPLOSION2";
2266
- TempEntity2[TempEntity2["ROCKET_EXPLOSION"] = 7] = "ROCKET_EXPLOSION";
2267
- TempEntity2[TempEntity2["GRENADE_EXPLOSION"] = 8] = "GRENADE_EXPLOSION";
2268
- TempEntity2[TempEntity2["SPARKS"] = 9] = "SPARKS";
2269
- TempEntity2[TempEntity2["SPLASH"] = 10] = "SPLASH";
2270
- TempEntity2[TempEntity2["BUBBLETRAIL"] = 11] = "BUBBLETRAIL";
2271
- TempEntity2[TempEntity2["SCREEN_SPARKS"] = 12] = "SCREEN_SPARKS";
2272
- TempEntity2[TempEntity2["SHIELD_SPARKS"] = 13] = "SHIELD_SPARKS";
2273
- TempEntity2[TempEntity2["BULLET_SPARKS"] = 14] = "BULLET_SPARKS";
2274
- TempEntity2[TempEntity2["LASER_SPARKS"] = 15] = "LASER_SPARKS";
2275
- TempEntity2[TempEntity2["PARASITE_ATTACK"] = 16] = "PARASITE_ATTACK";
2276
- TempEntity2[TempEntity2["ROCKET_EXPLOSION_WATER"] = 17] = "ROCKET_EXPLOSION_WATER";
2277
- TempEntity2[TempEntity2["GRENADE_EXPLOSION_WATER"] = 18] = "GRENADE_EXPLOSION_WATER";
2278
- TempEntity2[TempEntity2["MEDIC_CABLE_ATTACK"] = 19] = "MEDIC_CABLE_ATTACK";
2279
- TempEntity2[TempEntity2["BFG_EXPLOSION"] = 20] = "BFG_EXPLOSION";
2280
- TempEntity2[TempEntity2["BFG_BIGEXPLOSION"] = 21] = "BFG_BIGEXPLOSION";
2281
- TempEntity2[TempEntity2["BOSSTPORT"] = 22] = "BOSSTPORT";
2282
- TempEntity2[TempEntity2["BFG_LASER"] = 23] = "BFG_LASER";
2283
- TempEntity2[TempEntity2["GRAPPLE_CABLE"] = 24] = "GRAPPLE_CABLE";
2284
- TempEntity2[TempEntity2["WELDING_SPARKS"] = 25] = "WELDING_SPARKS";
2285
- TempEntity2[TempEntity2["GREENBLOOD"] = 26] = "GREENBLOOD";
2286
- TempEntity2[TempEntity2["BLUEHYPERBLASTER"] = 27] = "BLUEHYPERBLASTER";
2287
- TempEntity2[TempEntity2["PLASMA_EXPLOSION"] = 28] = "PLASMA_EXPLOSION";
2288
- TempEntity2[TempEntity2["TUNNEL_SPARKS"] = 29] = "TUNNEL_SPARKS";
2289
- TempEntity2[TempEntity2["BLASTER2"] = 30] = "BLASTER2";
2290
- TempEntity2[TempEntity2["RAILTRAIL2"] = 31] = "RAILTRAIL2";
2291
- TempEntity2[TempEntity2["FLAME"] = 32] = "FLAME";
2292
- TempEntity2[TempEntity2["LIGHTNING"] = 33] = "LIGHTNING";
2293
- TempEntity2[TempEntity2["DEBUGTRAIL"] = 34] = "DEBUGTRAIL";
2294
- TempEntity2[TempEntity2["PLAIN_EXPLOSION"] = 35] = "PLAIN_EXPLOSION";
2295
- TempEntity2[TempEntity2["FLASHLIGHT"] = 36] = "FLASHLIGHT";
2296
- TempEntity2[TempEntity2["FORCEWALL"] = 37] = "FORCEWALL";
2297
- TempEntity2[TempEntity2["HEATBEAM"] = 38] = "HEATBEAM";
2298
- TempEntity2[TempEntity2["MONSTER_HEATBEAM"] = 39] = "MONSTER_HEATBEAM";
2299
- TempEntity2[TempEntity2["STEAM"] = 40] = "STEAM";
2300
- TempEntity2[TempEntity2["BUBBLETRAIL2"] = 41] = "BUBBLETRAIL2";
2301
- TempEntity2[TempEntity2["MOREBLOOD"] = 42] = "MOREBLOOD";
2302
- TempEntity2[TempEntity2["HEATBEAM_SPARKS"] = 43] = "HEATBEAM_SPARKS";
2303
- TempEntity2[TempEntity2["HEATBEAM_STEAM"] = 44] = "HEATBEAM_STEAM";
2304
- TempEntity2[TempEntity2["CHAINFIST_SMOKE"] = 45] = "CHAINFIST_SMOKE";
2305
- TempEntity2[TempEntity2["ELECTRIC_SPARKS"] = 46] = "ELECTRIC_SPARKS";
2306
- TempEntity2[TempEntity2["TRACKER_EXPLOSION"] = 47] = "TRACKER_EXPLOSION";
2307
- TempEntity2[TempEntity2["TELEPORT_EFFECT"] = 48] = "TELEPORT_EFFECT";
2308
- TempEntity2[TempEntity2["DBALL_GOAL"] = 49] = "DBALL_GOAL";
2309
- TempEntity2[TempEntity2["WIDOWBEAMOUT"] = 50] = "WIDOWBEAMOUT";
2310
- TempEntity2[TempEntity2["NUKEBLAST"] = 51] = "NUKEBLAST";
2311
- TempEntity2[TempEntity2["WIDOWSPLASH"] = 52] = "WIDOWSPLASH";
2312
- TempEntity2[TempEntity2["EXPLOSION1_BIG"] = 53] = "EXPLOSION1_BIG";
2313
- TempEntity2[TempEntity2["EXPLOSION1_NP"] = 54] = "EXPLOSION1_NP";
2314
- TempEntity2[TempEntity2["FLECHETTE"] = 55] = "FLECHETTE";
2315
- TempEntity2[TempEntity2["BLUEHYPERBLASTER_KEX"] = 56] = "BLUEHYPERBLASTER_KEX";
2316
- TempEntity2[TempEntity2["BFG_ZAP"] = 57] = "BFG_ZAP";
2317
- TempEntity2[TempEntity2["BERSERK_SLAM"] = 58] = "BERSERK_SLAM";
2318
- TempEntity2[TempEntity2["GRAPPLE_CABLE_2"] = 59] = "GRAPPLE_CABLE_2";
2319
- TempEntity2[TempEntity2["POWER_SPLASH"] = 60] = "POWER_SPLASH";
2320
- TempEntity2[TempEntity2["LIGHTNING_BEAM"] = 61] = "LIGHTNING_BEAM";
2321
- TempEntity2[TempEntity2["EXPLOSION1_NL"] = 62] = "EXPLOSION1_NL";
2322
- TempEntity2[TempEntity2["EXPLOSION2_NL"] = 63] = "EXPLOSION2_NL";
2323
- return TempEntity2;
2259
+ var TempEntity = /* @__PURE__ */ ((TempEntity22) => {
2260
+ TempEntity22[TempEntity22["GUNSHOT"] = 0] = "GUNSHOT";
2261
+ TempEntity22[TempEntity22["BLOOD"] = 1] = "BLOOD";
2262
+ TempEntity22[TempEntity22["BLASTER"] = 2] = "BLASTER";
2263
+ TempEntity22[TempEntity22["RAILTRAIL"] = 3] = "RAILTRAIL";
2264
+ TempEntity22[TempEntity22["SHOTGUN"] = 4] = "SHOTGUN";
2265
+ TempEntity22[TempEntity22["EXPLOSION1"] = 5] = "EXPLOSION1";
2266
+ TempEntity22[TempEntity22["EXPLOSION2"] = 6] = "EXPLOSION2";
2267
+ TempEntity22[TempEntity22["ROCKET_EXPLOSION"] = 7] = "ROCKET_EXPLOSION";
2268
+ TempEntity22[TempEntity22["GRENADE_EXPLOSION"] = 8] = "GRENADE_EXPLOSION";
2269
+ TempEntity22[TempEntity22["SPARKS"] = 9] = "SPARKS";
2270
+ TempEntity22[TempEntity22["SPLASH"] = 10] = "SPLASH";
2271
+ TempEntity22[TempEntity22["BUBBLETRAIL"] = 11] = "BUBBLETRAIL";
2272
+ TempEntity22[TempEntity22["SCREEN_SPARKS"] = 12] = "SCREEN_SPARKS";
2273
+ TempEntity22[TempEntity22["SHIELD_SPARKS"] = 13] = "SHIELD_SPARKS";
2274
+ TempEntity22[TempEntity22["BULLET_SPARKS"] = 14] = "BULLET_SPARKS";
2275
+ TempEntity22[TempEntity22["LASER_SPARKS"] = 15] = "LASER_SPARKS";
2276
+ TempEntity22[TempEntity22["PARASITE_ATTACK"] = 16] = "PARASITE_ATTACK";
2277
+ TempEntity22[TempEntity22["ROCKET_EXPLOSION_WATER"] = 17] = "ROCKET_EXPLOSION_WATER";
2278
+ TempEntity22[TempEntity22["GRENADE_EXPLOSION_WATER"] = 18] = "GRENADE_EXPLOSION_WATER";
2279
+ TempEntity22[TempEntity22["MEDIC_CABLE_ATTACK"] = 19] = "MEDIC_CABLE_ATTACK";
2280
+ TempEntity22[TempEntity22["BFG_EXPLOSION"] = 20] = "BFG_EXPLOSION";
2281
+ TempEntity22[TempEntity22["BFG_BIGEXPLOSION"] = 21] = "BFG_BIGEXPLOSION";
2282
+ TempEntity22[TempEntity22["BOSSTPORT"] = 22] = "BOSSTPORT";
2283
+ TempEntity22[TempEntity22["BFG_LASER"] = 23] = "BFG_LASER";
2284
+ TempEntity22[TempEntity22["GRAPPLE_CABLE"] = 24] = "GRAPPLE_CABLE";
2285
+ TempEntity22[TempEntity22["WELDING_SPARKS"] = 25] = "WELDING_SPARKS";
2286
+ TempEntity22[TempEntity22["GREENBLOOD"] = 26] = "GREENBLOOD";
2287
+ TempEntity22[TempEntity22["BLUEHYPERBLASTER"] = 27] = "BLUEHYPERBLASTER";
2288
+ TempEntity22[TempEntity22["PLASMA_EXPLOSION"] = 28] = "PLASMA_EXPLOSION";
2289
+ TempEntity22[TempEntity22["TUNNEL_SPARKS"] = 29] = "TUNNEL_SPARKS";
2290
+ TempEntity22[TempEntity22["BLASTER2"] = 30] = "BLASTER2";
2291
+ TempEntity22[TempEntity22["RAILTRAIL2"] = 31] = "RAILTRAIL2";
2292
+ TempEntity22[TempEntity22["FLAME"] = 32] = "FLAME";
2293
+ TempEntity22[TempEntity22["LIGHTNING"] = 33] = "LIGHTNING";
2294
+ TempEntity22[TempEntity22["DEBUGTRAIL"] = 34] = "DEBUGTRAIL";
2295
+ TempEntity22[TempEntity22["PLAIN_EXPLOSION"] = 35] = "PLAIN_EXPLOSION";
2296
+ TempEntity22[TempEntity22["FLASHLIGHT"] = 36] = "FLASHLIGHT";
2297
+ TempEntity22[TempEntity22["FORCEWALL"] = 37] = "FORCEWALL";
2298
+ TempEntity22[TempEntity22["HEATBEAM"] = 38] = "HEATBEAM";
2299
+ TempEntity22[TempEntity22["MONSTER_HEATBEAM"] = 39] = "MONSTER_HEATBEAM";
2300
+ TempEntity22[TempEntity22["STEAM"] = 40] = "STEAM";
2301
+ TempEntity22[TempEntity22["BUBBLETRAIL2"] = 41] = "BUBBLETRAIL2";
2302
+ TempEntity22[TempEntity22["MOREBLOOD"] = 42] = "MOREBLOOD";
2303
+ TempEntity22[TempEntity22["HEATBEAM_SPARKS"] = 43] = "HEATBEAM_SPARKS";
2304
+ TempEntity22[TempEntity22["HEATBEAM_STEAM"] = 44] = "HEATBEAM_STEAM";
2305
+ TempEntity22[TempEntity22["CHAINFIST_SMOKE"] = 45] = "CHAINFIST_SMOKE";
2306
+ TempEntity22[TempEntity22["ELECTRIC_SPARKS"] = 46] = "ELECTRIC_SPARKS";
2307
+ TempEntity22[TempEntity22["TRACKER_EXPLOSION"] = 47] = "TRACKER_EXPLOSION";
2308
+ TempEntity22[TempEntity22["TELEPORT_EFFECT"] = 48] = "TELEPORT_EFFECT";
2309
+ TempEntity22[TempEntity22["DBALL_GOAL"] = 49] = "DBALL_GOAL";
2310
+ TempEntity22[TempEntity22["WIDOWBEAMOUT"] = 50] = "WIDOWBEAMOUT";
2311
+ TempEntity22[TempEntity22["NUKEBLAST"] = 51] = "NUKEBLAST";
2312
+ TempEntity22[TempEntity22["WIDOWSPLASH"] = 52] = "WIDOWSPLASH";
2313
+ TempEntity22[TempEntity22["EXPLOSION1_BIG"] = 53] = "EXPLOSION1_BIG";
2314
+ TempEntity22[TempEntity22["EXPLOSION1_NP"] = 54] = "EXPLOSION1_NP";
2315
+ TempEntity22[TempEntity22["FLECHETTE"] = 55] = "FLECHETTE";
2316
+ TempEntity22[TempEntity22["BLUEHYPERBLASTER_KEX"] = 56] = "BLUEHYPERBLASTER_KEX";
2317
+ TempEntity22[TempEntity22["BFG_ZAP"] = 57] = "BFG_ZAP";
2318
+ TempEntity22[TempEntity22["BERSERK_SLAM"] = 58] = "BERSERK_SLAM";
2319
+ TempEntity22[TempEntity22["GRAPPLE_CABLE_2"] = 59] = "GRAPPLE_CABLE_2";
2320
+ TempEntity22[TempEntity22["POWER_SPLASH"] = 60] = "POWER_SPLASH";
2321
+ TempEntity22[TempEntity22["LIGHTNING_BEAM"] = 61] = "LIGHTNING_BEAM";
2322
+ TempEntity22[TempEntity22["EXPLOSION1_NL"] = 62] = "EXPLOSION1_NL";
2323
+ TempEntity22[TempEntity22["EXPLOSION2_NL"] = 63] = "EXPLOSION2_NL";
2324
+ return TempEntity22;
2324
2325
  })(TempEntity || {});
2325
2326
  var AMMO_MAX = 12;
2326
2327
  var NUM_BITS_FOR_AMMO = 9;
@@ -3131,6 +3132,43 @@ var BSP_VERTEX_LAYOUT = [
3131
3132
  { index: 2, size: 2, type: 5126, stride: STRIDE, offset: 5 * FLOAT_BYTES }
3132
3133
  ];
3133
3134
  var MAX_DLIGHTS = 32;
3135
+ var DynamicLightManager = class {
3136
+ constructor() {
3137
+ this.lights = [];
3138
+ }
3139
+ /**
3140
+ * Adds a dynamic light or updates an existing one with the same key.
3141
+ */
3142
+ addLight(dlight, time) {
3143
+ if (dlight.key !== void 0) {
3144
+ const index = this.lights.findIndex((l) => l.key === dlight.key);
3145
+ if (index !== -1) {
3146
+ this.lights[index] = dlight;
3147
+ return;
3148
+ }
3149
+ }
3150
+ this.lights.push(dlight);
3151
+ }
3152
+ /**
3153
+ * Clears all lights (e.g., map change).
3154
+ */
3155
+ clear() {
3156
+ this.lights = [];
3157
+ }
3158
+ /**
3159
+ * Updates the list of active lights, removing expired ones.
3160
+ * @param time Current game time in seconds.
3161
+ */
3162
+ update(time) {
3163
+ this.lights = this.lights.filter((l) => l.die > time);
3164
+ }
3165
+ /**
3166
+ * Returns the current list of active lights.
3167
+ */
3168
+ getActiveLights() {
3169
+ return this.lights;
3170
+ }
3171
+ };
3134
3172
  var BSP_SURFACE_FRAGMENT_SOURCE = `#version 300 es
3135
3173
  precision highp float;
3136
3174
 
@@ -3438,15 +3476,21 @@ var Camera = class {
3438
3476
  return this._position;
3439
3477
  }
3440
3478
  set position(value) {
3441
- vec3_exports.copy(this._position, value);
3442
- this._dirty = true;
3479
+ if (!vec3_exports.equals(this._position, value)) {
3480
+ vec3_exports.copy(this._position, value);
3481
+ this._dirty = true;
3482
+ this.triggerMoveEvent();
3483
+ }
3443
3484
  }
3444
3485
  get angles() {
3445
3486
  return this._angles;
3446
3487
  }
3447
3488
  set angles(value) {
3448
- vec3_exports.copy(this._angles, value);
3449
- this._dirty = true;
3489
+ if (!vec3_exports.equals(this._angles, value)) {
3490
+ vec3_exports.copy(this._angles, value);
3491
+ this._dirty = true;
3492
+ this.triggerMoveEvent();
3493
+ }
3450
3494
  }
3451
3495
  get bobAngles() {
3452
3496
  return this._bobAngles;
@@ -3490,6 +3534,47 @@ var Camera = class {
3490
3534
  this._aspect = value;
3491
3535
  this._dirty = true;
3492
3536
  }
3537
+ // API Methods
3538
+ setPosition(x, y, z) {
3539
+ const newPos = vec3_exports.fromValues(x, y, z);
3540
+ if (!vec3_exports.equals(this._position, newPos)) {
3541
+ vec3_exports.copy(this._position, newPos);
3542
+ this._dirty = true;
3543
+ this.triggerMoveEvent();
3544
+ }
3545
+ }
3546
+ setRotation(pitch, yaw, roll) {
3547
+ const newAngles = vec3_exports.fromValues(pitch, yaw, roll);
3548
+ if (!vec3_exports.equals(this._angles, newAngles)) {
3549
+ vec3_exports.copy(this._angles, newAngles);
3550
+ this._dirty = true;
3551
+ this.triggerMoveEvent();
3552
+ }
3553
+ }
3554
+ setFov(fov) {
3555
+ this.fov = fov;
3556
+ }
3557
+ setAspectRatio(aspect) {
3558
+ this.aspect = aspect;
3559
+ }
3560
+ lookAt(target) {
3561
+ const direction = vec3_exports.create();
3562
+ vec3_exports.subtract(direction, target, this._position);
3563
+ const len2 = vec3_exports.length(direction);
3564
+ if (len2 < 1e-3) return;
3565
+ const yaw = Math.atan2(direction[1], direction[0]) * RAD2DEG;
3566
+ const hyp = Math.hypot(direction[0], direction[1]);
3567
+ const pitch = -Math.atan2(direction[2], hyp) * RAD2DEG;
3568
+ this.setRotation(pitch, yaw, 0);
3569
+ }
3570
+ triggerMoveEvent() {
3571
+ if (this.onCameraMove) {
3572
+ this.onCameraMove({
3573
+ position: vec3_exports.clone(this._position),
3574
+ angles: vec3_exports.clone(this._angles)
3575
+ });
3576
+ }
3577
+ }
3493
3578
  get viewMatrix() {
3494
3579
  this.updateMatrices();
3495
3580
  return this._viewMatrix;
@@ -3513,6 +3598,25 @@ var Camera = class {
3513
3598
  );
3514
3599
  return projectionMatrix;
3515
3600
  }
3601
+ screenToWorldRay(screenX, screenY) {
3602
+ const ndcX = screenX * 2 - 1;
3603
+ const ndcY = 1 - screenY * 2;
3604
+ const clipStart = vec3_exports.fromValues(ndcX, ndcY, -1);
3605
+ const clipEnd = vec3_exports.fromValues(ndcX, ndcY, 1);
3606
+ const invViewProj = mat4_exports.create();
3607
+ mat4_exports.invert(invViewProj, this.viewProjectionMatrix);
3608
+ const worldStart = vec3_exports.create();
3609
+ const worldEnd = vec3_exports.create();
3610
+ vec3_exports.transformMat4(worldStart, clipStart, invViewProj);
3611
+ vec3_exports.transformMat4(worldEnd, clipEnd, invViewProj);
3612
+ const direction = vec3_exports.create();
3613
+ vec3_exports.subtract(direction, worldEnd, worldStart);
3614
+ vec3_exports.normalize(direction, direction);
3615
+ return {
3616
+ origin: vec3_exports.clone(this._position),
3617
+ direction
3618
+ };
3619
+ }
3516
3620
  updateMatrices() {
3517
3621
  if (!this._dirty) {
3518
3622
  return;
@@ -3525,21 +3629,21 @@ var Camera = class {
3525
3629
  this._far
3526
3630
  );
3527
3631
  const quakeToGl = mat4_exports.fromValues(
3632
+ 0,
3528
3633
  0,
3529
3634
  -1,
3530
3635
  0,
3636
+ // column 0: Quake X -> WebGL -Z
3637
+ -1,
3531
3638
  0,
3532
- // column 0: Quake X -> WebGL (0, -1, 0)
3533
3639
  0,
3534
3640
  0,
3535
- 1,
3536
- 0,
3537
- // column 1: Quake Y -> WebGL (0, 0, 1)
3538
- -1,
3641
+ // column 1: Quake Y -> WebGL -X
3539
3642
  0,
3643
+ 1,
3540
3644
  0,
3541
3645
  0,
3542
- // column 2: Quake Z -> WebGL (-1, 0, 0)
3646
+ // column 2: Quake Z -> WebGL Y
3543
3647
  0,
3544
3648
  0,
3545
3649
  0,
@@ -3564,12 +3668,12 @@ var Camera = class {
3564
3668
  const rotatedPosQuake = vec3_exports.create();
3565
3669
  vec3_exports.transformMat4(rotatedPosQuake, negativePosition, rotationQuake);
3566
3670
  const translationGl = vec3_exports.fromValues(
3567
- rotatedPosQuake[1] || 0,
3568
- // Y in Quake -> X in WebGL (negation already applied above)
3671
+ rotatedPosQuake[1] ? -rotatedPosQuake[1] : 0,
3672
+ // Y in Quake -> -X in WebGL
3569
3673
  rotatedPosQuake[2] || 0,
3570
3674
  // Z in Quake -> Y in WebGL
3571
- rotatedPosQuake[0] || 0
3572
- // X in Quake -> Z in WebGL (negation already applied above)
3675
+ rotatedPosQuake[0] ? -rotatedPosQuake[0] : 0
3676
+ // X in Quake -> -Z in WebGL
3573
3677
  );
3574
3678
  mat4_exports.copy(this._viewMatrix, rotationGl);
3575
3679
  this._viewMatrix[12] = translationGl[0];
@@ -9930,6 +10034,73 @@ var ClientCommand = /* @__PURE__ */ ((ClientCommand2) => {
9930
10034
  ClientCommand2[ClientCommand2["stringcmd"] = 4] = "stringcmd";
9931
10035
  return ClientCommand2;
9932
10036
  })(ClientCommand || {});
10037
+ var TempEntity2 = /* @__PURE__ */ ((TempEntity22) => {
10038
+ TempEntity22[TempEntity22["GUNSHOT"] = 0] = "GUNSHOT";
10039
+ TempEntity22[TempEntity22["BLOOD"] = 1] = "BLOOD";
10040
+ TempEntity22[TempEntity22["BLASTER"] = 2] = "BLASTER";
10041
+ TempEntity22[TempEntity22["RAILTRAIL"] = 3] = "RAILTRAIL";
10042
+ TempEntity22[TempEntity22["SHOTGUN"] = 4] = "SHOTGUN";
10043
+ TempEntity22[TempEntity22["EXPLOSION1"] = 5] = "EXPLOSION1";
10044
+ TempEntity22[TempEntity22["EXPLOSION2"] = 6] = "EXPLOSION2";
10045
+ TempEntity22[TempEntity22["ROCKET_EXPLOSION"] = 7] = "ROCKET_EXPLOSION";
10046
+ TempEntity22[TempEntity22["GRENADE_EXPLOSION"] = 8] = "GRENADE_EXPLOSION";
10047
+ TempEntity22[TempEntity22["SPARKS"] = 9] = "SPARKS";
10048
+ TempEntity22[TempEntity22["SPLASH"] = 10] = "SPLASH";
10049
+ TempEntity22[TempEntity22["BUBBLETRAIL"] = 11] = "BUBBLETRAIL";
10050
+ TempEntity22[TempEntity22["SCREEN_SPARKS"] = 12] = "SCREEN_SPARKS";
10051
+ TempEntity22[TempEntity22["SHIELD_SPARKS"] = 13] = "SHIELD_SPARKS";
10052
+ TempEntity22[TempEntity22["BULLET_SPARKS"] = 14] = "BULLET_SPARKS";
10053
+ TempEntity22[TempEntity22["LASER_SPARKS"] = 15] = "LASER_SPARKS";
10054
+ TempEntity22[TempEntity22["PARASITE_ATTACK"] = 16] = "PARASITE_ATTACK";
10055
+ TempEntity22[TempEntity22["ROCKET_EXPLOSION_WATER"] = 17] = "ROCKET_EXPLOSION_WATER";
10056
+ TempEntity22[TempEntity22["GRENADE_EXPLOSION_WATER"] = 18] = "GRENADE_EXPLOSION_WATER";
10057
+ TempEntity22[TempEntity22["MEDIC_CABLE_ATTACK"] = 19] = "MEDIC_CABLE_ATTACK";
10058
+ TempEntity22[TempEntity22["BFG_EXPLOSION"] = 20] = "BFG_EXPLOSION";
10059
+ TempEntity22[TempEntity22["BFG_BIGEXPLOSION"] = 21] = "BFG_BIGEXPLOSION";
10060
+ TempEntity22[TempEntity22["BOSSTPORT"] = 22] = "BOSSTPORT";
10061
+ TempEntity22[TempEntity22["BFG_LASER"] = 23] = "BFG_LASER";
10062
+ TempEntity22[TempEntity22["GRAPPLE_CABLE"] = 24] = "GRAPPLE_CABLE";
10063
+ TempEntity22[TempEntity22["WELDING_SPARKS"] = 25] = "WELDING_SPARKS";
10064
+ TempEntity22[TempEntity22["GREENBLOOD"] = 26] = "GREENBLOOD";
10065
+ TempEntity22[TempEntity22["BLUEHYPERBLASTER"] = 27] = "BLUEHYPERBLASTER";
10066
+ TempEntity22[TempEntity22["PLASMA_EXPLOSION"] = 28] = "PLASMA_EXPLOSION";
10067
+ TempEntity22[TempEntity22["TUNNEL_SPARKS"] = 29] = "TUNNEL_SPARKS";
10068
+ TempEntity22[TempEntity22["BLASTER2"] = 30] = "BLASTER2";
10069
+ TempEntity22[TempEntity22["RAILTRAIL2"] = 31] = "RAILTRAIL2";
10070
+ TempEntity22[TempEntity22["FLAME"] = 32] = "FLAME";
10071
+ TempEntity22[TempEntity22["LIGHTNING"] = 33] = "LIGHTNING";
10072
+ TempEntity22[TempEntity22["DEBUGTRAIL"] = 34] = "DEBUGTRAIL";
10073
+ TempEntity22[TempEntity22["PLAIN_EXPLOSION"] = 35] = "PLAIN_EXPLOSION";
10074
+ TempEntity22[TempEntity22["FLASHLIGHT"] = 36] = "FLASHLIGHT";
10075
+ TempEntity22[TempEntity22["FORCEWALL"] = 37] = "FORCEWALL";
10076
+ TempEntity22[TempEntity22["HEATBEAM"] = 38] = "HEATBEAM";
10077
+ TempEntity22[TempEntity22["MONSTER_HEATBEAM"] = 39] = "MONSTER_HEATBEAM";
10078
+ TempEntity22[TempEntity22["STEAM"] = 40] = "STEAM";
10079
+ TempEntity22[TempEntity22["BUBBLETRAIL2"] = 41] = "BUBBLETRAIL2";
10080
+ TempEntity22[TempEntity22["MOREBLOOD"] = 42] = "MOREBLOOD";
10081
+ TempEntity22[TempEntity22["HEATBEAM_SPARKS"] = 43] = "HEATBEAM_SPARKS";
10082
+ TempEntity22[TempEntity22["HEATBEAM_STEAM"] = 44] = "HEATBEAM_STEAM";
10083
+ TempEntity22[TempEntity22["CHAINFIST_SMOKE"] = 45] = "CHAINFIST_SMOKE";
10084
+ TempEntity22[TempEntity22["ELECTRIC_SPARKS"] = 46] = "ELECTRIC_SPARKS";
10085
+ TempEntity22[TempEntity22["TRACKER_EXPLOSION"] = 47] = "TRACKER_EXPLOSION";
10086
+ TempEntity22[TempEntity22["TELEPORT_EFFECT"] = 48] = "TELEPORT_EFFECT";
10087
+ TempEntity22[TempEntity22["DBALL_GOAL"] = 49] = "DBALL_GOAL";
10088
+ TempEntity22[TempEntity22["WIDOWBEAMOUT"] = 50] = "WIDOWBEAMOUT";
10089
+ TempEntity22[TempEntity22["NUKEBLAST"] = 51] = "NUKEBLAST";
10090
+ TempEntity22[TempEntity22["WIDOWSPLASH"] = 52] = "WIDOWSPLASH";
10091
+ TempEntity22[TempEntity22["EXPLOSION1_BIG"] = 53] = "EXPLOSION1_BIG";
10092
+ TempEntity22[TempEntity22["EXPLOSION1_NP"] = 54] = "EXPLOSION1_NP";
10093
+ TempEntity22[TempEntity22["FLECHETTE"] = 55] = "FLECHETTE";
10094
+ TempEntity22[TempEntity22["BLUEHYPERBLASTER_KEX"] = 56] = "BLUEHYPERBLASTER_KEX";
10095
+ TempEntity22[TempEntity22["BFG_ZAP"] = 57] = "BFG_ZAP";
10096
+ TempEntity22[TempEntity22["BERSERK_SLAM"] = 58] = "BERSERK_SLAM";
10097
+ TempEntity22[TempEntity22["GRAPPLE_CABLE_2"] = 59] = "GRAPPLE_CABLE_2";
10098
+ TempEntity22[TempEntity22["POWER_SPLASH"] = 60] = "POWER_SPLASH";
10099
+ TempEntity22[TempEntity22["LIGHTNING_BEAM"] = 61] = "LIGHTNING_BEAM";
10100
+ TempEntity22[TempEntity22["EXPLOSION1_NL"] = 62] = "EXPLOSION1_NL";
10101
+ TempEntity22[TempEntity22["EXPLOSION2_NL"] = 63] = "EXPLOSION2_NL";
10102
+ return TempEntity22;
10103
+ })(TempEntity2 || {});
9933
10104
  var CMD_BACKUP = 64;
9934
10105
  var MZ_BLASTER = 0;
9935
10106
  var MZ_MACHINEGUN = 1;
@@ -9943,6 +10114,7 @@ var MZ_GRENADE = 8;
9943
10114
  var MZ_SSHOTGUN = 11;
9944
10115
  var MZ_BFG = 12;
9945
10116
  var MZ_HYPERBLASTER = 13;
10117
+ var MZ_BLUEHYPERBLASTER = 17;
9946
10118
  function readUint16LE(stats, startIndex, byteOffset) {
9947
10119
  const elementIndex = Math.floor(byteOffset / 2);
9948
10120
  const isOdd = byteOffset % 2 !== 0;
@@ -11689,6 +11861,9 @@ var ClientNetworkHandler = class {
11689
11861
  }
11690
11862
  }
11691
11863
  onTempEntity(type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt) {
11864
+ if (this.callbacks?.onTempEntity) {
11865
+ this.callbacks.onTempEntity(type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt);
11866
+ }
11692
11867
  }
11693
11868
  onLayout(layout) {
11694
11869
  }
@@ -11696,8 +11871,14 @@ var ClientNetworkHandler = class {
11696
11871
  this.inventory = [...inventory];
11697
11872
  }
11698
11873
  onMuzzleFlash(ent, weapon) {
11874
+ if (this.callbacks?.onMuzzleFlash) {
11875
+ this.callbacks.onMuzzleFlash(ent, weapon);
11876
+ }
11699
11877
  }
11700
11878
  onMuzzleFlash2(ent, weapon) {
11879
+ if (this.callbacks?.onMuzzleFlash2) {
11880
+ this.callbacks.onMuzzleFlash2(ent, weapon);
11881
+ }
11701
11882
  }
11702
11883
  onMuzzleFlash3(ent, weapon) {
11703
11884
  const isLocalPlayer = ent === this.playerNum + 1;
@@ -13205,6 +13386,7 @@ var MultiplayerConnection = class {
13205
13386
  this.levelName = "";
13206
13387
  this.configStrings = /* @__PURE__ */ new Map();
13207
13388
  this.baselines = /* @__PURE__ */ new Map();
13389
+ this.entities = /* @__PURE__ */ new Map();
13208
13390
  this.challenge = 0;
13209
13391
  this.connectPacketCount = 0;
13210
13392
  this.connectPacketTime = 0;
@@ -13235,6 +13417,9 @@ var MultiplayerConnection = class {
13235
13417
  setDemoRecorder(recorder) {
13236
13418
  this.demoRecorder = recorder;
13237
13419
  }
13420
+ setEffectSystem(system) {
13421
+ this.effectSystem = system;
13422
+ }
13238
13423
  async connectToServer(address, port) {
13239
13424
  const url = `ws://${address}:${port}`;
13240
13425
  return this.connect(url);
@@ -13270,6 +13455,7 @@ var MultiplayerConnection = class {
13270
13455
  cleanup() {
13271
13456
  this.configStrings.clear();
13272
13457
  this.baselines.clear();
13458
+ this.entities.clear();
13273
13459
  this.commandHistory = [];
13274
13460
  this.latestServerFrame = 0;
13275
13461
  this.parser = null;
@@ -13404,6 +13590,13 @@ var MultiplayerConnection = class {
13404
13590
  if (frame.serverFrame > this.latestServerFrame) {
13405
13591
  this.latestServerFrame = frame.serverFrame;
13406
13592
  }
13593
+ const packetEntities = frame.packetEntities;
13594
+ if (!packetEntities.delta) {
13595
+ this.entities.clear();
13596
+ }
13597
+ for (const ent of packetEntities.entities) {
13598
+ this.entities.set(ent.number, ent);
13599
+ }
13407
13600
  if (this.prediction && frame.playerState) {
13408
13601
  const ps = frame.playerState;
13409
13602
  const predState = {
@@ -13432,15 +13625,29 @@ var MultiplayerConnection = class {
13432
13625
  onSound(flags, soundNum, volume, attenuation, offset, ent, pos) {
13433
13626
  }
13434
13627
  onTempEntity(type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt) {
13628
+ if (this.effectSystem) {
13629
+ const time = Date.now() / 1e3;
13630
+ this.effectSystem.onTempEntity(type, pos, time);
13631
+ }
13435
13632
  }
13436
13633
  onLayout(layout) {
13437
13634
  }
13438
13635
  onInventory(inventory) {
13439
13636
  }
13440
13637
  onMuzzleFlash(ent, weapon) {
13638
+ if (this.effectSystem) {
13639
+ const time = Date.now() / 1e3;
13640
+ this.effectSystem.onMuzzleFlash(ent, weapon, time);
13641
+ }
13441
13642
  }
13442
13643
  onMuzzleFlash2(ent, weapon) {
13443
13644
  }
13645
+ onMuzzleFlash3(ent, weapon) {
13646
+ if (this.effectSystem) {
13647
+ const time = Date.now() / 1e3;
13648
+ this.effectSystem.onMuzzleFlash(ent, weapon, time);
13649
+ }
13650
+ }
13444
13651
  onDisconnect() {
13445
13652
  this.disconnect();
13446
13653
  }
@@ -13448,6 +13655,31 @@ var MultiplayerConnection = class {
13448
13655
  }
13449
13656
  onDownload(size, percent, data) {
13450
13657
  }
13658
+ // New handlers stubs
13659
+ onSplitClient(clientNum) {
13660
+ }
13661
+ onConfigBlast(index, data) {
13662
+ }
13663
+ onSpawnBaselineBlast(entity) {
13664
+ }
13665
+ onLevelRestart() {
13666
+ }
13667
+ onDamage(indicators) {
13668
+ }
13669
+ onLocPrint(flags, base, args) {
13670
+ }
13671
+ onFog(data) {
13672
+ }
13673
+ onWaitingForPlayers(count) {
13674
+ }
13675
+ onBotChat(msg) {
13676
+ }
13677
+ onPoi(flags, pos) {
13678
+ }
13679
+ onHelpPath(pos) {
13680
+ }
13681
+ onAchievement(id) {
13682
+ }
13451
13683
  };
13452
13684
 
13453
13685
  // src/ui/demo-controls.ts
@@ -13595,6 +13827,152 @@ function processEntityEffects(entity, dlights, time) {
13595
13827
  }
13596
13828
  }
13597
13829
 
13830
+ // src/effects-system.ts
13831
+ var copyVec3 = (v) => ({ x: v.x, y: v.y, z: v.z });
13832
+ var vectorMA = (start, scale3, dir) => ({
13833
+ x: start.x + dir.x * scale3,
13834
+ y: start.y + dir.y * scale3,
13835
+ z: start.z + dir.z * scale3
13836
+ });
13837
+ var ClientEffectSystem = class {
13838
+ constructor(dlightManager, engine, entityProvider) {
13839
+ this.dlightManager = dlightManager;
13840
+ this.engine = engine;
13841
+ this.entityProvider = entityProvider;
13842
+ }
13843
+ // Helper to add dlight
13844
+ addLight(key, origin, color, radius, minLight, time) {
13845
+ this.dlightManager.addLight({
13846
+ key,
13847
+ origin: copyVec3(origin),
13848
+ color,
13849
+ intensity: radius,
13850
+ minLight,
13851
+ die: time
13852
+ }, 0);
13853
+ }
13854
+ playSound(pos, ent, soundName, vol = 1, attn = 1) {
13855
+ if (!this.engine.audio) return;
13856
+ const index = this.engine.audio.soundindex(soundName);
13857
+ if (index === 0) return;
13858
+ if (pos) {
13859
+ this.engine.audio.positioned_sound(pos, index, vol, attn);
13860
+ } else {
13861
+ this.engine.audio.sound(ent, 0, index, vol, attn, 0);
13862
+ }
13863
+ }
13864
+ onMuzzleFlash(entNum, weapon, time) {
13865
+ const ent = this.entityProvider.getEntity(entNum);
13866
+ if (!ent) return;
13867
+ const origin = { x: ent.origin.x, y: ent.origin.y, z: ent.origin.z };
13868
+ const angles = { x: ent.angles.x, y: ent.angles.y, z: ent.angles.z };
13869
+ const vectors = angleVectors(angles);
13870
+ let flashOrigin = vectorMA(origin, 18, vectors.forward);
13871
+ flashOrigin = vectorMA(flashOrigin, 16, vectors.right);
13872
+ const silenced = (weapon & 128) !== 0;
13873
+ weapon &= ~128;
13874
+ let radius = silenced ? 100 + Math.random() * 31 : 200 + Math.random() * 31;
13875
+ const minLight = 32;
13876
+ const duration = 0.1;
13877
+ const die = time + duration;
13878
+ const volume = silenced ? 0.2 : 1;
13879
+ let color = { x: 1, y: 1, z: 0 };
13880
+ switch (weapon) {
13881
+ case MZ_BLASTER:
13882
+ case MZ_HYPERBLASTER:
13883
+ case MZ_MACHINEGUN:
13884
+ case MZ_SHOTGUN:
13885
+ case MZ_SSHOTGUN:
13886
+ case MZ_CHAINGUN1:
13887
+ case MZ_CHAINGUN2:
13888
+ case MZ_CHAINGUN3:
13889
+ color = { x: 1, y: 1, z: 0 };
13890
+ break;
13891
+ case MZ_BLUEHYPERBLASTER:
13892
+ color = { x: 0, y: 0, z: 1 };
13893
+ break;
13894
+ case MZ_RAILGUN:
13895
+ color = { x: 0.5, y: 0.5, z: 1 };
13896
+ break;
13897
+ case MZ_ROCKET:
13898
+ case MZ_GRENADE:
13899
+ color = { x: 1, y: 0.5, z: 0.2 };
13900
+ break;
13901
+ case MZ_BFG:
13902
+ color = { x: 0, y: 1, z: 0 };
13903
+ break;
13904
+ }
13905
+ this.addLight(entNum, flashOrigin, color, radius, minLight, die);
13906
+ let soundName = "";
13907
+ switch (weapon) {
13908
+ case MZ_BLASTER:
13909
+ soundName = "weapons/blastf1a.wav";
13910
+ break;
13911
+ case MZ_SHOTGUN:
13912
+ soundName = "weapons/shotgf1b.wav";
13913
+ break;
13914
+ case MZ_SSHOTGUN:
13915
+ soundName = "weapons/sshotf1b.wav";
13916
+ break;
13917
+ case MZ_MACHINEGUN:
13918
+ soundName = `weapons/machgf${Math.floor(Math.random() * 5) + 1}b.wav`;
13919
+ break;
13920
+ case MZ_RAILGUN:
13921
+ soundName = "weapons/railgf1a.wav";
13922
+ break;
13923
+ case MZ_ROCKET:
13924
+ soundName = "weapons/rocklf1a.wav";
13925
+ break;
13926
+ case MZ_GRENADE:
13927
+ soundName = "weapons/grenlf1a.wav";
13928
+ break;
13929
+ case MZ_BFG:
13930
+ soundName = "weapons/bfg__f1y.wav";
13931
+ break;
13932
+ case MZ_HYPERBLASTER:
13933
+ soundName = "weapons/hyprbf1a.wav";
13934
+ break;
13935
+ case MZ_BLUEHYPERBLASTER:
13936
+ soundName = "weapons/hyprbf1a.wav";
13937
+ break;
13938
+ case MZ_CHAINGUN1:
13939
+ case MZ_CHAINGUN2:
13940
+ case MZ_CHAINGUN3:
13941
+ soundName = `weapons/machgf${Math.floor(Math.random() * 5) + 1}b.wav`;
13942
+ break;
13943
+ }
13944
+ if (soundName) {
13945
+ this.playSound(null, entNum, soundName, volume, 1);
13946
+ }
13947
+ }
13948
+ onTempEntity(type, pos, time) {
13949
+ switch (type) {
13950
+ case TempEntity2.EXPLOSION1:
13951
+ case TempEntity2.EXPLOSION1_BIG:
13952
+ case TempEntity2.EXPLOSION1_NP:
13953
+ case TempEntity2.ROCKET_EXPLOSION:
13954
+ case TempEntity2.GRENADE_EXPLOSION:
13955
+ case TempEntity2.ROCKET_EXPLOSION_WATER:
13956
+ case TempEntity2.GRENADE_EXPLOSION_WATER:
13957
+ {
13958
+ const color = { x: 1, y: 0.5, z: 0.2 };
13959
+ const duration = 0.5;
13960
+ this.addLight(void 0, pos, color, 300, 0, time + duration);
13961
+ this.playSound(pos, 0, "weapons/rocklx1a.wav", 1, 0.5);
13962
+ }
13963
+ break;
13964
+ case TempEntity2.BFG_EXPLOSION:
13965
+ case TempEntity2.BFG_BIGEXPLOSION:
13966
+ {
13967
+ const color = { x: 0, y: 1, z: 0 };
13968
+ this.addLight(void 0, pos, color, 300, 0, time + 0.5);
13969
+ this.playSound(pos, 0, "weapons/bfg__x1b.wav", 1, 0.5);
13970
+ }
13971
+ break;
13972
+ }
13973
+ }
13974
+ };
13975
+
13598
13976
  // src/input/bindings.ts
13599
13977
  var DEFAULT_BINDINGS = [
13600
13978
  { code: "KeyW", command: "+forward" },
@@ -14253,6 +14631,23 @@ function createClient(imports) {
14253
14631
  const demoHandler = new ClientNetworkHandler(imports);
14254
14632
  const demoRecorder = new DemoRecorder();
14255
14633
  demoHandler.setView(view);
14634
+ const dlightManager = new DynamicLightManager();
14635
+ const entityProvider = {
14636
+ getEntity(entNum) {
14637
+ if (isDemoPlaying) {
14638
+ return demoHandler.entities.get(entNum);
14639
+ } else {
14640
+ if (multiplayer.isConnected()) {
14641
+ return multiplayer.entities.get(entNum);
14642
+ }
14643
+ }
14644
+ return void 0;
14645
+ },
14646
+ getPlayerNum() {
14647
+ return multiplayer.playerNum;
14648
+ }
14649
+ };
14650
+ const effectSystem = new ClientEffectSystem(dlightManager, imports.engine, entityProvider);
14256
14651
  let isDemoPlaying = false;
14257
14652
  let currentDemoName = null;
14258
14653
  let clientMode = 0 /* Normal */;
@@ -14315,6 +14710,7 @@ function createClient(imports) {
14315
14710
  }
14316
14711
  });
14317
14712
  multiplayer.setDemoRecorder(demoRecorder);
14713
+ multiplayer.setEffectSystem(effectSystem);
14318
14714
  const multiplayerFactory = new MultiplayerMenuFactory(menuSystem, multiplayer);
14319
14715
  demoHandler.setCallbacks({
14320
14716
  onCenterPrint: (msg) => cg.ParseCenterPrint(msg, 0, false),
@@ -14329,6 +14725,19 @@ function createClient(imports) {
14329
14725
  } else {
14330
14726
  demoPlayback.setFrameDuration(100);
14331
14727
  }
14728
+ },
14729
+ // New hooks for effects
14730
+ onMuzzleFlash: (ent, weapon) => {
14731
+ const time = demoPlayback.getCurrentTime() / 1e3;
14732
+ effectSystem.onMuzzleFlash(ent, weapon, time);
14733
+ },
14734
+ onMuzzleFlash2: (ent, weapon) => {
14735
+ },
14736
+ onTempEntity: (type, pos, pos2, dir, cnt, color, ent, srcEnt, destEnt) => {
14737
+ const time = demoPlayback.getCurrentTime() / 1e3;
14738
+ if (pos) {
14739
+ effectSystem.onTempEntity(type, pos, time);
14740
+ }
14332
14741
  }
14333
14742
  });
14334
14743
  demoPlayback.setHandler(demoHandler);
@@ -14442,6 +14851,7 @@ function createClient(imports) {
14442
14851
  const clientExports = {
14443
14852
  loadingScreen,
14444
14853
  errorDialog,
14854
+ dlightManager,
14445
14855
  init(initial) {
14446
14856
  this.Init(initial);
14447
14857
  },
@@ -14640,8 +15050,9 @@ function createClient(imports) {
14640
15050
  const frameTimeMs = sample.latest && sample.previous ? Math.max(0, sample.latest.timeMs - sample.previous.timeMs) : 0;
14641
15051
  lastView = view.sample(lastRendered, frameTimeMs);
14642
15052
  const command = {};
14643
- const dlights = [];
14644
15053
  const timeSeconds = sample.nowMs / 1e3;
15054
+ dlightManager.update(timeSeconds);
15055
+ const dlights = [...dlightManager.getActiveLights()];
14645
15056
  for (const ent of currentPacketEntities) {
14646
15057
  processEntityEffects(ent, dlights, timeSeconds);
14647
15058
  }