quake2ts 0.0.432 → 0.0.433

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 (51) hide show
  1. package/package.json +1 -1
  2. package/packages/cgame/dist/index.cjs +27 -17
  3. package/packages/cgame/dist/index.cjs.map +1 -1
  4. package/packages/cgame/dist/index.d.cts +2 -0
  5. package/packages/cgame/dist/index.d.ts +2 -0
  6. package/packages/cgame/dist/index.js +27 -17
  7. package/packages/cgame/dist/index.js.map +1 -1
  8. package/packages/client/dist/browser/index.global.js +16 -16
  9. package/packages/client/dist/browser/index.global.js.map +1 -1
  10. package/packages/client/dist/cjs/index.cjs +9 -0
  11. package/packages/client/dist/cjs/index.cjs.map +1 -1
  12. package/packages/client/dist/esm/index.js +9 -0
  13. package/packages/client/dist/esm/index.js.map +1 -1
  14. package/packages/client/dist/tsconfig.tsbuildinfo +1 -1
  15. package/packages/client/dist/types/index.d.ts.map +1 -1
  16. package/packages/client/dist/types/net/serverBrowser.d.ts +6 -0
  17. package/packages/client/dist/types/net/serverBrowser.d.ts.map +1 -1
  18. package/packages/game/dist/browser/index.global.js +4 -4
  19. package/packages/game/dist/browser/index.global.js.map +1 -1
  20. package/packages/game/dist/cjs/index.cjs +248 -77
  21. package/packages/game/dist/cjs/index.cjs.map +1 -1
  22. package/packages/game/dist/esm/index.js +248 -77
  23. package/packages/game/dist/esm/index.js.map +1 -1
  24. package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
  25. package/packages/game/dist/types/combat/weapons/chaingun.d.ts.map +1 -1
  26. package/packages/game/dist/types/combat/weapons/firing.d.ts +9 -0
  27. package/packages/game/dist/types/combat/weapons/firing.d.ts.map +1 -1
  28. package/packages/game/dist/types/combat/weapons/supershotgun.d.ts.map +1 -1
  29. package/packages/game/dist/types/entities/player.d.ts.map +1 -1
  30. package/packages/game/dist/types/entities/system.d.ts.map +1 -1
  31. package/packages/game/dist/types/imports.d.ts +2 -0
  32. package/packages/game/dist/types/imports.d.ts.map +1 -1
  33. package/packages/game/dist/types/index.d.ts +1 -0
  34. package/packages/game/dist/types/index.d.ts.map +1 -1
  35. package/packages/game/dist/types/inventory/playerInventory.d.ts +1 -0
  36. package/packages/game/dist/types/inventory/playerInventory.d.ts.map +1 -1
  37. package/packages/game/dist/types/modes/ctf/capture.d.ts +7 -0
  38. package/packages/game/dist/types/modes/ctf/capture.d.ts.map +1 -0
  39. package/packages/game/dist/types/modes/ctf/drop.d.ts +8 -0
  40. package/packages/game/dist/types/modes/ctf/drop.d.ts.map +1 -0
  41. package/packages/game/dist/types/modes/ctf/flag.d.ts.map +1 -1
  42. package/packages/game/dist/types/modes/ctf/integration.d.ts +4 -0
  43. package/packages/game/dist/types/modes/ctf/integration.d.ts.map +1 -0
  44. package/packages/game/dist/types/modes/ctf/pickup.d.ts +6 -0
  45. package/packages/game/dist/types/modes/ctf/pickup.d.ts.map +1 -0
  46. package/packages/game/dist/types/modes/ctf/state.d.ts +15 -0
  47. package/packages/game/dist/types/modes/ctf/state.d.ts.map +1 -0
  48. package/packages/server/dist/index.cjs +122 -1
  49. package/packages/server/dist/index.d.cts +4 -0
  50. package/packages/server/dist/index.d.ts +4 -0
  51. package/packages/server/dist/index.js +122 -1
@@ -4475,6 +4475,8 @@ var EntitySystem = class {
4475
4475
  configstring: () => {
4476
4476
  },
4477
4477
  serverCommand: () => {
4478
+ },
4479
+ setLagCompensation: () => {
4478
4480
  }
4479
4481
  };
