quake2ts 0.0.446 → 0.0.448

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 (34) 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/tsconfig.tsbuildinfo +1 -1
  5. package/packages/engine/dist/tsconfig.tsbuildinfo +1 -1
  6. package/packages/engine/dist/types/editor/bsp-inspector.d.ts +6 -1
  7. package/packages/engine/dist/types/editor/bsp-inspector.d.ts.map +1 -1
  8. package/packages/engine/dist/types/render/renderer.d.ts +2 -0
  9. package/packages/engine/dist/types/render/renderer.d.ts.map +1 -1
  10. package/packages/game/dist/browser/index.global.js +4 -4
  11. package/packages/game/dist/browser/index.global.js.map +1 -1
  12. package/packages/game/dist/cjs/index.cjs +145 -56
  13. package/packages/game/dist/cjs/index.cjs.map +1 -1
  14. package/packages/game/dist/esm/index.js +144 -56
  15. package/packages/game/dist/esm/index.js.map +1 -1
  16. package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
  17. package/packages/game/dist/types/ai/targeting.d.ts +1 -0
  18. package/packages/game/dist/types/ai/targeting.d.ts.map +1 -1
  19. package/packages/game/dist/types/combat/obituary.d.ts.map +1 -1
  20. package/packages/game/dist/types/entities/items/ammo.d.ts.map +1 -1
  21. package/packages/game/dist/types/entities/items/armor.d.ts.map +1 -1
  22. package/packages/game/dist/types/entities/items/common.d.ts +5 -0
  23. package/packages/game/dist/types/entities/items/common.d.ts.map +1 -0
  24. package/packages/game/dist/types/entities/items/health.d.ts.map +1 -1
  25. package/packages/game/dist/types/entities/items/powerups.d.ts.map +1 -1
  26. package/packages/game/dist/types/entities/items/weapons.d.ts.map +1 -1
  27. package/packages/game/dist/types/entities/player.d.ts.map +1 -1
  28. package/packages/game/dist/types/entities/projectiles/prox.d.ts.map +1 -1
  29. package/packages/game/dist/types/entities/spawn.d.ts +2 -0
  30. package/packages/game/dist/types/entities/spawn.d.ts.map +1 -1
  31. package/packages/game/dist/types/entities/system.d.ts +2 -0
  32. package/packages/game/dist/types/entities/system.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
