quake2ts 0.0.206 → 0.0.208

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.
@@ -3533,59 +3533,12 @@ var __export3 = (target, all) => {
3533
3533
  };
3534
3534
  var ZERO_VEC3 = { x: 0, y: 0, z: 0 };
3535
3535
  var DEG_TO_RAD2 = Math.PI / 180;
3536
- function dotVec3(a, b) {
3537
- return a.x * b.x + a.y * b.y + a.z * b.z;
3538
- }
3539
- var PITCH = 0;
3540
- var YAW = 1;
3541
- var ROLL = 2;
3542
3536
  var DEG2RAD_FACTOR2 = Math.PI / 180;
3543
3537
  var RAD2DEG_FACTOR2 = 180 / Math.PI;
3544
- function axisComponent(vec, axis) {
3545
- switch (axis) {
3546
- case PITCH:
3547
- return vec.x;
3548
- case YAW:
3549
- return vec.y;
3550
- case ROLL:
3551
- default:
3552
- return vec.z;
3553
- }
3554
- }
3555
- function degToRad(degrees) {
3556
- return degrees * DEG2RAD_FACTOR2;
3557
- }
3558
3538
  function angleMod(angle2) {
3559
3539
  const value = angle2 % 360;
3560
3540
  return value < 0 ? 360 + value : value;
3561
3541
  }
3562
- function angleVectors(angles) {
3563
- const yaw = degToRad(axisComponent(angles, YAW));
3564
- const pitch = degToRad(axisComponent(angles, PITCH));
3565
- const roll = degToRad(axisComponent(angles, ROLL));
3566
- const sy = Math.sin(yaw);
3567
- const cy = Math.cos(yaw);
3568
- const sp = Math.sin(pitch);
3569
- const cp = Math.cos(pitch);
3570
- const sr = Math.sin(roll);
3571
- const cr = Math.cos(roll);
3572
- const forward = {
3573
- x: cp * cy,
3574
- y: cp * sy,
3575
- z: -sp
3576
- };
3577
- const right = {
3578
- x: -sr * sp * cy - cr * -sy,
3579
- y: -sr * sp * sy - cr * cy,
3580
- z: -sr * cp
3581
- };
3582
- const up = {
3583
- x: cr * sp * cy - sr * -sy,
3584
- y: cr * sp * sy - sr * cy,
3585
- z: cr * cp
3586
- };
3587
- return { forward, right, up };
3588
- }
3589
3542
  var CONTENTS_SOLID2 = 1 << 0;
3590
3543
  var CONTENTS_WINDOW2 = 1 << 1;
3591
3544
  var CONTENTS_AUX2 = 1 << 2;
@@ -3785,6 +3738,56 @@ function mouseDeltaToViewDelta(delta, options) {
3785
3738
  z: 0
3786
3739
  };
3787
3740
  }
