quake2ts 0.0.446 → 0.0.449

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
@@ -3323,6 +3323,24 @@ function classifyClientVisibility(self, other, level, trace) {
3323
3323
  }
3324
3324
  return true;
3325
3325
  }
3326
+ function AI_GetSightClient(self, context, trace) {
3327
+ if ((self.monsterinfo.aiflags & 1024 /* NoStep */) !== 0) {
3328
+ return null;
3329
+ }
3330
+ for (let i = 1; i <= context.maxClients; i++) {
3331
+ const ent = context.entities[i];
3332
+ if (!ent || !ent.inUse || ent.health <= 0) {
3333
+ continue;
3334
+ }
3335
+ if ((ent.flags & FL_NOTARGET) !== 0) {
3336
+ continue;
3337
+ }
3338
+ if (visible(self, ent, trace, { throughGlass: false })) {
3339
+ return ent;
3340
+ }
3341
+ }
3342
+ return null;
3343
+ }
3326
3344
  function updateSoundChase(self, client, level, hearability, trace) {
3327
3345
  if ((self.spawnflags & SPAWNFLAG_MONSTER_AMBUSH) !== 0) {
3328
3346
  if (!visible(self, client, trace)) return false;
@@ -4775,6 +4793,18 @@ var EntitySystem = class {
4775
4793
  get game() {
4776
4794
  return this._game;
4777
4795
  }
4796
+ get maxClients() {
4797
+ return 32;
4798
+ }
4799
+ get entities() {
4800
+ const arr = new Array(this.pool.capacity + 1).fill(null);
4801
+ for (const ent of this.pool) {
4802
+ if (ent.index >= 0 && ent.index < arr.length) {
4803
+ arr[ent.index] = ent;
4804
+ }
4805
+ }
4806
+ return arr;
4807
+ }
4778
4808
  get world() {
4779
4809
  return this.pool.world;
4780
4810
  }
@@ -9855,11 +9885,35 @@ var FLAG_ITEMS = {
9855
9885
  }
9856
9886
  };
9857
9887
 
9858
- // src/entities/items/weapons.ts
9859
- function createWeaponPickupEntity(game, weaponItem) {
9860
- const respawn = (self) => {
9888
+ // src/entities/items/common.ts
9889
+ init_esm();
9890
+ function handleItemPickup(game, self, other, respawnTime = 30) {
9891
+ if (!game.deathmatch) {
9892
+ game.entities.free(self);
9893
+ return;
9894
+ }
9895
+ self.solid = 0 /* Not */;
9896
+ self.modelindex = 0;
9897
+ self.svflags |= 1 /* NoClient */;
9898
+ self.nextthink = game.time + respawnTime;
9899
+ game.entities.scheduleThink(self, self.nextthink);
9900
+ }
9901
+ function createItemRespawnFunction(game, originalModel) {
9902
+ let cachedIndex = 0;
9903
+ return (self) => {
9904
+ if (!cachedIndex) {
9905
+ cachedIndex = game.entities.modelIndex(originalModel);
9906
+ }
9861
9907
  self.solid = 1 /* Trigger */;
9908
+ self.modelindex = cachedIndex;
9909
+ self.svflags &= ~1 /* NoClient */;
9910
+ game.multicast(self.origin, 1 /* Pvs */, ServerCommand.sound, 0, "items/respawn.wav", 1, 0, 0);
9862
9911
  };
9912
+ }
9913
+
9914
+ // src/entities/items/weapons.ts
9915
+ function createWeaponPickupEntity(game, weaponItem) {
9916
+ const modelName = `models/items/${weaponItem.id.replace("weapon_", "")}/tris.md2`;
9863
9917
  return {
9864
9918
  classname: weaponItem.id,
9865
9919
  solid: 1 /* Trigger */,
@@ -9870,22 +9924,16 @@ function createWeaponPickupEntity(game, weaponItem) {
9870
9924
  if (pickupWeapon(other.client.inventory, weaponItem, game.time * 1e3)) {
9871
9925
  game.sound?.(other, 0, "items/pkup.wav", 1, 1, 0);
9872
9926
  game.centerprintf?.(other, `You got the ${weaponItem.name}`);
9873
- self.solid = 0 /* Not */;
9874
- if (game.deathmatch) {
9875
- self.nextthink = game.time + 30;
9876
- game.entities.scheduleThink(self, self.nextthink);
9877
- }
9927
+ handleItemPickup(game, self, other);
9878
9928
  }
9879
9929
  },
9880
- think: respawn
9930
+ think: createItemRespawnFunction(game, modelName)
9881
9931
  };
9882
9932
  }
9883
9933
 
9884
9934
  // src/entities/items/health.ts
9885
9935
  function createHealthPickupEntity(game, healthItem) {
9886
- const respawn = (self) => {
9887
- self.solid = 1 /* Trigger */;
9888
- };
9936
+ const modelName = `models/items/healing/${healthItem.id.replace("item_health_", "")}/tris.md2`;
9889
9937
  return {
9890
9938
  classname: healthItem.id,
9891
9939
  solid: 1 /* Trigger */,
@@ -9900,22 +9948,16 @@ function createHealthPickupEntity(game, healthItem) {
9900
9948
  }
9901
9949
  game.sound?.(other, 0, "items/pkup.wav", 1, 1, 0);
9902
9950
  game.centerprintf?.(other, `You got the ${healthItem.name}`);
9903
- self.solid = 0 /* Not */;
9904
- if (game.deathmatch) {
9905
- self.nextthink = game.time + 30;
9906
- game.entities.scheduleThink(self, self.nextthink);
9907
- }
9951
+ handleItemPickup(game, self, other);
9908
9952
  }
9909
9953
  },
9910
- think: respawn
9954
+ think: createItemRespawnFunction(game, modelName)
9911
9955
  };
9912
9956
  }
9913
9957
 
9914
9958
  // src/entities/items/armor.ts
9915
9959
  function createArmorPickupEntity(game, armorItem) {
9916
- const respawn = (self) => {
9917
- self.solid = 1 /* Trigger */;
9918
- };
9960
+ const modelName = `models/items/armor/${armorItem.id.replace("item_armor_", "")}/tris.md2`;
9919
9961
  return {
9920
9962
  classname: armorItem.id,
9921
9963
  solid: 1 /* Trigger */,
@@ -9926,22 +9968,17 @@ function createArmorPickupEntity(game, armorItem) {
9926
9968
  if (pickupArmor(other.client.inventory, armorItem, game.time * 1e3)) {
9927
9969
  game.sound?.(other, 0, "items/pkup.wav", 1, 1, 0);
9928
9970
  game.centerprintf?.(other, `You got the ${armorItem.name}`);
9929
- self.solid = 0 /* Not */;
9930
- if (game.deathmatch) {
9931
- self.nextthink = game.time + 30;
9932
- game.entities.scheduleThink(self, self.nextthink);
9933
- }
9971
+ handleItemPickup(game, self, other);
9934
9972
  }
9935
9973
  },
9936
- think: respawn
9974
+ think: createItemRespawnFunction(game, modelName)
9937
9975
  };
9938
9976
  }
9939
9977
 
9940
9978
  // src/entities/items/powerups.ts
9941
9979
  function createPowerupPickupEntity(game, powerupItem) {
9942
- const respawn = (self) => {
9943
- self.solid = 1 /* Trigger */;
9944
- };
9980
+ const respawnTime = powerupItem.id === "item_quad" || powerupItem.id === "item_invulnerability" ? 60 : 30;
9981
+ const modelName = `models/items/powerups/${powerupItem.id.replace("item_", "")}/tris.md2`;
9945
9982
  return {
9946
9983
  classname: powerupItem.id,
9947
9984
  solid: 1 /* Trigger */,
@@ -9952,14 +9989,10 @@ function createPowerupPickupEntity(game, powerupItem) {
9952
9989
  if (pickupPowerup(other.client, powerupItem, game.time * 1e3)) {
9953
9990
  game.sound?.(other, 0, "items/pkup.wav", 1, 1, 0);
9954
9991
  game.centerprintf?.(other, `You got the ${powerupItem.name}`);
9955
- self.solid = 0 /* Not */;
9956
- if (game.deathmatch) {
9957
- self.nextthink = game.time + 30;
9958
- game.entities.scheduleThink(self, self.nextthink);
9959
- }
9992
+ handleItemPickup(game, self, other, respawnTime);
9960
9993
  }
9961
9994
  },
9962
- think: respawn
9995
+ think: createItemRespawnFunction(game, modelName)
9963
9996
  };
9964
9997
  }
9965
9998
 
@@ -10005,9 +10038,7 @@ var AMMO_DISPLAY_NAMES = {
10005
10038
  };
10006
10039
  function createAmmoPickupEntity(game, itemId) {
10007
10040
  const def = getAmmoItemDefinition(itemId);
10008
- const respawn = (self) => {
10009
- self.solid = 1 /* Trigger */;
10010
- };
10041
+ const modelName = `models/items/ammo/${itemId.replace("ammo_", "")}/tris.md2`;
10011
10042
  return {
10012
10043
  classname: itemId,
10013
10044
  solid: 1 /* Trigger */,
@@ -10020,14 +10051,10 @@ function createAmmoPickupEntity(game, itemId) {
10020
10051
  game.sound?.(other, 0, "items/pkup.wav", 1, 1, 0);
10021
10052
  const name = AMMO_DISPLAY_NAMES[itemId] || itemId.replace("ammo_", "");
10022
10053
  game.centerprintf?.(other, `You got ${def.quantity} ${name}`);
10023
- self.solid = 0 /* Not */;
10024
- if (game.deathmatch) {
10025
- self.nextthink = game.time + 30;
10026
- game.entities.scheduleThink(self, self.nextthink);
10027
- }
10054
+ handleItemPickup(game, self, other);
10028
10055
  }
10029
10056
  },
10030
- think: respawn
10057
+ think: createItemRespawnFunction(game, modelName)
10031
10058
  };
10032
10059
  }
10033
10060
 
@@ -23846,6 +23873,21 @@ function spawnEntitiesFromText(text, options) {
23846
23873
  }
23847
23874
  return spawned;
23848
23875
  }