@@ -2462,6 +2462,7 @@ var init_switching = __esm({
2462
2462
  var index_exports = {};
2463
2463
  __export(index_exports, {
2464
2464
  AIFlags: () => AIFlags,
2465
+ AI_GetSightClient: () => AI_GetSightClient,
2465
2466
  AMMO_TYPE_COUNT: () => AMMO_TYPE_COUNT,
2466
2467
  ARMOR_INFO: () => ARMOR_INFO,
2467
2468
  ARMOR_ITEMS: () => ARMOR_ITEMS,
@@ -3510,6 +3511,24 @@ function classifyClientVisibility(self, other, level, trace) {
3510
3511
  }
3511
3512
  return true;
3512
3513
  }
3514
+ function AI_GetSightClient(self, context, trace) {
3515
+ if ((self.monsterinfo.aiflags & 1024 /* NoStep */) !== 0) {
3516
+ return null;
3517
+ }
3518
+ for (let i = 1; i <= context.maxClients; i++) {
3519
+ const ent = context.entities[i];
3520
+ if (!ent || !ent.inUse || ent.health <= 0) {
3521
+ continue;
3522
+ }
3523
+ if ((ent.flags & FL_NOTARGET) !== 0) {
3524
+ continue;
3525
+ }
3526
+ if (visible(self, ent, trace, { throughGlass: false })) {
3527
+ return ent;
3528
+ }
3529
+ }
3530
+ return null;
3531
+ }
3513
3532
  function updateSoundChase(self, client, level, hearability, trace) {
3514
3533
  if ((self.spawnflags & SPAWNFLAG_MONSTER_AMBUSH) !== 0) {
3515
3534
  if (!visible(self, client, trace)) return false;
@@ -4962,6 +4981,18 @@ var EntitySystem = class {
4962
4981
  get game() {
4963
4982
  return this._game;
4964
4983
  }
4984
+ get maxClients() {
4985
+ return 32;
4986
+ }
4987
+ get entities() {
4988
+ const arr = new Array(this.pool.capacity + 1).fill(null);
4989
+ for (const ent of this.pool) {
4990
+ if (ent.index >= 0 && ent.index < arr.length) {
4991
+ arr[ent.index] = ent;
4992
+ }
4993
+ }
4994
+ return arr;
4995
+ }
4965
4996
  get world() {
4966
4997
  return this.pool.world;
4967
4998
  }
@@ -10042,11 +10073,35 @@ var FLAG_ITEMS = {
10042
10073
  }
10043
10074
  };
10044
10075
 
10045
- // src/entities/items/weapons.ts
10046
- function createWeaponPickupEntity(game, weaponItem) {
10047
- const respawn = (self) => {
10076
+ // src/entities/items/common.ts
10077
+ init_esm();
10078
+ function handleItemPickup(game, self, other, respawnTime = 30) {
10079
+ if (!game.deathmatch) {
10080
+ game.entities.free(self);
10081
+ return;
10082
+ }
10083
+ self.solid = 0 /* Not */;
10084
+ self.modelindex = 0;
10085
+ self.svflags |= 1 /* NoClient */;
10086
+ self.nextthink = game.time + respawnTime;
10087
+ game.entities.scheduleThink(self, self.nextthink);
10088
+ }
10089
+ function createItemRespawnFunction(game, originalModel) {
10090
+ let cachedIndex = 0;
10091
+ return (self) => {
10092
+ if (!cachedIndex) {
10093
+ cachedIndex = game.entities.modelIndex(originalModel);
10094
+ }
10048
10095
  self.solid = 1 /* Trigger */;
10096
+ self.modelindex = cachedIndex;
10097
+ self.svflags &= ~1 /* NoClient */;
10098
+ game.multicast(self.origin, 1 /* Pvs */, ServerCommand.sound, 0, "items/respawn.wav", 1, 0, 0);
10049
10099
  };
10100
+ }
10101
+
10102
+ // src/entities/items/weapons.ts
10103
+ function createWeaponPickupEntity(game, weaponItem) {
10104
+ const modelName = `models/items/${weaponItem.id.replace("weapon_", "")}/tris.md2`;
10050
10105
  return {
10051
10106
  classname: weaponItem.id,
10052
10107
  solid: 1 /* Trigger */,
@@ -10057,22 +10112,16 @@ function createWeaponPickupEntity(game, weaponItem) {
10057
10112
  if (pickupWeapon(other.client.inventory, weaponItem, game.time * 1e3)) {
10058
10113
  game.sound?.(other, 0, "items/pkup.wav", 1, 1, 0);
10059
10114
  game.centerprintf?.(other, `You got the ${weaponItem.name}`);
10060
- self.solid = 0 /* Not */;
10061
- if (game.deathmatch) {
10062
- self.nextthink = game.time + 30;
10063
- game.entities.scheduleThink(self, self.nextthink);
10064
- }
10115
+ handleItemPickup(game, self, other);
10065
10116
  }
10066
10117
  },
10067
- think: respawn
10118
+ think: createItemRespawnFunction(game, modelName)
10068
10119
  };
10069
10120
  }
10070
10121
 
10071
10122
  // src/entities/items/health.ts
10072
10123
  function createHealthPickupEntity(game, healthItem) {
10073
- const respawn = (self) => {
10074
- self.solid = 1 /* Trigger */;
10075
- };
10124
+ const modelName = `models/items/healing/${healthItem.id.replace("item_health_", "")}/tris.md2`;
10076
10125
  return {
10077
10126
  classname: healthItem.id,
10078
10127
  solid: 1 /* Trigger */,
@@ -10087,22 +10136,16 @@ function createHealthPickupEntity(game, healthItem) {
10087
10136
  }
10088
10137
  game.sound?.(other, 0, "items/pkup.wav", 1, 1, 0);
10089
10138
  game.centerprintf?.(other, `You got the ${healthItem.name}`);
10090
- self.solid = 0 /* Not */;
10091
- if (game.deathmatch) {
10092
- self.nextthink = game.time + 30;
10093
- game.entities.scheduleThink(self, self.nextthink);
10094
- }
10139
+ handleItemPickup(game, self, other);
10095
10140
  }
10096
10141
  },
10097
- think: respawn
10142
+ think: createItemRespawnFunction(game, modelName)
10098
10143
  };
10099
10144
  }
10100
10145
 
10101
10146
  // src/entities/items/armor.ts
10102
10147
  function createArmorPickupEntity(game, armorItem) {
10103
- const respawn = (self) => {
10104
- self.solid = 1 /* Trigger */;
10105
- };
10148
+ const modelName = `models/items/armor/${armorItem.id.replace("item_armor_", "")}/tris.md2`;
10106
10149
  return {
10107
10150
  classname: armorItem.id,
10108
10151
  solid: 1 /* Trigger */,
@@ -10113,22 +10156,17 @@ function createArmorPickupEntity(game, armorItem) {
10113
10156
  if (pickupArmor(other.client.inventory, armorItem, game.time * 1e3)) {
10114
10157
  game.sound?.(other, 0, "items/pkup.wav", 1, 1, 0);
10115
10158
  game.centerprintf?.(other, `You got the ${armorItem.name}`);
10116
- self.solid = 0 /* Not */;
10117
- if (game.deathmatch) {
10118
- self.nextthink = game.time + 30;
10119
- game.entities.scheduleThink(self, self.nextthink);
10120
- }
10159
+ handleItemPickup(game, self, other);
10121
10160
  }
10122
10161
  },
10123
- think: respawn
10162
+ think: createItemRespawnFunction(game, modelName)
10124
10163
  };
10125
10164
  }
10126
10165
 
10127
10166
  // src/entities/items/powerups.ts
10128
10167
  function createPowerupPickupEntity(game, powerupItem) {
10129
- const respawn = (self) => {
10130
- self.solid = 1 /* Trigger */;
10131
- };
10168
+ const respawnTime = powerupItem.id === "item_quad" || powerupItem.id === "item_invulnerability" ? 60 : 30;
10169
+ const modelName = `models/items/powerups/${powerupItem.id.replace("item_", "")}/tris.md2`;
10132
10170
  return {
10133
10171
  classname: powerupItem.id,
10134
10172
  solid: 1 /* Trigger */,
@@ -10139,14 +10177,10 @@ function createPowerupPickupEntity(game, powerupItem) {
10139
10177
  if (pickupPowerup(other.client, powerupItem, game.time * 1e3)) {
10140
10178
  game.sound?.(other, 0, "items/pkup.wav", 1, 1, 0);
10141
10179
  game.centerprintf?.(other, `You got the ${powerupItem.name}`);
10142
- self.solid = 0 /* Not */;
10143
- if (game.deathmatch) {
10144
- self.nextthink = game.time + 30;
10145
- game.entities.scheduleThink(self, self.nextthink);
10146
- }
10180
+ handleItemPickup(game, self, other, respawnTime);
10147
10181
  }
10148
10182
  },
10149
- think: respawn
10183
+ think: createItemRespawnFunction(game, modelName)
10150
10184
  };
10151
10185
  }
10152
10186
 
@@ -10192,9 +10226,7 @@ var AMMO_DISPLAY_NAMES = {
10192
10226
  };
10193
10227
  function createAmmoPickupEntity(game, itemId) {
10194
10228
  const def = getAmmoItemDefinition(itemId);
10195
- const respawn = (self) => {
10196
- self.solid = 1 /* Trigger */;
10197
- };
10229
+ const modelName = `models/items/ammo/${itemId.replace("ammo_", "")}/tris.md2`;
10198
10230
  return {
10199
10231
  classname: itemId,
10200
10232
  solid: 1 /* Trigger */,
@@ -10207,14 +10239,10 @@ function createAmmoPickupEntity(game, itemId) {
10207
10239
  game.sound?.(other, 0, "items/pkup.wav", 1, 1, 0);
10208
10240
  const name = AMMO_DISPLAY_NAMES[itemId] || itemId.replace("ammo_", "");
10209
10241
  game.centerprintf?.(other, `You got ${def.quantity} ${name}`);
10210
- self.solid = 0 /* Not */;
10211
- if (game.deathmatch) {
10212
- self.nextthink = game.time + 30;
10213
- game.entities.scheduleThink(self, self.nextthink);
10214
- }
10242
+ handleItemPickup(game, self, other);
10215
10243
  }
10216
10244
  },
10217
- think: respawn
10245
+ think: createItemRespawnFunction(game, modelName)
10218
10246
  };
10219
10247
  }
10220
10248
 
@@ -24033,6 +24061,21 @@ function spawnEntitiesFromText(text, options) {
24033
24061
  }
24034
24062
  return spawned;
24035
24063
  }
24064
+ function SelectDeathmatchSpawnPoint(entities) {
24065
+ const spots = entities.findByClassname("info_player_deathmatch");
24066
+ if (spots.length === 0) {
24067
+ return void 0;
24068
+ }
24069
+ const index = Math.floor(entities.rng.frandom() * spots.length);
24070
+ return spots[index];
24071
+ }
24072
+ function SelectSpawnPoint(entities) {
24073
+ if (entities.deathmatch) {
24074
+ const spot = SelectDeathmatchSpawnPoint(entities);
24075
+ if (spot) return spot;
24076
+ }
24077
+ return findPlayerStart(entities);
24078
+ }
24036
24079
  function findPlayerStart(entities) {
24037
24080
  return entities.find(
24038
24081
  (entity) => entity.classname === "info_player_start"
@@ -25200,26 +25243,37 @@ function ClientObituary(self, inflictor, attacker, mod, sys) {
25200
25243
  }
25201
25244
  if (mod === 24 /* SUICIDE */) {
25202
25245
  message = `${friendlyName} suicides.`;
25246
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25203
25247
  } else if (mod === 23 /* FALLING */) {
25204
25248
  message = `${friendlyName} cratered.`;
25249
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25205
25250
  } else if (mod === 20 /* CRUSH */) {
25206
25251
  message = `${friendlyName} was squished.`;
25252
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25207
25253
  } else if (mod === 17 /* WATER */) {
25208
25254
  message = `${friendlyName} sank like a rock.`;
25255
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25209
25256
  } else if (mod === 18 /* SLIME */) {
25210
25257
  message = `${friendlyName} melted.`;
25258
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25211
25259
  } else if (mod === 19 /* LAVA */) {
25212
25260
  message = `${friendlyName} does a back flip into the lava.`;
25261
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25213
25262
  } else if (mod === 26 /* EXPLOSIVE */) {
25214
25263
  message = `${friendlyName} blew up.`;
25264
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25215
25265
  } else if (mod === 31 /* TARGET_LASER */) {
25216
25266
  message = `${friendlyName} saw the light.`;
25267
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25217
25268
  } else if (mod === 34 /* TARGET_BLASTER */) {
25218
25269
  message = `${friendlyName} got blasted.`;
25270
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25219
25271
  } else if (mod === 28 /* BOMB */) {
25220
25272
  message = `${friendlyName} was bombed.`;
25273
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25221
25274
  } else if (attacker && attacker.classname === "player") {
25222
25275
  if (self === attacker) {
25276
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25223
25277
  switch (mod) {
25224
25278
  case 6 /* GRENADE */:
25225
25279
  case 7 /* G_SPLASH */:
@@ -25248,6 +25302,9 @@ function ClientObituary(self, inflictor, attacker, mod, sys) {
25248
25302
  break;
25249
25303
  }
25250
25304
  } else {
25305
+ if (attacker.client) {
25306
+ attacker.client.score = (attacker.client.score || 0) + 1;
25307
+ }
25251
25308
  const attackerName = "Enemy";
25252
25309
  switch (mod) {
25253
25310
  case 1 /* BLASTER */:
@@ -25480,6 +25537,18 @@ function player_die(self, inflictor, attacker, damage, point, mod, sys) {
25480
25537
  }
25481
25538
  function player_think(self, sys) {
25482
25539
  if (!self.client) return;
25540
+ if (self.deadflag) {
25541
+ if (self.client.buttons) {
25542
+ if (sys.game && sys.game.respawn) {
25543
+ sys.game.respawn(self);
25544
+ return;
25545
+ }
25546
+ }
25547
+ P_PlayerThink(self, sys);
25548
+ self.nextthink = sys.timeSeconds + 0.1;
25549
+ sys.scheduleThink(self, self.nextthink);
25550
+ return;
25551
+ }
25483
25552
  const nowMs = sys.timeSeconds * 1e3;
25484
25553
  const quadTime = self.client.quad_time || 0;
25485
25554
  const doubleTime = self.client.double_time || 0;
@@ -26150,17 +26219,9 @@ function createGame(imports, engine, options) {
26150
26219
  return true;
26151
26220
  },
26152
26221
  clientBegin(client) {
26153
- const playerStart = findPlayerStart(entities);
26154
26222
  const player = entities.spawn();
26155
- player.classname = "player";
26156
- player.origin = playerStart ? { ...playerStart.origin } : { x: 0, y: 0, z: 0 };
26157
- player.angles = playerStart ? { ...playerStart.angles } : { x: 0, y: 0, z: 0 };
26158
- player.health = 100;
26159
- player.takedamage = true;
26160
- player.movetype = 7 /* Toss */;
26161
- player.mins = { x: -16, y: -16, z: -24 };
26162
- player.maxs = { x: 16, y: 16, z: 32 };
26163
26223
  player.client = client;
26224
+ this.respawn(player);
26164
26225
  player.die = (self, inflictor, attacker, damage, point, mod) => {
26165
26226
  player_die(self, inflictor, attacker, damage, point, mod, entities);
26166
26227
  };
@@ -26172,10 +26233,37 @@ function createGame(imports, engine, options) {
26172
26233
  };
26173
26234
  player.nextthink = entities.timeSeconds + 0.1;
26174
26235
  entities.scheduleThink(player, player.nextthink);
26175
- entities.finalizeSpawn(player);
26176
- origin = { ...player.origin };
26177
26236
  return player;
26178
26237
  },
26238
+ respawn(ent) {
26239
+ if (!ent.client) return;
26240
+ const spawnPoint = SelectSpawnPoint(entities);
26241
+ ent.classname = "player";
26242
+ ent.origin = spawnPoint ? { ...spawnPoint.origin } : { x: 0, y: 0, z: 0 };
26243
+ ent.angles = spawnPoint ? { ...spawnPoint.angles } : { x: 0, y: 0, z: 0 };
26244
+ ent.health = 100;
26245
+ ent.takedamage = true;
26246
+ ent.movetype = 7 /* Toss */;
26247
+ ent.mins = { x: -16, y: -16, z: -24 };
26248
+ ent.maxs = { x: 16, y: 16, z: 32 };
26249
+ ent.solid = 2 /* BoundingBox */;
26250
+ ent.deadflag = 0;
26251
+ ent.modelindex = engine.modelIndex?.("players/male/tris.md2") || 0;
26252
+ ent.client.damage_alpha = 0;
26253
+ ent.client.damage_blend = [0, 0, 0];
26254
+ ent.client.anim_priority = 0;
26255
+ ent.client.anim_end = 0;
26256
+ ent.frame = 0;
26257
+ if (deathmatch) {
26258
+ ent.client.inventory = createPlayerInventory({
26259
+ weapons: [WeaponId.Blaster],
26260
+ currentWeapon: WeaponId.Blaster
26261
+ });
26262
+ } else {
26263
+ }
26264
+ entities.finalizeSpawn(ent);
26265
+ origin = { ...ent.origin };
26266
+ },
26179
26267
  clientDisconnect(ent) {
26180
26268
  if (ent && ent.inUse) {
26181
26269
  entities.free(ent);
@@ -26274,6 +26362,7 @@ function createGame(imports, engine, options) {
26274
26362
  // Annotate the CommonJS export names for ESM import in node:
26275
26363
  0 && (module.exports = {
26276
26364
  AIFlags,
26365
+ AI_GetSightClient,
26277
26366
  AMMO_TYPE_COUNT,
26278
26367
  ARMOR_INFO,
26279
26368
  ARMOR_ITEMS,