3741
+ var PlayerStat = /* @__PURE__ */ ((PlayerStat2) => {
3742
+ PlayerStat2[PlayerStat2["STAT_HEALTH_ICON"] = 0] = "STAT_HEALTH_ICON";
3743
+ PlayerStat2[PlayerStat2["STAT_HEALTH"] = 1] = "STAT_HEALTH";
3744
+ PlayerStat2[PlayerStat2["STAT_AMMO_ICON"] = 2] = "STAT_AMMO_ICON";
3745
+ PlayerStat2[PlayerStat2["STAT_AMMO"] = 3] = "STAT_AMMO";
3746
+ PlayerStat2[PlayerStat2["STAT_ARMOR_ICON"] = 4] = "STAT_ARMOR_ICON";
3747
+ PlayerStat2[PlayerStat2["STAT_ARMOR"] = 5] = "STAT_ARMOR";
3748
+ PlayerStat2[PlayerStat2["STAT_SELECTED_ICON"] = 6] = "STAT_SELECTED_ICON";
3749
+ PlayerStat2[PlayerStat2["STAT_PICKUP_ICON"] = 7] = "STAT_PICKUP_ICON";
3750
+ PlayerStat2[PlayerStat2["STAT_PICKUP_STRING"] = 8] = "STAT_PICKUP_STRING";
3751
+ PlayerStat2[PlayerStat2["STAT_TIMER_ICON"] = 9] = "STAT_TIMER_ICON";
3752
+ PlayerStat2[PlayerStat2["STAT_TIMER"] = 10] = "STAT_TIMER";
3753
+ PlayerStat2[PlayerStat2["STAT_HELPICON"] = 11] = "STAT_HELPICON";
3754
+ PlayerStat2[PlayerStat2["STAT_SELECTED_ITEM"] = 12] = "STAT_SELECTED_ITEM";
3755
+ PlayerStat2[PlayerStat2["STAT_LAYOUTS"] = 13] = "STAT_LAYOUTS";
3756
+ PlayerStat2[PlayerStat2["STAT_FRAGS"] = 14] = "STAT_FRAGS";
3757
+ PlayerStat2[PlayerStat2["STAT_FLASHES"] = 15] = "STAT_FLASHES";
3758
+ PlayerStat2[PlayerStat2["STAT_CHASE"] = 16] = "STAT_CHASE";
3759
+ PlayerStat2[PlayerStat2["STAT_SPECTATOR"] = 17] = "STAT_SPECTATOR";
3760
+ PlayerStat2[PlayerStat2["STAT_CTF_TEAM1_PIC"] = 18] = "STAT_CTF_TEAM1_PIC";
3761
+ PlayerStat2[PlayerStat2["STAT_CTF_TEAM1_CAPS"] = 19] = "STAT_CTF_TEAM1_CAPS";
3762
+ PlayerStat2[PlayerStat2["STAT_CTF_TEAM2_PIC"] = 20] = "STAT_CTF_TEAM2_PIC";
3763
+ PlayerStat2[PlayerStat2["STAT_CTF_TEAM2_CAPS"] = 21] = "STAT_CTF_TEAM2_CAPS";
3764
+ PlayerStat2[PlayerStat2["STAT_CTF_FLAG_PIC"] = 22] = "STAT_CTF_FLAG_PIC";
3765
+ PlayerStat2[PlayerStat2["STAT_CTF_JOINED_TEAM1_PIC"] = 23] = "STAT_CTF_JOINED_TEAM1_PIC";
3766
+ PlayerStat2[PlayerStat2["STAT_CTF_JOINED_TEAM2_PIC"] = 24] = "STAT_CTF_JOINED_TEAM2_PIC";
3767
+ PlayerStat2[PlayerStat2["STAT_CTF_TEAM1_HEADER"] = 25] = "STAT_CTF_TEAM1_HEADER";
3768
+ PlayerStat2[PlayerStat2["STAT_CTF_TEAM2_HEADER"] = 26] = "STAT_CTF_TEAM2_HEADER";
3769
+ PlayerStat2[PlayerStat2["STAT_CTF_TECH"] = 27] = "STAT_CTF_TECH";
3770
+ PlayerStat2[PlayerStat2["STAT_CTF_ID_VIEW"] = 28] = "STAT_CTF_ID_VIEW";
3771
+ PlayerStat2[PlayerStat2["STAT_CTF_MATCH"] = 29] = "STAT_CTF_MATCH";
3772
+ PlayerStat2[PlayerStat2["STAT_CTF_ID_VIEW_COLOR"] = 30] = "STAT_CTF_ID_VIEW_COLOR";
3773
+ PlayerStat2[PlayerStat2["STAT_CTF_TEAMINFO"] = 31] = "STAT_CTF_TEAMINFO";
3774
+ PlayerStat2[PlayerStat2["STAT_WEAPONS_OWNED_1"] = 32] = "STAT_WEAPONS_OWNED_1";
3775
+ PlayerStat2[PlayerStat2["STAT_WEAPONS_OWNED_2"] = 33] = "STAT_WEAPONS_OWNED_2";
3776
+ PlayerStat2[PlayerStat2["STAT_AMMO_INFO_START"] = 34] = "STAT_AMMO_INFO_START";
3777
+ PlayerStat2[PlayerStat2["STAT_POWERUP_INFO_START"] = 41] = "STAT_POWERUP_INFO_START";
3778
+ PlayerStat2[PlayerStat2["STAT_KEY_A"] = 44] = "STAT_KEY_A";
3779
+ PlayerStat2[PlayerStat2["STAT_KEY_B"] = 45] = "STAT_KEY_B";
3780
+ PlayerStat2[PlayerStat2["STAT_KEY_C"] = 46] = "STAT_KEY_C";
3781
+ PlayerStat2[PlayerStat2["STAT_ACTIVE_WHEEL_WEAPON"] = 47] = "STAT_ACTIVE_WHEEL_WEAPON";
3782
+ PlayerStat2[PlayerStat2["STAT_COOP_RESPAWN"] = 48] = "STAT_COOP_RESPAWN";
3783
+ PlayerStat2[PlayerStat2["STAT_LIVES"] = 49] = "STAT_LIVES";
3784
+ PlayerStat2[PlayerStat2["STAT_HIT_MARKER"] = 50] = "STAT_HIT_MARKER";
3785
+ PlayerStat2[PlayerStat2["STAT_SELECTED_ITEM_NAME"] = 51] = "STAT_SELECTED_ITEM_NAME";
3786
+ PlayerStat2[PlayerStat2["STAT_HEALTH_BARS"] = 52] = "STAT_HEALTH_BARS";
3787
+ PlayerStat2[PlayerStat2["STAT_ACTIVE_WEAPON"] = 53] = "STAT_ACTIVE_WEAPON";
3788
+ PlayerStat2[PlayerStat2["STAT_LAST"] = 54] = "STAT_LAST";
3789
+ return PlayerStat2;
3790
+ })(PlayerStat || {});
3788
3791
  var AMMO_MAX2 = 12;
3789
3792
  var NUM_BITS_FOR_AMMO2 = 9;
3790
3793
  var NUM_AMMO_STATS2 = Math.ceil(AMMO_MAX2 * NUM_BITS_FOR_AMMO2 / 16);
@@ -4021,7 +4024,6 @@ function createCGameImport(imports, state) {
4021
4024
  // src/hud/crosshair.ts
4022
4025
  var crosshairPic = null;
4023
4026
  var crosshairIndex = 0;
4024
- var crosshairColor = [1, 1, 1, 1];
4025
4027
  var crosshairEnabled = true;
4026
4028
  var CROSSHAIR_NAMES = ["ch1", "ch2", "ch3"];
4027
4029
  var crosshairPics = [null, null, null];
@@ -4075,59 +4077,9 @@ var Cycle_Crosshair = () => {
4075
4077
  }
4076
4078
  return crosshairEnabled ? crosshairIndex : -1;
4077
4079
  };
4078
- var Draw_Crosshair = (renderer, width, height) => {
4079
- if (crosshairEnabled && crosshairPic) {
4080
- const x = (width - crosshairPic.width) / 2;
4081
- const y = (height - crosshairPic.height) / 2;
4082
- renderer.drawPic(x, y, crosshairPic, crosshairColor);
4083
- }
4084
- };
4085
4080
 
4086
4081
  // src/hud/icons.ts
4087
4082
  var import_game = require("@quake2ts/game");
4088
-
4089
- // src/hud/layout.ts
4090
- var REFERENCE_WIDTH = 640;
4091
- var REFERENCE_HEIGHT = 480;
4092
- var getHudLayout = (width, height) => {
4093
- const scaleX = width / REFERENCE_WIDTH;
4094
- const scaleY = height / REFERENCE_HEIGHT;
4095
- const scale3 = Math.min(scaleX, scaleY);
4096
- return {
4097
- // Status bar numbers - Anchored Bottom-Left / Center / Right
4098
- HEALTH_X: 100 * scale3,
4099
- HEALTH_Y: height - (REFERENCE_HEIGHT - 450) * scale3,
4100
- ARMOR_X: 200 * scale3,
4101
- ARMOR_Y: height - (REFERENCE_HEIGHT - 450) * scale3,
4102
- AMMO_X: width - (REFERENCE_WIDTH - 540) * scale3,
4103
- // Anchor right? 540 is near right (640)
4104
- AMMO_Y: height - (REFERENCE_HEIGHT - 450) * scale3,
4105
- // Center print messages - Center
4106
- CENTER_PRINT_X: width / 2,
4107
- CENTER_PRINT_Y: 100 * scale3,
4108
- // Top anchor
4109
- // Weapon and powerup icons
4110
- WEAPON_ICON_X: 10 * scale3,
4111
- WEAPON_ICON_Y: height - (REFERENCE_HEIGHT - 450) * scale3,
4112
- POWERUP_X: width - (REFERENCE_WIDTH - 610) * scale3,
4113
- POWERUP_Y: height - (REFERENCE_HEIGHT - 450) * scale3,
4114
- scale: scale3
4115
- };
4116
- };
4117
-
4118
- // src/hud/numbers.ts
4119
- var Draw_Number = (renderer, x, y, value, pics, width, color) => {
4120
- const s = Math.abs(value).toString();
4121
- for (let i = 0; i < s.length; i++) {
4122
- const digit = parseInt(s[i]);
4123
- const pic = pics[digit];
4124
- if (pic) {
4125
- renderer.drawPic(x + i * width, y, pic, color);
4126
- }
4127
- }
4128
- };
4129
-
4130
- // src/hud/icons.ts
4131
4083
  var iconPics = /* @__PURE__ */ new Map();