23876
+ function SelectDeathmatchSpawnPoint(entities) {
23877
+ const spots = entities.findByClassname("info_player_deathmatch");
23878
+ if (spots.length === 0) {
23879
+ return void 0;
23880
+ }
23881
+ const index = Math.floor(entities.rng.frandom() * spots.length);
23882
+ return spots[index];
23883
+ }
23884
+ function SelectSpawnPoint(entities) {
23885
+ if (entities.deathmatch) {
23886
+ const spot = SelectDeathmatchSpawnPoint(entities);
23887
+ if (spot) return spot;
23888
+ }
23889
+ return findPlayerStart(entities);
23890
+ }
23849
23891
  function findPlayerStart(entities) {
23850
23892
  return entities.find(
23851
23893
  (entity) => entity.classname === "info_player_start"
@@ -25013,26 +25055,37 @@ function ClientObituary(self, inflictor, attacker, mod, sys) {
25013
25055
  }
25014
25056
  if (mod === 24 /* SUICIDE */) {
25015
25057
  message = `${friendlyName} suicides.`;
25058
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25016
25059
  } else if (mod === 23 /* FALLING */) {
25017
25060
  message = `${friendlyName} cratered.`;
25061
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25018
25062
  } else if (mod === 20 /* CRUSH */) {
25019
25063
  message = `${friendlyName} was squished.`;
25064
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25020
25065
  } else if (mod === 17 /* WATER */) {
25021
25066
  message = `${friendlyName} sank like a rock.`;
25067
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25022
25068
  } else if (mod === 18 /* SLIME */) {
25023
25069
  message = `${friendlyName} melted.`;
25070
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25024
25071
  } else if (mod === 19 /* LAVA */) {
25025
25072
  message = `${friendlyName} does a back flip into the lava.`;
25073
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25026
25074
  } else if (mod === 26 /* EXPLOSIVE */) {
25027
25075
  message = `${friendlyName} blew up.`;
25076
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25028
25077
  } else if (mod === 31 /* TARGET_LASER */) {
25029
25078
  message = `${friendlyName} saw the light.`;
25079
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25030
25080
  } else if (mod === 34 /* TARGET_BLASTER */) {
25031
25081
  message = `${friendlyName} got blasted.`;
25082
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25032
25083
  } else if (mod === 28 /* BOMB */) {
25033
25084
  message = `${friendlyName} was bombed.`;
25085
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25034
25086
  } else if (attacker && attacker.classname === "player") {
25035
25087
  if (self === attacker) {
25088
+ if (self.client) self.client.score = (self.client.score || 0) - 1;
25036
25089
  switch (mod) {
25037
25090
  case 6 /* GRENADE */:
25038
25091
  case 7 /* G_SPLASH */:
@@ -25061,6 +25114,9 @@ function ClientObituary(self, inflictor, attacker, mod, sys) {
25061
25114
  break;
25062
25115
  }
25063
25116
  } else {
25117
+ if (attacker.client) {
25118
+ attacker.client.score = (attacker.client.score || 0) + 1;
25119
+ }
25064
25120
  const attackerName = "Enemy";
25065
25121
  switch (mod) {
25066
25122
  case 1 /* BLASTER */:
@@ -25293,6 +25349,18 @@ function player_die(self, inflictor, attacker, damage, point, mod, sys) {
25293
25349
  }
25294
25350
  function player_think(self, sys) {
25295
25351
  if (!self.client) return;
25352
+ if (self.deadflag) {
25353
+ if (self.client.buttons) {
25354
+ if (sys.game && sys.game.respawn) {
25355
+ sys.game.respawn(self);
25356
+ return;
25357
+ }
25358
+ }
25359
+ P_PlayerThink(self, sys);
25360
+ self.nextthink = sys.timeSeconds + 0.1;
25361
+ sys.scheduleThink(self, self.nextthink);
25362
+ return;
25363
+ }
25296
25364
  const nowMs = sys.timeSeconds * 1e3;
25297
25365
  const quadTime = self.client.quad_time || 0;
25298
25366
  const doubleTime = self.client.double_time || 0;
@@ -25963,17 +26031,9 @@ function createGame(imports, engine, options) {
25963
26031
  return true;
25964
26032
  },
25965
26033
  clientBegin(client) {
25966
- const playerStart = findPlayerStart(entities);
25967
26034
  const player = entities.spawn();
25968
- player.classname = "player";
25969
- player.origin = playerStart ? { ...playerStart.origin } : { x: 0, y: 0, z: 0 };
25970
- player.angles = playerStart ? { ...playerStart.angles } : { x: 0, y: 0, z: 0 };
25971
- player.health = 100;
25972
- player.takedamage = true;
25973
- player.movetype = 7 /* Toss */;
25974
- player.mins = { x: -16, y: -16, z: -24 };
25975
- player.maxs = { x: 16, y: 16, z: 32 };
25976
26035
  player.client = client;
26036
+ this.respawn(player);
25977
26037
  player.die = (self, inflictor, attacker, damage, point, mod) => {
25978
26038
  player_die(self, inflictor, attacker, damage, point, mod, entities);
25979
26039
  };
@@ -25985,10 +26045,37 @@ function createGame(imports, engine, options) {
25985
26045
  };
25986
26046
  player.nextthink = entities.timeSeconds + 0.1;
25987
26047
  entities.scheduleThink(player, player.nextthink);
25988
- entities.finalizeSpawn(player);
25989
- origin = { ...player.origin };
25990
26048
  return player;
25991
26049
  },
26050
+ respawn(ent) {
26051
+ if (!ent.client) return;
26052
+ const spawnPoint = SelectSpawnPoint(entities);
26053
+ ent.classname = "player";
26054
+ ent.origin = spawnPoint ? { ...spawnPoint.origin } : { x: 0, y: 0, z: 0 };
26055
+ ent.angles = spawnPoint ? { ...spawnPoint.angles } : { x: 0, y: 0, z: 0 };
26056
+ ent.health = 100;
26057
+ ent.takedamage = true;
26058
+ ent.movetype = 7 /* Toss */;
26059
+ ent.mins = { x: -16, y: -16, z: -24 };
26060
+ ent.maxs = { x: 16, y: 16, z: 32 };
26061
+ ent.solid = 2 /* BoundingBox */;
26062
+ ent.deadflag = 0;
26063
+ ent.modelindex = engine.modelIndex?.("players/male/tris.md2") || 0;
26064
+ ent.client.damage_alpha = 0;
26065
+ ent.client.damage_blend = [0, 0, 0];
26066
+ ent.client.anim_priority = 0;
26067
+ ent.client.anim_end = 0;
26068
+ ent.frame = 0;
26069
+ if (deathmatch) {
26070
+ ent.client.inventory = createPlayerInventory({
26071
+ weapons: [WeaponId.Blaster],
26072
+ currentWeapon: WeaponId.Blaster
26073
+ });
26074
+ } else {
26075
+ }
26076
+ entities.finalizeSpawn(ent);
26077
+ origin = { ...ent.origin };
26078
+ },
25992
26079
  clientDisconnect(ent) {
25993
26080
  if (ent && ent.inUse) {
25994
26081
  entities.free(ent);
@@ -26086,6 +26173,7 @@ function createGame(imports, engine, options) {
26086
26173
  }
26087
26174
  export {
26088
26175
  AIFlags,
26176
+ AI_GetSightClient,
26089
26177
  AMMO_TYPE_COUNT,
26090
26178
  ARMOR_INFO,
26091
26179
  ARMOR_ITEMS,