4480
4482
  this.imports = { ...defaultImports, ...imports };
@@ -8151,6 +8153,7 @@ var FRAME_CHAINGUN_ACTIVATE_LAST = 4;
8151
8153
  var FRAME_CHAINGUN_FIRE_LAST = 21;
8152
8154
  var FRAME_CHAINGUN_IDLE_LAST = 52;
8153
8155
  var FRAME_CHAINGUN_DEACTIVATE_LAST = 61;
8156
+ var FRAME_CHAINGUN_SPINUP = 5;
8154
8157
  var FRAME_RAILGUN_ACTIVATE_LAST = 3;
8155
8158
  var FRAME_RAILGUN_FIRE_LAST = 18;
8156
8159
  var FRAME_RAILGUN_IDLE_LAST = 51;
@@ -8204,6 +8207,14 @@ var ANIM_DEATH = 3;
8204
8207
 
8205
8208
  // src/combat/weapons/firing.ts
8206
8209
  var random3 = createRandomGenerator();
8210
+ var DEFAULT_SHOTGUN_HSPREAD = 500;
8211
+ var DEFAULT_SHOTGUN_VSPREAD = 500;
8212
+ var DEFAULT_SSHOTGUN_HSPREAD = 1e3;
8213
+ var DEFAULT_SSHOTGUN_VSPREAD = 500;
8214
+ var DEFAULT_DEATHMATCH_SHOTGUN_COUNT = 12;
8215
+ var DEFAULT_SHOTGUN_COUNT = 12;
8216
+ var DEFAULT_SSHOTGUN_COUNT = 20;
8217
+ var BUTTON_ATTACK2 = 32;
8207
8218
  function applyKick(player, pitch, yaw = 0, kickOrigin = 0) {
8208
8219
  if (player.client) {
8209
8220
  player.client.kick_angles = { x: pitch, y: yaw, z: 0 };
@@ -8224,14 +8235,24 @@ function setPlayerAttackAnim(player) {
8224
8235
  }
8225
8236
  function fireHitscan(game, player, start, forward, damage, knockback, mod) {
8226
8237
  const end = { x: start.x + forward.x * 8192, y: start.y + forward.y * 8192, z: start.z + forward.z * 8192 };
8227
- const trace = game.trace(
8228
- start,
8229
- null,
8230
- null,
8231
- end,
8232
- player,
8233
- 0
8234
- );
8238
+ if (game.setLagCompensation && player.client) {
8239
+ game.setLagCompensation(true, player, player.client.ping);
8240
+ }
8241
+ let trace;
8242
+ try {
8243
+ trace = game.trace(
8244
+ start,
8245
+ null,
8246
+ null,
8247
+ end,
8248
+ player,
8249
+ 0
8250
+ );
8251
+ } finally {
8252
+ if (game.setLagCompensation) {
8253
+ game.setLagCompensation(false);
8254
+ }
8255
+ }
8235
8256
  if (trace.ent && trace.ent.takedamage) {
8236
8257
  T_Damage(
8237
8258
  trace.ent,
@@ -8254,31 +8275,40 @@ function fireHitscan(game, player, start, forward, damage, knockback, mod) {
8254
8275
  }
8255
8276
  }
8256
8277
  function fireMultiplePellets(game, player, start, forward, right, up, count, damage, knockback, hspread, vspread, mod) {
8257
- for (let i = 0; i < count; i++) {
8258
- const spread = addVec3(scaleVec3(right, random3.crandom() * hspread), scaleVec3(up, random3.crandom() * vspread));
8259
- const dir = addVec3(forward, spread);
8260
- const end = { x: start.x + dir.x * 8192, y: start.y + dir.y * 8192, z: start.z + dir.z * 8192 };
8261
- const trace = game.trace(start, null, null, end, player, 0);
8262
- if (trace.ent && trace.ent.takedamage) {
8263
- T_Damage(
8264
- trace.ent,
8265
- player,
8266
- player,
8267
- ZERO_VEC3,
8268
- trace.endpos,
8269
- trace.plane ? trace.plane.normal : ZERO_VEC3,
8270
- damage,
8271
- knockback,
8272
- 16 /* BULLET */,
8273
- mod,
8274
- game.time,
8275
- game.multicast
8276
- );
8277
- } else if (trace.plane) {
8278
- if (random3.frandom() > 0.9) {
8279
- game.multicast(trace.endpos, 1 /* Pvs */, ServerCommand.temp_entity, TempEntity.GUNSHOT, trace.endpos, trace.plane.normal);
8278
+ if (game.setLagCompensation && player.client) {
8279
+ game.setLagCompensation(true, player, player.client.ping);
8280
+ }
8281
+ try {
8282
+ for (let i = 0; i < count; i++) {
8283
+ const spread = addVec3(scaleVec3(right, random3.crandom() * hspread), scaleVec3(up, random3.crandom() * vspread));
8284
+ const dir = addVec3(forward, spread);
8285
+ const end = { x: start.x + dir.x * 8192, y: start.y + dir.y * 8192, z: start.z + dir.z * 8192 };
8286
+ const trace = game.trace(start, null, null, end, player, 0);
8287
+ if (trace.ent && trace.ent.takedamage) {
8288
+ T_Damage(
8289
+ trace.ent,
8290
+ player,
8291
+ player,
8292
+ ZERO_VEC3,
8293
+ trace.endpos,
8294
+ trace.plane ? trace.plane.normal : ZERO_VEC3,
8295
+ damage,
8296
+ knockback,
8297
+ 16 /* BULLET */,
8298
+ mod,
8299
+ game.time,
8300
+ game.multicast
8301
+ );
8302
+ } else if (trace.plane) {
8303
+ if (random3.frandom() > 0.9) {
8304
+ game.multicast(trace.endpos, 1 /* Pvs */, ServerCommand.temp_entity, TempEntity.GUNSHOT, trace.endpos, trace.plane.normal);
8305
+ }
8280
8306
  }
8281
8307
  }
8308
+ } finally {
8309
+ if (game.setLagCompensation) {
8310
+ game.setLagCompensation(false);
8311
+ }
8282
8312
  }
8283
8313
  }
8284
8314
  function fireRailgun(game, player, start, forward, damage, knockback) {
@@ -8288,33 +8318,42 @@ function fireRailgun(game, player, start, forward, damage, knockback) {
8288
8318
  let ignore = player;
8289
8319
  let count = 0;
8290
8320
  let finalEnd = end;
8291
- while (count < 16) {
8292
- count++;
8293
- const trace = game.trace(currentStart, null, null, end, ignore, 0);
8294
- finalEnd = trace.endpos;
8295
- if (trace.fraction >= 1) {
8296
- break;
8297
- }
8298
- if (trace.ent && trace.ent.takedamage) {
8299
- T_Damage(
8300
- trace.ent,
8301
- player,
8302
- player,
8303
- ZERO_VEC3,
8304
- trace.endpos,
8305
- trace.plane ? trace.plane.normal : ZERO_VEC3,
8306
- damage,
8307
- knockback,
8308
- 4 /* ENERGY */,
8309
- 11 /* RAILGUN */,
8310
- game.time,
8311
- game.multicast
8312
- );
8321
+ if (game.setLagCompensation && player.client) {
8322
+ game.setLagCompensation(true, player, player.client.ping);
8323
+ }
8324
+ try {
8325
+ while (count < 16) {
8326
+ count++;
8327
+ const trace = game.trace(currentStart, null, null, end, ignore, 0);
8328
+ finalEnd = trace.endpos;
8329
+ if (trace.fraction >= 1) {
8330
+ break;
8331
+ }
8332
+ if (trace.ent && trace.ent.takedamage) {
8333
+ T_Damage(
8334
+ trace.ent,
8335
+ player,
8336
+ player,
8337
+ ZERO_VEC3,
8338
+ trace.endpos,
8339
+ trace.plane ? trace.plane.normal : ZERO_VEC3,
8340
+ damage,
8341
+ knockback,
8342
+ 4 /* ENERGY */,
8343
+ 11 /* RAILGUN */,
8344
+ game.time,
8345
+ game.multicast
8346
+ );
8347
+ }
8348
+ ignore = trace.ent;
8349
+ currentStart = trace.endpos;
8350
+ if (!trace.ent || trace.ent === game.entities.world) {
8351
+ break;
8352
+ }
8313
8353
  }
8314
- ignore = trace.ent;
8315
- currentStart = trace.endpos;
8316
- if (!trace.ent || trace.ent === game.entities.world) {
8317
- break;
8354
+ } finally {
8355
+ if (game.setLagCompensation) {
8356
+ game.setLagCompensation(false);
8318
8357
  }
8319
8358
  }
8320
8359
  game.multicast(originalStart, 2 /* Phs */, ServerCommand.temp_entity, TempEntity.RAILTRAIL, originalStart, finalEnd);
@@ -8331,7 +8370,8 @@ function fireShotgun(game, player) {
8331
8370
  setPlayerAttackAnim(player);
8332
8371
  const { forward, right, up } = angleVectors(player.angles);
8333
8372
  const source = P_ProjectSource(game, player, { x: 8, y: 8, z: -8 }, forward, right, up);
8334
- fireMultiplePellets(game, player, source, forward, right, up, 12, 4, 1, 500, 500, 2 /* SHOTGUN */);
8373
+ const count = game.deathmatch ? DEFAULT_DEATHMATCH_SHOTGUN_COUNT : DEFAULT_SHOTGUN_COUNT;
8374
+ fireMultiplePellets(game, player, source, forward, right, up, count, 4, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, 2 /* SHOTGUN */);
8335
8375
  }
8336
8376
  function fireSuperShotgun(game, player) {
8337
8377
  if (!player.client) return;
@@ -8339,16 +8379,26 @@ function fireSuperShotgun(game, player) {
8339
8379
  if (inventory.ammo.counts[AmmoType.Shells] < 2) {
8340
8380
  return;
8341
8381
  }
8382
+ const isPrecision = (player.client.buttons & BUTTON_ATTACK2) !== 0;
8342
8383
  inventory.ammo.counts[AmmoType.Shells] -= 2;
8343
8384
  game.multicast(player.origin, 1 /* Pvs */, ServerCommand.muzzleflash, player.index, MZ_SSHOTGUN);
8344
8385
  applyKick(player, -4, 0, -4);
8345
8386
  setPlayerAttackAnim(player);
8346
8387
  const { forward, right, up } = angleVectors(player.angles);
8347
8388
  const source = P_ProjectSource(game, player, { x: 8, y: 8, z: -8 }, forward, right, up);
8389
+ const count = DEFAULT_SSHOTGUN_COUNT / 2;
8390
+ let hspread = DEFAULT_SSHOTGUN_HSPREAD;
8391
+ let vspread = DEFAULT_SSHOTGUN_VSPREAD;
8392
+ let damage = 6;
8393
+ if (isPrecision) {
8394
+ hspread = 300;
8395
+ vspread = 150;
8396
+ damage = 4;
8397
+ }
8348
8398
  const { forward: forward1, right: right1, up: up1 } = angleVectors({ ...player.angles, y: player.angles.y - 5 });
8349
- fireMultiplePellets(game, player, source, forward1, right1, up1, 10, 6, 1, 700, 700, 3 /* SSHOTGUN */);
8399
+ fireMultiplePellets(game, player, source, forward1, right1, up1, count, damage, 1, hspread, vspread, 3 /* SSHOTGUN */);
8350
8400
  const { forward: forward2, right: right2, up: up2 } = angleVectors({ ...player.angles, y: player.angles.y + 5 });
8351
- fireMultiplePellets(game, player, source, forward2, right2, up2, 10, 6, 1, 700, 700, 3 /* SSHOTGUN */);
8401
+ fireMultiplePellets(game, player, source, forward2, right2, up2, count, damage, 1, hspread, vspread, 3 /* SSHOTGUN */);
8352
8402
  }
8353
8403
  function fireMachinegun(game, player) {
8354
8404
  if (!player.client) return;
@@ -8737,12 +8787,36 @@ function Throw_Generic(ent, FRAME_FIRE_LAST, FRAME_IDLE_LAST, FRAME_THROW_FIRST,
8737
8787
 
8738
8788
  // src/combat/weapons/chaingun.ts
8739
8789
  var CHAINGUN_PAUSE_FRAMES = [38, 43, 51, 61];
8790
+ var BUTTON_ATTACK22 = 32;
8740
8791
  function chaingunThink(player, sys) {
8741
8792
  const weaponState = getWeaponState(player.client.weaponStates, WeaponId.Chaingun);
8742
- if (!(player.client.buttons & BUTTON_ATTACK) && weaponState.spinupCount && weaponState.spinupCount > 0) {
8793
+ const client = player.client;
8794
+ if (!(client.buttons & BUTTON_ATTACK) && !(client.buttons & BUTTON_ATTACK22) && weaponState.spinupCount && weaponState.spinupCount > 0) {
8743
8795
  sys.sound(player, 0, "weapons/chngnd1a.wav", 1, 0, 0);
8744
8796
  weaponState.spinupCount = 0;
8745
8797
  }
8798
+ if (client.buttons & BUTTON_ATTACK22 && !(client.buttons & BUTTON_ATTACK)) {
8799
+ const spinupCount = (weaponState.spinupCount || 0) + 1;
8800
+ weaponState.spinupCount = spinupCount;
8801
+ const currentTime = sys.game ? sys.game.time : sys.timeSeconds * 1e3;
8802
+ weaponState.lastFireTime = currentTime;
8803
+ if (spinupCount > FRAME_CHAINGUN_SPINUP) {
8804
+ sys.sound(player, 0, "weapons/chngnl1a.wav", 1, 0, 0);
8805
+ } else {
8806
+ if (spinupCount === 1) {
8807
+ sys.sound(player, 0, "weapons/chngnu1a.wav", 1, 0, 0);
8808
+ }
8809
+ }
8810
+ if (client.gun_frame < FRAME_CHAINGUN_SPINUP || client.gun_frame > FRAME_CHAINGUN_FIRE_LAST) {
8811
+ client.gun_frame = FRAME_CHAINGUN_SPINUP;
8812
+ } else {
8813
+ client.gun_frame++;
8814
+ if (client.gun_frame > FRAME_CHAINGUN_FIRE_LAST) {
8815
+ client.gun_frame = FRAME_CHAINGUN_SPINUP;
8816
+ }
8817
+ }
8818
+ return;
8819
+ }
8746
8820
  Weapon_Repeating(
8747
8821
  player,
8748
8822
  FRAME_CHAINGUN_ACTIVATE_LAST,
@@ -8773,9 +8847,13 @@ function shotgunThink(player, sys) {
8773
8847
  }
8774
8848
 
8775
8849
  // src/combat/weapons/supershotgun.ts
8850
+ init_state();
8851
+ init_playerInventory();
8776
8852
  var SSHOTGUN_PAUSE_FRAMES = [29, 42, 57];
8777
8853
  var SSHOTGUN_FIRE_FRAMES = [22, 28];
8778
8854
  function superShotgunThink(player, sys) {
8855
+ const client = player.client;
8856
+ const weaponState = getWeaponState(client.weaponStates, WeaponId.SuperShotgun);
8779
8857
  Weapon_Generic(
8780
8858
  player,
8781
8859
  FRAME_SSHOTGUN_ACTIVATE_LAST,
@@ -9134,9 +9212,9 @@ function Weapon_ChainFist(player, sys) {
9134
9212
  fireChainfist(game, ent, inventory, weaponState, start, forward);
9135
9213
  if (ent.client) {
9136
9214
  const client = ent.client;
9137
- const BUTTON_ATTACK2 = 1;
9215
+ const BUTTON_ATTACK3 = 1;
9138
9216
  const buttons = client.buttons;
9139
- if (buttons & BUTTON_ATTACK2) {
9217
+ if (buttons & BUTTON_ATTACK3) {
9140
9218
  if (client.gun_frame === 12) client.gun_frame = 14;
9141
9219
  else if (client.gun_frame === 22) client.gun_frame = 24;
9142
9220
  else if (client.gun_frame >= 32) client.gun_frame = 7;
@@ -9755,32 +9833,68 @@ function createPowerArmorPickupEntity(game, item) {
9755
9833
 
9756
9834
  // src/modes/ctf/flag.ts
9757
9835
  init_playerInventory();
9836
+
9837
+ // src/modes/ctf/state.ts
9838
+ function setFlagState(flag, newState, context) {
9839
+ flag.flagState = newState;
9840
+ }
9841
+
9842
+ // src/modes/ctf/flag.ts
9758
9843
  function createFlagPickupEntity(game, flagItem) {
9759
- const drop = (self, context) => {
9760
- };
9844
+ const isRed = flagItem.team === "red";
9761
9845
  const respawn = (self) => {
9846
+ setFlagState(self, 0 /* AT_BASE */, game.entities);
9762
9847
  self.solid = 1 /* Trigger */;
9848
+ self.model = isRed ? "players/male/flag1.md2" : "players/male/flag2.md2";
9849
+ self.origin = { ...self.baseOrigin };
9850
+ self.svflags &= ~1;
9763
9851
  };
9764
9852
  return {
9765
9853
  classname: flagItem.id,
9766
9854
  solid: 1 /* Trigger */,
9767
- model: flagItem.team === "red" ? "players/male/flag1.md2" : "players/male/flag2.md2",
9768
- // Note: Models might need adjustment based on how Q2 handles skins for flags
9769
- // Original: "players/male/flag1.md2" (red) "players/male/flag2.md2" (blue)
9770
- // Usually it's just one model with skin change, but Q2 uses separate models for dropped flags often?
9771
- // Checking g_ctf.c: SP_item_flag_team1 sets ent->s.modelindex = gi.modelindex ("players/male/flag1.md2");
9772
- touch: (self, other) => {
9855
+ model: isRed ? "players/male/flag1.md2" : "players/male/flag2.md2",
9856
+ movetype: 0 /* None */,
9857
+ // Base flag is stationary
9858
+ // Initialize extended properties
9859
+ // We cast this object to Partial<Entity> which includes FlagEntity props if we extend definition
9860
+ // or we just assign them dynamically.
9861
+ // For type safety, we might need to cast to any here or define these props on Entity.
9862
+ // Since we can't easily modify Entity definition right now without a big refactor,
9863
+ // we assume runtime extensions are allowed or these are custom fields.
9864
+ flagState: 0 /* AT_BASE */,
9865
+ flagTeam: flagItem.team,
9866
+ baseOrigin: { x: 0, y: 0, z: 0 },
9867
+ touch: (selfEntity, other) => {
9868
+ const self = selfEntity;
9773
9869
  if (!other || !other.client) {
9774
9870
  return;
9775
9871
  }
9776
- if (pickupFlag(other.client, flagItem, game.time * 1e3)) {
9777
- game.sound?.(other, 0, "ctf/flagpk.wav", 1, 1, 0);
9778
- game.centerprintf?.(other, `You got the ${flagItem.name}`);
9779
- self.solid = 0 /* Not */;
9780
- self.model = void 0;
9872
+ const playerTeam = other.client.team || "red";
9873
+ const sameTeam = self.flagTeam === playerTeam;
9874
+ if (sameTeam) {
9875
+ if (self.flagState === 0 /* AT_BASE */) {
9876
+ return;
9877
+ }
9878
+ if (self.flagState === 2 /* DROPPED */) {
9879
+ game.sound?.(other, 0, "ctf/flagret.wav", 1, 1, 0);
9880
+ game.centerprintf?.(other, `You returned the ${flagItem.name}!`);
9881
+ respawn(self);
9882
+ }
9883
+ } else {
9884
+ if (pickupFlag(other.client, flagItem, game.time * 1e3)) {
9885
+ game.sound?.(other, 0, "ctf/flagpk.wav", 1, 1, 0);
9886
+ game.centerprintf?.(other, `You got the ${flagItem.name}!`);
9887
+ setFlagState(self, 1 /* CARRIED */, game.entities);
9888
+ self.solid = 0 /* Not */;
9889
+ self.model = void 0;
9890
+ self.owner = other;
9891
+ }
9781
9892
  }
9782
9893
  },
9783
- think: (self, context) => {
9894
+ think: (selfEntity, context) => {
9895
+ const self = selfEntity;
9896
+ if (self.flagState === 2 /* DROPPED */) {
9897
+ }
9784
9898
  }
9785
9899
  };
9786
9900
  }
@@ -24746,6 +24860,55 @@ function ClientObituary(self, inflictor, attacker, mod, sys) {
24746
24860
  }
24747
24861
  }
24748
24862
 
24863
+ // src/modes/ctf/integration.ts
24864
+ init_playerInventory();
24865
+
24866
+ // src/modes/ctf/drop.ts
24867
+ function dropFlag(flag, origin, game, context) {
24868
+ if (flag.flagState !== 1 /* CARRIED */) {
24869
+ return;
24870
+ }
24871
+ setFlagState(flag, 2 /* DROPPED */, context);
24872
+ flag.origin = { x: origin.x, y: origin.y, z: origin.z + 24 };
24873
+ flag.owner = null;
24874
+ flag.solid = 1 /* Trigger */;
24875
+ flag.model = flag.flagTeam === "red" ? "players/male/flag1.md2" : "players/male/flag2.md2";
24876
+ const time = context.timeSeconds ?? game.time;
24877
+ flag.nextthink = time + 30;
24878
+ game.centerprintf?.(flag, `The ${flag.flagTeam} flag was dropped!`);
24879
+ flag.think = (selfEntity, ctx) => flagThink(selfEntity, ctx, game);
24880
+ }
24881
+ function flagThink(self, context, game) {
24882
+ const flag = self;
24883
+ if (flag.flagState === 2 /* DROPPED */) {
24884
+ game.sound?.(flag, 0, "ctf/flagret.wav", 1, 1, 0);
24885
+ game.centerprintf?.(flag, `The ${flag.flagTeam} flag returned to base!`);
24886
+ setFlagState(flag, 0 /* AT_BASE */, context);
24887
+ flag.origin = { ...flag.baseOrigin };
24888
+ flag.solid = 1 /* Trigger */;
24889
+ flag.nextthink = -1;
24890
+ }
24891
+ }
24892
+
24893
+ // src/modes/ctf/integration.ts
24894
+ function checkPlayerFlagDrop(player, sys) {
24895
+ if (!player.client) return;
24896
+ const hasRedFlag = hasKey(player.client.inventory, "key_red_flag" /* RedFlag */);
24897
+ const hasBlueFlag = hasKey(player.client.inventory, "key_blue_flag" /* BlueFlag */);
24898
+ if (!hasRedFlag && !hasBlueFlag) return;
24899
+ sys.forEachEntity((ent) => {
24900
+ const flag = ent;
24901
+ if ((flag.classname === "item_flag_team1" || flag.classname === "item_flag_team2") && flag.owner === player) {
24902
+ const game = sys._game;
24903
+ if (game) {
24904
+ dropFlag(flag, player.origin, game, sys);
24905
+ player.client.inventory.keys.delete("key_red_flag" /* RedFlag */);
24906
+ player.client.inventory.keys.delete("key_blue_flag" /* BlueFlag */);
24907
+ }
24908
+ }
24909
+ });
24910
+ }
24911
+
24749
24912
  // src/entities/player.ts
24750
24913
  function P_PlayerThink(ent, sys) {
24751
24914
  if (!ent.client) return;
@@ -24826,6 +24989,9 @@ function player_die(self, inflictor, attacker, damage, point, mod, sys) {
24826
24989
  self.solid = 0 /* Not */;
24827
24990
  self.movetype = 7 /* Toss */;
24828
24991
  self.takedamage = false;
24992
+ if (sys) {
24993
+ checkPlayerFlagDrop(self, sys);
24994
+ }
24829
24995
  if (self.health < -40 && sys) {
24830
24996
  throwGibs(sys, self.origin, damage);
24831
24997
  return;
@@ -25592,6 +25758,11 @@ function createGame(imports, engine, options) {
25592
25758
  serverCommand(cmd) {
25593
25759
  serverCommand(cmd);
25594
25760
  },
25761
+ setLagCompensation(active, client, lagMs) {
25762
+ if (engine.setLagCompensation) {
25763
+ engine.setLagCompensation(active, client, lagMs);
25764
+ }
25765
+ },
25595
25766
  get time() {
25596
25767
  return levelClock.current.timeSeconds;
25597
25768
  },