4132
4084
  var ICON_NAMES = [
4133
4085
  // Weapons
@@ -4203,163 +4155,6 @@ var Init_Damage = async (renderer, assets) => {
4203
4155
  }
4204
4156
  }
4205
4157
  };
4206
- var Draw_Damage = (renderer, ps) => {
4207
- if (!ps.damageIndicators) {
4208
- return;
4209
- }
4210
- const screenWidth = renderer.width;
4211
- const screenHeight = renderer.height;
4212
- const { forward, right, up } = angleVectors(ps.viewAngles);
4213
- for (const indicator of ps.damageIndicators) {
4214
- const { direction, strength } = indicator;
4215
- const normalizedDirection = { ...direction };
4216
- const len2 = Math.sqrt(normalizedDirection.x * normalizedDirection.x + normalizedDirection.y * normalizedDirection.y + normalizedDirection.z * normalizedDirection.z);
4217
- if (len2 > 0) {
4218
- normalizedDirection.x /= len2;
4219
- normalizedDirection.y /= len2;
4220
- normalizedDirection.z /= len2;
4221
- }
4222
- const rightDot = dotVec3(normalizedDirection, right);
4223
- const forwardDot = dotVec3(normalizedDirection, forward);
4224
- const angle2 = Math.atan2(forwardDot, rightDot) * 180 / Math.PI;
4225
- let pic;
4226
- let x = 0;
4227
- let y = 0;
4228
- if (angle2 > -45 && angle2 <= 45) {
4229
- pic = damagePics.get("d_right");
4230
- x = screenWidth - (pic?.width || 0);
4231
- y = (screenHeight - (pic?.height || 0)) / 2;
4232
- } else if (angle2 > 45 && angle2 <= 135) {
4233
- pic = damagePics.get("d_up");
4234
- x = (screenWidth - (pic?.width || 0)) / 2;
4235
- y = 0;
4236
- } else if (angle2 > 135 || angle2 <= -135) {
4237
- pic = damagePics.get("d_left");
4238
- x = 0;
4239
- y = (screenHeight - (pic?.height || 0)) / 2;
4240
- } else {
4241
- pic = damagePics.get("d_down");
4242
- x = (screenWidth - (pic?.width || 0)) / 2;
4243
- y = screenHeight - (pic?.height || 0);
4244
- }
4245
- if (pic) {
4246
- renderer.drawPic(x, y, pic);
4247
- }
4248
- }
4249
- };
4250
-
4251
- // src/hud/diagnostics.ts
4252
- var Draw_Diagnostics = (renderer, stats) => {
4253
- const lines = [
4254
- `FPS: ${stats.fps}`,
4255
- `Draw Calls: ${stats.drawCalls}`,
4256
- `Batches: ${stats.batches}`,
4257
- `Faces Drawn: ${stats.facesDrawn}`,
4258
- `Vertices: ${stats.vertexCount}`
4259
- ];
4260
- let y = 10;
4261
- for (const line of lines) {
4262
- renderer.drawString(10, y, line);
4263
- y += 10;
4264
- }
4265
- };
4266
-
4267
- // src/hud/blends.ts
4268
- var Draw_Blends = (renderer, ps) => {
4269
- if (!ps.blend) return;
4270
- const [r, g, b, a] = ps.blend;
4271
- if (a > 0) {
4272
- renderer.drawfillRect(0, 0, renderer.width, renderer.height, [r, g, b, a]);
4273
- }
4274
- };
4275
-
4276
- // src/hud/pickup.ts
4277
- var Draw_Pickup = (renderer, ps) => {
4278
- if (!ps.pickupIcon) return;
4279
- const icon = iconPics.get(ps.pickupIcon);
4280
- if (icon) {
4281
- const x = renderer.width - icon.width - 10;
4282
- const y = renderer.height - icon.height - 10;
4283
- renderer.drawPic(x, y, icon);
4284
- }
4285
- };
4286
-
4287
- // src/hud/statusbar.ts
4288
- var import_game2 = require("@quake2ts/game");
4289
- var colorblindMode = false;
4290
- var Draw_StatusBar = (renderer, client, health, armor, ammo, hudNumberPics2, numberWidth2, timeMs, layout) => {
4291
- let healthColor = void 0;
4292
- if (health <= 25) {
4293
- if (colorblindMode) {
4294
- healthColor = [0.2, 0.6, 1, 1];
4295
- } else {
4296
- healthColor = [1, 0, 0, 1];
4297
- }
4298
- }
4299
- if (hudNumberPics2.length > 0) {
4300
- Draw_Number(renderer, layout.HEALTH_X, layout.HEALTH_Y, health, hudNumberPics2, numberWidth2, healthColor);
4301
- Draw_Number(renderer, layout.ARMOR_X, layout.ARMOR_Y, armor, hudNumberPics2, numberWidth2);
4302
- Draw_Number(renderer, layout.AMMO_X, layout.AMMO_Y, ammo, hudNumberPics2, numberWidth2);
4303
- }
4304
- const armorItem = client.inventory.armor;
4305
- if (armorItem && armorItem.armorCount > 0) {
4306
- const iconName = `i_${armorItem.armorType}armor`;
4307
- const icon = iconPics.get(iconName);
4308
- if (icon) {
4309
- renderer.drawPic(layout.ARMOR_X - 24, layout.ARMOR_Y - 2, icon);
4310
- }
4311
- }
4312
- const currentWeapon = client.inventory.currentWeapon;
4313
- if (currentWeapon) {
4314
- const weaponDef = Object.values(import_game2.WEAPON_ITEMS).find((w) => w.weaponId === currentWeapon);
4315
- if (weaponDef) {
4316
- const iconName = `w_${weaponDef.id.substring(7)}`;
4317
- const icon = iconPics.get(iconName);
4318
- if (icon) {
4319
- renderer.drawPic(layout.WEAPON_ICON_X, layout.WEAPON_ICON_Y, icon);
4320
- }
4321
- }
4322
- }
4323
- const keys = Array.from(client.inventory.keys).sort();
4324
- let keyY = layout.WEAPON_ICON_Y - 150 * layout.scale;
4325
- for (const key of keys) {
4326
- let iconName = "";
4327
- switch (key) {
4328
- case "blue":
4329
- iconName = "k_bluekey";
4330
- break;
4331
- case "red":
4332
- iconName = "k_redkey";
4333
- break;
4334
- case "green":
4335
- iconName = "k_security";
4336
- break;
4337
- case "yellow":
4338
- iconName = "k_pyramid";
4339
- break;
4340
- }
4341
- if (iconName) {
4342
- const icon = iconPics.get(iconName);
4343
- if (icon) {
4344
- renderer.drawPic(layout.WEAPON_ICON_X, keyY, icon);
4345
- keyY += icon.height + 2;
4346
- }
4347
- }
4348
- }
4349
- let powerupX = layout.POWERUP_X;
4350
- for (const [powerup, expiresAt] of client.inventory.powerups.entries()) {
4351
- if (expiresAt && expiresAt > timeMs) {
4352
- const iconName = `p_${powerup}`;
4353
- const icon = iconPics.get(iconName);
4354
- if (icon) {
4355
- renderer.drawPic(powerupX, layout.POWERUP_Y, icon);
4356
- const remainingSeconds = Math.ceil((expiresAt - timeMs) / 1e3);
4357
- Draw_Number(renderer, powerupX + icon.width + 2, layout.POWERUP_Y, remainingSeconds, hudNumberPics2, numberWidth2);
4358
- powerupX -= icon.width + numberWidth2 * remainingSeconds.toString().length + 8;
4359
- }
4360
- }
4361
- }
4362
- };
4363
4158
 
4364
4159
  // src/hud.ts
4365
4160
  var hudNumberPics = [];
@@ -4381,77 +4176,6 @@ var Init_Hud = async (renderer, assets) => {
4381
4176
  await Init_Icons(renderer, assets);
4382
4177
  await Init_Damage(renderer, assets);
4383
4178
  };
4384
- var Draw_Hud = (renderer, ps, client, health, armor, ammo, stats, messageSystem, subtitleSystem, timeMs) => {
4385
- renderer.begin2D();
4386
- Draw_Blends(renderer, ps);
4387
- if (ps.damageAlpha > 0) {
4388
- renderer.drawfillRect(0, 0, renderer.width, renderer.height, [1, 0, 0, ps.damageAlpha]);
4389
- }
4390
- const layout = getHudLayout(renderer.width, renderer.height);
4391
- Draw_StatusBar(renderer, client, health, armor, ammo, hudNumberPics, numberWidth, timeMs, layout);
4392
- Draw_Pickup(renderer, ps);
4393
- Draw_Damage(renderer, ps);
4394
- Draw_Diagnostics(renderer, stats);
4395
- messageSystem.drawCenterPrint(renderer, timeMs, layout);
4396
- messageSystem.drawNotifications(renderer, timeMs);
4397
- subtitleSystem.drawSubtitles(renderer, timeMs);
4398
- if (ps.centerPrint) {
4399
- renderer.drawCenterString(renderer.height / 2 - 20, ps.centerPrint);
4400
- }
4401
- if (ps.notify) {
4402
- renderer.drawString(8, 8, ps.notify);
4403
- }
4404
- Draw_Crosshair(renderer, renderer.width, renderer.height);
4405
- renderer.end2D();
4406
- };
4407
-
4408
- // src/hud/messages.ts
4409
- var CENTER_PRINT_DURATION = 3e3;
4410
- var NOTIFY_DURATION = 5e3;
4411
- var MAX_NOTIFY_MESSAGES = 4;
4412
- var MessageSystem = class {
4413
- constructor() {
4414
- this.centerPrintMsg = null;
4415
- this.notifyMessages = [];
4416
- }
4417
- addCenterPrint(text, now) {
4418
- this.centerPrintMsg = {
4419
- text,
4420
- startTime: now,
4421
- duration: CENTER_PRINT_DURATION
4422
- };
4423
- }
4424
- addNotify(text, now) {
4425
- this.notifyMessages.push({
4426
- text,
4427
- startTime: now,
4428
- duration: NOTIFY_DURATION
4429
- });
4430
- if (this.notifyMessages.length > MAX_NOTIFY_MESSAGES) {
4431
- this.notifyMessages.shift();
4432
- }
4433
- }
4434
- drawCenterPrint(renderer, now, layout) {
4435
- if (!this.centerPrintMsg) return;
4436
- if (now > this.centerPrintMsg.startTime + this.centerPrintMsg.duration) {
4437
- this.centerPrintMsg = null;
4438
- return;
4439
- }
4440
- const width = this.centerPrintMsg.text.length * 8;
4441
- const y = layout.CENTER_PRINT_Y;
4442
- renderer.drawCenterString(y, this.centerPrintMsg.text);
4443
- }
4444
- drawNotifications(renderer, now) {
4445
- while (this.notifyMessages.length > 0 && now > this.notifyMessages[0].startTime + this.notifyMessages[0].duration) {
4446
- this.notifyMessages.shift();
4447
- }
4448
- let y = 10;
4449
- for (const msg of this.notifyMessages) {
4450
- renderer.drawString(10, y, msg.text);
4451
- y += 10;
4452
- }
4453
- }
4454
- };
4455
4179
 
4456
4180
  // src/hud/subtitles.ts
4457
4181
  var SUBTITLE_DURATION = 3e3;
@@ -4483,20 +4207,20 @@ var SubtitleSystem = class {
4483
4207
  var import_cgame = require("@quake2ts/cgame");
4484
4208
 
4485
4209
  // src/demo/itemMapping.ts
4210
+ var import_game2 = require("@quake2ts/game");
4486
4211
  var import_game3 = require("@quake2ts/game");
4487
4212
  var import_game4 = require("@quake2ts/game");
4488
- var import_game5 = require("@quake2ts/game");
4489
4213
  var DEMO_ITEM_MAPPING = [
4490
4214
  { type: "null" },
4491
4215
  // IT_NULL = 0
4492
4216
  // Armor
4493
- { type: "armor", id: import_game5.ArmorType.BODY },
4217
+ { type: "armor", id: import_game4.ArmorType.BODY },
4494
4218
  // IT_ARMOR_BODY
4495
- { type: "armor", id: import_game5.ArmorType.COMBAT },
4219
+ { type: "armor", id: import_game4.ArmorType.COMBAT },
4496
4220
  // IT_ARMOR_COMBAT
4497
- { type: "armor", id: import_game5.ArmorType.JACKET },
4221
+ { type: "armor", id: import_game4.ArmorType.JACKET },
4498
4222
  // IT_ARMOR_JACKET
4499
- { type: "armor", id: import_game5.ArmorType.JACKET },
4223
+ { type: "armor", id: import_game4.ArmorType.JACKET },
4500
4224
  // IT_ARMOR_SHARD (Handled as jacket in base game logic usually, or separate counter)
4501
4225
  // Power Armor
4502
4226
  { type: "item", id: "item_power_screen" },
@@ -4504,85 +4228,85 @@ var DEMO_ITEM_MAPPING = [
4504
4228
  { type: "item", id: "item_power_shield" },
4505
4229
  // IT_ITEM_POWER_SHIELD
4506
4230
  // Weapons
4507
- { type: "weapon", id: import_game3.WeaponId.Grapple },
4231
+ { type: "weapon", id: import_game2.WeaponId.Grapple },
4508
4232
  // IT_WEAPON_GRAPPLE
4509
- { type: "weapon", id: import_game3.WeaponId.Blaster },
4233
+ { type: "weapon", id: import_game2.WeaponId.Blaster },
4510
4234
  // IT_WEAPON_BLASTER
4511
- { type: "weapon", id: import_game3.WeaponId.ChainFist },
4235
+ { type: "weapon", id: import_game2.WeaponId.ChainFist },
4512
4236
  // IT_WEAPON_CHAINFIST
4513
- { type: "weapon", id: import_game3.WeaponId.Shotgun },
4237
+ { type: "weapon", id: import_game2.WeaponId.Shotgun },
4514
4238
  // IT_WEAPON_SHOTGUN
4515
- { type: "weapon", id: import_game3.WeaponId.SuperShotgun },
4239
+ { type: "weapon", id: import_game2.WeaponId.SuperShotgun },
4516
4240
  // IT_WEAPON_SSHOTGUN
4517
- { type: "weapon", id: import_game3.WeaponId.Machinegun },
4241
+ { type: "weapon", id: import_game2.WeaponId.Machinegun },
4518
4242
  // IT_WEAPON_MACHINEGUN
4519
- { type: "weapon", id: import_game3.WeaponId.EtfRifle },
4243
+ { type: "weapon", id: import_game2.WeaponId.EtfRifle },
4520
4244
  // IT_WEAPON_ETF_RIFLE
4521
- { type: "weapon", id: import_game3.WeaponId.Chaingun },
4245
+ { type: "weapon", id: import_game2.WeaponId.Chaingun },
4522
4246
  // IT_WEAPON_CHAINGUN
4523
4247
  // Ammo
4524
- { type: "ammo", id: import_game4.AmmoType.Grenades },
4248
+ { type: "ammo", id: import_game3.AmmoType.Grenades },
4525
4249
  // IT_AMMO_GRENADES
4526
- { type: "ammo", id: import_game4.AmmoType.Trap },
4250
+ { type: "ammo", id: import_game3.AmmoType.Trap },
4527
4251
  // IT_AMMO_TRAP
4528
- { type: "ammo", id: import_game4.AmmoType.Tesla },
4252
+ { type: "ammo", id: import_game3.AmmoType.Tesla },
4529
4253
  // IT_AMMO_TESLA
4530
4254
  // Weapons cont.
4531
- { type: "weapon", id: import_game3.WeaponId.GrenadeLauncher },
4255
+ { type: "weapon", id: import_game2.WeaponId.GrenadeLauncher },
4532
4256
  // IT_WEAPON_GLAUNCHER
4533
- { type: "weapon", id: import_game3.WeaponId.ProxLauncher },
4257
+ { type: "weapon", id: import_game2.WeaponId.ProxLauncher },
4534
4258
  // IT_WEAPON_PROXLAUNCHER
4535
- { type: "weapon", id: import_game3.WeaponId.RocketLauncher },
4259
+ { type: "weapon", id: import_game2.WeaponId.RocketLauncher },
4536
4260
  // IT_WEAPON_RLAUNCHER
4537
- { type: "weapon", id: import_game3.WeaponId.HyperBlaster },
4261
+ { type: "weapon", id: import_game2.WeaponId.HyperBlaster },
4538
4262
  // IT_WEAPON_HYPERBLASTER
4539
- { type: "weapon", id: import_game3.WeaponId.IonRipper },
4263
+ { type: "weapon", id: import_game2.WeaponId.IonRipper },
4540
4264
  // IT_WEAPON_IONRIPPER
4541
- { type: "weapon", id: import_game3.WeaponId.PlasmaBeam },
4265
+ { type: "weapon", id: import_game2.WeaponId.PlasmaBeam },
4542
4266
  // IT_WEAPON_PLASMABEAM
4543
- { type: "weapon", id: import_game3.WeaponId.Railgun },
4267
+ { type: "weapon", id: import_game2.WeaponId.Railgun },
4544
4268
  // IT_WEAPON_RAILGUN
4545
- { type: "weapon", id: import_game3.WeaponId.Phalanx },
4269
+ { type: "weapon", id: import_game2.WeaponId.Phalanx },
4546
4270
  // IT_WEAPON_PHALANX
4547
- { type: "weapon", id: import_game3.WeaponId.BFG10K },
4271
+ { type: "weapon", id: import_game2.WeaponId.BFG10K },
4548
4272
  // IT_WEAPON_BFG
4549
- { type: "weapon", id: import_game3.WeaponId.Disruptor },
4273
+ { type: "weapon", id: import_game2.WeaponId.Disruptor },
4550
4274
  // IT_WEAPON_DISRUPTOR
4551
4275
  // Ammo
4552
- { type: "ammo", id: import_game4.AmmoType.Shells },
4276
+ { type: "ammo", id: import_game3.AmmoType.Shells },
4553
4277
  // IT_AMMO_SHELLS
4554
- { type: "ammo", id: import_game4.AmmoType.Bullets },
4278
+ { type: "ammo", id: import_game3.AmmoType.Bullets },
4555
4279
  // IT_AMMO_BULLETS
4556
- { type: "ammo", id: import_game4.AmmoType.Cells },
4280
+ { type: "ammo", id: import_game3.AmmoType.Cells },
4557
4281
  // IT_AMMO_CELLS
4558
- { type: "ammo", id: import_game4.AmmoType.Rockets },
4282
+ { type: "ammo", id: import_game3.AmmoType.Rockets },
4559
4283
  // IT_AMMO_ROCKETS
4560
- { type: "ammo", id: import_game4.AmmoType.Slugs },
4284
+ { type: "ammo", id: import_game3.AmmoType.Slugs },
4561
4285
  // IT_AMMO_SLUGS
4562
- { type: "ammo", id: import_game4.AmmoType.MagSlugs },
4286
+ { type: "ammo", id: import_game3.AmmoType.MagSlugs },
4563
4287
  // IT_AMMO_MAGSLUG
4564
- { type: "ammo", id: import_game4.AmmoType.Flechettes },
4288
+ { type: "ammo", id: import_game3.AmmoType.Flechettes },
4565
4289
  // IT_AMMO_FLECHETTES
4566
- { type: "ammo", id: import_game4.AmmoType.Prox },
4290
+ { type: "ammo", id: import_game3.AmmoType.Prox },
4567
4291
  // IT_AMMO_PROX
4568
- { type: "ammo", id: import_game4.AmmoType.Nuke },
4292
+ { type: "ammo", id: import_game3.AmmoType.Nuke },
4569
4293
  // IT_AMMO_NUKE
4570
- { type: "ammo", id: import_game4.AmmoType.Rounds },
4294
+ { type: "ammo", id: import_game3.AmmoType.Rounds },
4571
4295
  // IT_AMMO_ROUNDS
4572
4296
  // Items / Powerups
4573
- { type: "powerup", id: import_game3.PowerupId.QuadDamage },
4297
+ { type: "powerup", id: import_game2.PowerupId.QuadDamage },
4574
4298
  // IT_ITEM_QUAD
4575
- { type: "powerup", id: import_game3.PowerupId.QuadFire },
4299
+ { type: "powerup", id: import_game2.PowerupId.QuadFire },
4576
4300
  // IT_ITEM_QUADFIRE
4577
- { type: "powerup", id: import_game3.PowerupId.Invulnerability },
4301
+ { type: "powerup", id: import_game2.PowerupId.Invulnerability },
4578
4302
  // IT_ITEM_INVULNERABILITY
4579
- { type: "powerup", id: import_game3.PowerupId.Invisibility },
4303
+ { type: "powerup", id: import_game2.PowerupId.Invisibility },
4580
4304
  // IT_ITEM_INVISIBILITY
4581
- { type: "powerup", id: import_game3.PowerupId.Silencer },
4305
+ { type: "powerup", id: import_game2.PowerupId.Silencer },
4582
4306
  // IT_ITEM_SILENCER
4583
- { type: "powerup", id: import_game3.PowerupId.Rebreather },
4307
+ { type: "powerup", id: import_game2.PowerupId.Rebreather },
4584
4308
  // IT_ITEM_REBREATHER
4585
- { type: "powerup", id: import_game3.PowerupId.EnviroSuit },
4309
+ { type: "powerup", id: import_game2.PowerupId.EnviroSuit },
4586
4310
  // IT_ITEM_ENVIROSUIT
4587
4311
  { type: "health", id: "ancient_head" },
4588
4312
  // IT_ITEM_ANCIENT_HEAD
@@ -4590,54 +4314,54 @@ var DEMO_ITEM_MAPPING = [
4590
4314
  // IT_ITEM_LEGACY_HEAD
4591
4315
  { type: "health", id: "adrenaline" },
4592
4316
  // IT_ITEM_ADRENALINE
4593
- { type: "powerup", id: import_game3.PowerupId.Bandolier },
4317
+ { type: "powerup", id: import_game2.PowerupId.Bandolier },
4594
4318
  // IT_ITEM_BANDOLIER
4595
- { type: "powerup", id: import_game3.PowerupId.AmmoPack },
4319
+ { type: "powerup", id: import_game2.PowerupId.AmmoPack },
4596
4320
  // IT_ITEM_PACK
4597
- { type: "powerup", id: import_game3.PowerupId.IRGoggles },
4321
+ { type: "powerup", id: import_game2.PowerupId.IRGoggles },
4598
4322
  // IT_ITEM_IR_GOGGLES
4599
- { type: "powerup", id: import_game3.PowerupId.DoubleDamage },
4323
+ { type: "powerup", id: import_game2.PowerupId.DoubleDamage },
4600
4324
  // IT_ITEM_DOUBLE
4601
- { type: "powerup", id: import_game3.PowerupId.SphereVengeance },
4325
+ { type: "powerup", id: import_game2.PowerupId.SphereVengeance },
4602
4326
  // IT_ITEM_SPHERE_VENGEANCE
4603
- { type: "powerup", id: import_game3.PowerupId.SphereHunter },
4327
+ { type: "powerup", id: import_game2.PowerupId.SphereHunter },
4604
4328
  // IT_ITEM_SPHERE_HUNTER
4605
- { type: "powerup", id: import_game3.PowerupId.SphereDefender },
4329
+ { type: "powerup", id: import_game2.PowerupId.SphereDefender },
4606
4330
  // IT_ITEM_SPHERE_DEFENDER
4607
- { type: "powerup", id: import_game3.PowerupId.Doppelganger },
4331
+ { type: "powerup", id: import_game2.PowerupId.Doppelganger },
4608
4332
  // IT_ITEM_DOPPELGANGER
4609
- { type: "powerup", id: import_game3.PowerupId.TagToken },
4333
+ { type: "powerup", id: import_game2.PowerupId.TagToken },
4610
4334
  // IT_ITEM_TAG_TOKEN
4611
4335
  // Keys
4612
- { type: "key", id: import_game3.KeyId.DataCD },
4336
+ { type: "key", id: import_game2.KeyId.DataCD },
4613
4337
  // IT_KEY_DATA_CD
4614
- { type: "key", id: import_game3.KeyId.PowerCube },
4338
+ { type: "key", id: import_game2.KeyId.PowerCube },
4615
4339
  // IT_KEY_POWER_CUBE
4616
- { type: "key", id: import_game3.KeyId.ExplosiveCharges },
4340
+ { type: "key", id: import_game2.KeyId.ExplosiveCharges },
4617
4341
  // IT_KEY_EXPLOSIVE_CHARGES
4618
- { type: "key", id: import_game3.KeyId.Yellow },
4342
+ { type: "key", id: import_game2.KeyId.Yellow },
4619
4343
  // IT_KEY_YELLOW
4620
- { type: "key", id: import_game3.KeyId.PowerCore },
4344
+ { type: "key", id: import_game2.KeyId.PowerCore },
4621
4345
  // IT_KEY_POWER_CORE
4622
- { type: "key", id: import_game3.KeyId.Pyramid },
4346
+ { type: "key", id: import_game2.KeyId.Pyramid },
4623
4347
  // IT_KEY_PYRAMID
4624
- { type: "key", id: import_game3.KeyId.DataSpinner },
4348
+ { type: "key", id: import_game2.KeyId.DataSpinner },
4625
4349
  // IT_KEY_DATA_SPINNER
4626
- { type: "key", id: import_game3.KeyId.Pass },
4350
+ { type: "key", id: import_game2.KeyId.Pass },
4627
4351
  // IT_KEY_PASS
4628
- { type: "key", id: import_game3.KeyId.Blue },
4352
+ { type: "key", id: import_game2.KeyId.Blue },
4629
4353
  // IT_KEY_BLUE_KEY
4630
- { type: "key", id: import_game3.KeyId.Red },
4354
+ { type: "key", id: import_game2.KeyId.Red },
4631
4355
  // IT_KEY_RED_KEY
4632
- { type: "key", id: import_game3.KeyId.Green },
4356
+ { type: "key", id: import_game2.KeyId.Green },
4633
4357
  // IT_KEY_GREEN_KEY
4634
- { type: "key", id: import_game3.KeyId.CommanderHead },
4358
+ { type: "key", id: import_game2.KeyId.CommanderHead },
4635
4359
  // IT_KEY_COMMANDER_HEAD
4636
- { type: "key", id: import_game3.KeyId.Airstrike },
4360
+ { type: "key", id: import_game2.KeyId.Airstrike },
4637
4361
  // IT_KEY_AIRSTRIKE
4638
- { type: "key", id: import_game3.KeyId.NukeContainer },
4362
+ { type: "key", id: import_game2.KeyId.NukeContainer },
4639
4363
  // IT_KEY_NUKE_CONTAINER
4640
- { type: "key", id: import_game3.KeyId.Nuke },
4364
+ { type: "key", id: import_game2.KeyId.Nuke },
4641
4365
  // IT_KEY_NUKE
4642
4366
  // Health
4643
4367
  { type: "health", id: "health_small" },
@@ -4649,22 +4373,22 @@ var DEMO_ITEM_MAPPING = [
4649
4373
  { type: "health", id: "health_mega" },
4650
4374
  // IT_HEALTH_MEGA
4651
4375
  // CTF
4652
- { type: "key", id: import_game3.KeyId.RedFlag },
4376
+ { type: "key", id: import_game2.KeyId.RedFlag },
4653
4377
  // IT_FLAG1
4654
- { type: "key", id: import_game3.KeyId.BlueFlag },
4378
+ { type: "key", id: import_game2.KeyId.BlueFlag },
4655
4379
  // IT_FLAG2
4656
4380
  // Tech
4657
- { type: "powerup", id: import_game3.PowerupId.TechResistance },
4381
+ { type: "powerup", id: import_game2.PowerupId.TechResistance },
4658
4382
  // IT_TECH_RESISTANCE
4659
- { type: "powerup", id: import_game3.PowerupId.TechStrength },
4383
+ { type: "powerup", id: import_game2.PowerupId.TechStrength },
4660
4384
  // IT_TECH_STRENGTH
4661
- { type: "powerup", id: import_game3.PowerupId.TechHaste },
4385
+ { type: "powerup", id: import_game2.PowerupId.TechHaste },
4662
4386
  // IT_TECH_HASTE
4663
- { type: "powerup", id: import_game3.PowerupId.TechRegeneration },
4387
+ { type: "powerup", id: import_game2.PowerupId.TechRegeneration },
4664
4388
  // IT_TECH_REGENERATION
4665
- { type: "powerup", id: import_game3.PowerupId.Flashlight },
4389
+ { type: "powerup", id: import_game2.PowerupId.Flashlight },
4666
4390
  // IT_ITEM_FLASHLIGHT
4667
- { type: "powerup", id: import_game3.PowerupId.Compass }
4391
+ { type: "powerup", id: import_game2.PowerupId.Compass }
4668
4392
  // IT_ITEM_COMPASS
4669
4393
  ];
4670
4394
 
@@ -6316,7 +6040,6 @@ function buildRenderableEntities(latestEntities, previousEntities, alpha, config
6316
6040
  function createClient(imports) {
6317
6041
  const prediction = new import_cgame2.ClientPrediction(imports.engine.trace);
6318
6042
  const view = new import_cgame3.ViewEffects();
6319
- const messageSystem = new MessageSystem();
6320
6043
  const subtitleSystem = new SubtitleSystem();
6321
6044
  const demoPlayback = new DemoPlaybackController();
6322
6045
  const demoHandler = new ClientNetworkHandler(imports);
@@ -6328,19 +6051,7 @@ function createClient(imports) {
6328
6051
  let pauseMenuFactory;
6329
6052
  let optionsFactory;
6330
6053
  const configStrings = new ClientConfigStrings();
6331
- demoHandler.setCallbacks({
6332
- onCenterPrint: (msg) => messageSystem.addCenterPrint(msg, demoHandler.latestFrame?.serverFrame ?? 0),
6333
- onPrint: (level, msg) => messageSystem.addNotify(msg, demoHandler.latestFrame?.serverFrame ?? 0),
6334
- onConfigString: (index, str3) => {
6335
- configStrings.set(index, str3);
6336
- cg.ParseConfigString(index, str3);
6337
- }
6338
- });
6339
- demoPlayback.setHandler(demoHandler);
6340
6054
  let latestFrame;
6341
- let lastRendered;
6342
- let lastView;
6343
- let camera;
6344
6055
  let clientInAutoDemo = false;
6345
6056
  const stateProvider = {
6346
6057
  get tickRate() {
@@ -6353,7 +6064,6 @@ function createClient(imports) {
6353
6064
  get serverFrame() {
6354
6065
  return demoHandler.latestServerFrame;
6355
6066
  },
6356
- // Corrected access
6357
6067
  get serverProtocol() {
6358
6068
  return 34;
6359
6069
  },
@@ -6368,6 +6078,18 @@ function createClient(imports) {
6368
6078
  };
6369
6079
  const cgameImport = createCGameImport(imports, stateProvider);
6370
6080
  const cg = (0, import_cgame2.GetCGameAPI)(cgameImport);
6081
+ demoHandler.setCallbacks({
6082
+ onCenterPrint: (msg) => cg.ParseCenterPrint(msg, 0, false),
6083
+ onPrint: (level, msg) => cg.NotifyMessage(0, msg, false),
6084
+ onConfigString: (index, str3) => {
6085
+ configStrings.set(index, str3);
6086
+ cg.ParseConfigString(index, str3);
6087
+ }
6088
+ });
6089
+ demoPlayback.setHandler(demoHandler);
6090
+ let lastRendered;
6091
+ let lastView;
6092
+ let camera;
6371
6093
  let fovValue = 90;
6372
6094
  let isZooming = false;
6373
6095
  if (imports.host) {
@@ -6623,6 +6345,9 @@ function createClient(imports) {
6623
6345
  },
6624
6346
  DrawHUD(stats, timeMs) {
6625
6347
  if (!imports.engine.renderer) return;
6348
+ const renderer = imports.engine.renderer;
6349
+ const width = renderer.width;
6350
+ const height = renderer.height;
6626
6351
  if (lastRendered && lastRendered.client) {
6627
6352
  const playerState = {
6628
6353
  origin: lastRendered.origin,
@@ -6636,30 +6361,38 @@ function createClient(imports) {
6636
6361
  damageIndicators: lastRendered.damageIndicators ?? [],
6637
6362
  blend: lastRendered.blend ?? [0, 0, 0, 0],
6638
6363
  pickupIcon: lastRendered.pickupIcon,
6639
- centerPrint: messageSystem["centerPrintMsg"]?.text,
6640
- // Hack to get text for legacy state? No, Draw_Hud uses messageSystem directly now.
6364
+ centerPrint: void 0,
6365
+ // Handled by CGame MessageSystem now
6641
6366
  notify: void 0,
6642
6367
  // Stubs for new fields
6643
- stats: [],
6368
+ // Ensure stats are safely initialized
6369
+ stats: lastRendered.stats ? [...lastRendered.stats] : new Array(32).fill(0),
6644
6370
  kick_angles: ZERO_VEC32,
6645
6371
  gunoffset: ZERO_VEC32,
6646
6372
  gunangles: ZERO_VEC32,
6647
6373
  gunindex: 0
6648
6374
  };
6649
- const playbackState = demoPlayback.getState();
6650
- const hudTimeMs = playbackState === PlaybackState.Playing || playbackState === PlaybackState.Paused ? (demoHandler.latestFrame?.serverFrame || 0) * 100 : timeMs;
6651
- Draw_Hud(
6652
- imports.engine.renderer,
6653
- playerState,
6654
- lastRendered.client,
6655
- lastRendered.health ?? 0,
6656
- lastRendered.armor ?? 0,
6657
- lastRendered.ammo ?? 0,
6658
- stats,
6659
- messageSystem,
6660
- subtitleSystem,
6661
- hudTimeMs
6375
+ playerState.stats[PlayerStat.STAT_HEALTH] = lastRendered.health ?? 0;
6376
+ playerState.stats[PlayerStat.STAT_AMMO] = lastRendered.ammo ?? 0;
6377
+ playerState.stats[PlayerStat.STAT_ARMOR] = lastRendered.armor ?? 0;
6378
+ renderer.begin2D();
6379
+ cg.DrawHUD(
6380
+ 0,
6381
+ // isplit
6382
+ null,
6383
+ // data
6384
+ { x: 0, y: 0, width, height },
6385
+ // hud_vrect
6386
+ { x: 0, y: 0, width, height },
6387
+ // hud_safe
6388
+ 1,
6389
+ // scale
6390
+ 0,
6391
+ // playernum
6392
+ playerState
6662
6393
  );
6394
+ subtitleSystem.drawSubtitles(renderer, timeMs);
6395
+ renderer.end2D();
6663
6396
  }
6664
6397
  if (menuSystem.isActive()) {
6665
6398
  Draw_Menu(imports.engine.renderer, menuSystem.getState(), imports.engine.renderer.width, imports.engine.renderer.height);
@@ -6703,12 +6436,10 @@ function createClient(imports) {
6703
6436
  },
6704
6437
  demoPlayback,
6705
6438
  ParseCenterPrint(msg) {
6706
- const timeMs = latestFrame?.timeMs ?? 0;
6707
- messageSystem.addCenterPrint(msg, timeMs);
6439
+ cg.ParseCenterPrint(msg, 0, false);
6708
6440
  },
6709
6441
  ParseNotify(msg) {
6710
- const timeMs = latestFrame?.timeMs ?? 0;
6711
- messageSystem.addNotify(msg, timeMs);
6442
+ cg.NotifyMessage(0, msg, false);
6712
6443
  },
6713
6444
  showSubtitle(text, soundName) {
6714
6445
  const timeMs = latestFrame?.timeMs ?? 0;