quake2ts 0.0.46 → 0.0.48

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 (31) hide show
  1. package/apps/viewer/dist/browser/index.global.js +1 -1
  2. package/apps/viewer/dist/browser/index.global.js.map +1 -1
  3. package/apps/viewer/dist/cjs/index.cjs +14 -3
  4. package/apps/viewer/dist/cjs/index.cjs.map +1 -1
  5. package/apps/viewer/dist/esm/index.js +14 -3
  6. package/apps/viewer/dist/esm/index.js.map +1 -1
  7. package/apps/viewer/dist/tsconfig.tsbuildinfo +1 -1
  8. package/package.json +1 -1
  9. package/packages/engine/dist/browser/index.global.js +7 -7
  10. package/packages/engine/dist/browser/index.global.js.map +1 -1
  11. package/packages/engine/dist/cjs/index.cjs +3 -1
  12. package/packages/engine/dist/cjs/index.cjs.map +1 -1
  13. package/packages/engine/dist/esm/index.js +3 -1
  14. package/packages/engine/dist/esm/index.js.map +1 -1
  15. package/packages/engine/dist/tsconfig.tsbuildinfo +1 -1
  16. package/packages/engine/dist/types/render/md3Pipeline.d.ts.map +1 -1
  17. package/packages/game/dist/browser/index.global.js +1 -1
  18. package/packages/game/dist/browser/index.global.js.map +1 -1
  19. package/packages/game/dist/cjs/index.cjs +176 -3
  20. package/packages/game/dist/cjs/index.cjs.map +1 -1
  21. package/packages/game/dist/esm/index.js +172 -3
  22. package/packages/game/dist/esm/index.js.map +1 -1
  23. package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
  24. package/packages/game/dist/types/ai/constants.d.ts +16 -0
  25. package/packages/game/dist/types/ai/constants.d.ts.map +1 -1
  26. package/packages/game/dist/types/ai/index.d.ts +1 -0
  27. package/packages/game/dist/types/ai/index.d.ts.map +1 -1
  28. package/packages/game/dist/types/ai/targeting.d.ts +25 -0
  29. package/packages/game/dist/types/ai/targeting.d.ts.map +1 -0
  30. package/packages/game/dist/types/entities/entity.d.ts +11 -0
  31. package/packages/game/dist/types/entities/entity.d.ts.map +1 -1
@@ -34,6 +34,7 @@ __export(index_exports, {
34
34
  EntityDamageFlags: () => EntityDamageFlags,
35
35
  EntitySystem: () => EntitySystem,
36
36
  EnvironmentalFlags: () => EnvironmentalFlags,
37
+ FL_NOTARGET: () => FL_NOTARGET,
37
38
  FL_NOVISIBLE: () => FL_NOVISIBLE,
38
39
  KeyId: () => KeyId,
39
40
  MoveType: () => MoveType,
@@ -87,6 +88,8 @@ __export(index_exports, {
87
88
  damageModName: () => damageModName,
88
89
  equipArmor: () => equipArmor,
89
90
  facingIdeal: () => facingIdeal,
91
+ findTarget: () => findTarget,
92
+ foundTarget: () => foundTarget,
90
93
  getAmmoItemDefinition: () => getAmmoItemDefinition,
91
94
  giveAmmo: () => giveAmmo,
92
95
  giveAmmoItem: () => giveAmmoItem,
@@ -96,6 +99,7 @@ __export(index_exports, {
96
99
  hasPowerup: () => hasPowerup,
97
100
  hasWeapon: () => hasWeapon,
98
101
  hashGameState: () => hashGameState,
102
+ huntTarget: () => huntTarget,
99
103
  infront: () => infront,
100
104
  isZeroVector: () => isZeroVector,
101
105
  killBox: () => killBox,
@@ -526,7 +530,12 @@ var ZERO = { ...ZERO_VEC3 };
526
530
  function copyVec3() {
527
531
  return { ...ZERO };
528
532
  }
529
- var DEFAULT_MONSTER_INFO = Object.freeze({ aiflags: 0 });
533
+ var DEFAULT_MONSTER_INFO = Object.freeze({
534
+ aiflags: 0,
535
+ last_sighting: ZERO,
536
+ trail_time: 0,
537
+ pausetime: 0
538
+ });
530
539
  var Entity = class {
531
540
  constructor(index) {
532
541
  this.inUse = false;
@@ -586,7 +595,9 @@ var Entity = class {
586
595
  this.solid = 0 /* Not */;
587
596
  this.flags = 0;
588
597
  this.svflags = 0;
589
- this.monsterinfo = { ...DEFAULT_MONSTER_INFO };
598
+ this.monsterinfo = { ...DEFAULT_MONSTER_INFO, last_sighting: copyVec3() };
599
+ this.show_hostile = 0;
600
+ this.light_level = 0;
590
601
  this.index = index;
591
602
  }
592
603
  reset() {
@@ -660,7 +671,10 @@ var Entity = class {
660
671
  this.solid = 0 /* Not */;
661
672
  this.flags = 0;
662
673
  this.svflags = 0;
663
- this.monsterinfo = { ...DEFAULT_MONSTER_INFO };
674
+ this.monsterinfo = { ...DEFAULT_MONSTER_INFO, last_sighting: copyVec3() };
675
+ this.combattarget = void 0;
676
+ this.show_hostile = 0;
677
+ this.light_level = 0;
664
678
  }
665
679
  };
666
680
  var ENTITY_FIELD_METADATA = [
@@ -2183,9 +2197,25 @@ var LevelClock = class {
2183
2197
  var RANGE_MELEE = 20;
2184
2198
  var RANGE_NEAR = 440;
2185
2199
  var RANGE_MID = 940;
2200
+ var FL_NOTARGET = 1 << 5;
2186
2201
  var FL_NOVISIBLE = 1 << 24;
2187
2202
  var SPAWNFLAG_MONSTER_AMBUSH = 1 << 0;
2188
2203
  var AIFlags = /* @__PURE__ */ ((AIFlags2) => {
2204
+ AIFlags2[AIFlags2["StandGround"] = 1] = "StandGround";
2205
+ AIFlags2[AIFlags2["TempStandGround"] = 2] = "TempStandGround";
2206
+ AIFlags2[AIFlags2["SoundTarget"] = 4] = "SoundTarget";
2207
+ AIFlags2[AIFlags2["LostSight"] = 8] = "LostSight";
2208
+ AIFlags2[AIFlags2["PursuitLastSeen"] = 16] = "PursuitLastSeen";
2209
+ AIFlags2[AIFlags2["PursueNext"] = 32] = "PursueNext";
2210
+ AIFlags2[AIFlags2["PursueTemp"] = 64] = "PursueTemp";
2211
+ AIFlags2[AIFlags2["HoldFrame"] = 128] = "HoldFrame";
2212
+ AIFlags2[AIFlags2["GoodGuy"] = 256] = "GoodGuy";
2213
+ AIFlags2[AIFlags2["Brutal"] = 512] = "Brutal";
2214
+ AIFlags2[AIFlags2["NoStep"] = 1024] = "NoStep";
2215
+ AIFlags2[AIFlags2["Ducked"] = 2048] = "Ducked";
2216
+ AIFlags2[AIFlags2["CombatPoint"] = 4096] = "CombatPoint";
2217
+ AIFlags2[AIFlags2["Medic"] = 8192] = "Medic";
2218
+ AIFlags2[AIFlags2["Resurrecting"] = 16384] = "Resurrecting";
2189
2219
  AIFlags2[AIFlags2["Pathing"] = 1073741824] = "Pathing";
2190
2220
  return AIFlags2;
2191
2221
  })(AIFlags || {});
@@ -2353,6 +2383,145 @@ function visible(self, other, trace, options) {
2353
2383
  return result.fraction === 1 || result.entity === other;
2354
2384
  }
2355
2385
 
2386
+ // src/ai/targeting.ts
2387
+ function setIdealYawTowards2(self, other) {
2388
+ const delta = {
2389
+ x: other.origin.x - self.origin.x,
2390
+ y: other.origin.y - self.origin.y,
2391
+ z: other.origin.z - self.origin.z
2392
+ };
2393
+ self.ideal_yaw = vectorToYaw(delta);
2394
+ }
2395
+ function faceYawInstantly(self) {
2396
+ self.angles.y = angleMod(self.ideal_yaw);
2397
+ }
2398
+ function huntTarget(self, level) {
2399
+ if (!self.enemy) return;
2400
+ self.goalentity = self.enemy;
2401
+ setIdealYawTowards2(self, self.enemy);
2402
+ faceYawInstantly(self);
2403
+ if ((self.monsterinfo.aiflags & 1 /* StandGround */) !== 0) {
2404
+ self.monsterinfo.stand?.(self);
2405
+ } else {
2406
+ self.monsterinfo.run?.(self);
2407
+ self.attack_finished_time = level.timeSeconds + 1;
2408
+ }
2409
+ }
2410
+ function foundTarget(self, level, options) {
2411
+ if (!self.enemy) return;
2412
+ if ((self.enemy.svflags & 8 /* Player */) !== 0) {
2413
+ level.sightEntity = self;
2414
+ level.sightEntityFrame = level.frameNumber;
2415
+ self.light_level = 128;
2416
+ }
2417
+ self.show_hostile = level.timeSeconds + 1;
2418
+ const lastSighting = self.monsterinfo.last_sighting;
2419
+ lastSighting.x = self.enemy.origin.x;
2420
+ lastSighting.y = self.enemy.origin.y;
2421
+ lastSighting.z = self.enemy.origin.z;
2422
+ self.trail_time = level.timeSeconds;
2423
+ self.monsterinfo.trail_time = level.timeSeconds;
2424
+ if (!self.combattarget) {
2425
+ huntTarget(self, level);
2426
+ return;
2427
+ }
2428
+ const pickTarget = options?.pickTarget;
2429
+ const movetarget = pickTarget?.(self.combattarget) ?? self.enemy;
2430
+ self.goalentity = movetarget;
2431
+ self.movetarget = movetarget;
2432
+ self.combattarget = void 0;
2433
+ self.monsterinfo.aiflags |= 4096 /* CombatPoint */;
2434
+ if (self.movetarget) {
2435
+ self.movetarget.targetname = void 0;
2436
+ }
2437
+ self.monsterinfo.pausetime = 0;
2438
+ self.monsterinfo.run?.(self);
2439
+ }
2440
+ function classifyClientVisibility(self, other, level) {
2441
+ const distance = rangeTo(self, other);
2442
+ const range = classifyRange(distance);
2443
+ const passthrough = (_start, _end, _ignore, _mask) => ({ fraction: 1, entity: other });
2444
+ if (range === "far" /* Far */) return false;
2445
+ if (other.light_level <= 5) return false;
2446
+ if (!visible(self, other, passthrough, { throughGlass: false })) return false;
2447
+ if (range === "near" /* Near */) {
2448
+ return level.timeSeconds <= other.show_hostile || infront(self, other);
2449
+ }
2450
+ if (range === "mid" /* Mid */) {
2451
+ return infront(self, other);
2452
+ }
2453
+ return true;
2454
+ }
2455
+ function updateSoundChase(self, client, level, hearability) {
2456
+ const passthrough = (_start, _end, _ignore, _mask) => ({ fraction: 1, entity: client });
2457
+ if ((self.spawnflags & SPAWNFLAG_MONSTER_AMBUSH) !== 0) {
2458
+ if (!visible(self, client, passthrough)) return false;
2459
+ } else if (hearability.canHear && !hearability.canHear(self, client)) {
2460
+ return false;
2461
+ }
2462
+ const delta = subtractVec3(client.origin, self.origin);
2463
+ if (lengthVec3(delta) > 1e3) return false;
2464
+ if (hearability.areasConnected && !hearability.areasConnected(self, client)) return false;
2465
+ self.ideal_yaw = vectorToYaw(delta);
2466
+ faceYawInstantly(self);
2467
+ self.monsterinfo.aiflags |= 4 /* SoundTarget */;
2468
+ self.enemy = client;
2469
+ return true;
2470
+ }
2471
+ function chooseCandidate(self, level) {
2472
+ if (level.sightEntity && level.sightEntityFrame >= level.frameNumber - 1 && (self.spawnflags & SPAWNFLAG_MONSTER_AMBUSH) === 0) {
2473
+ if (level.sightEntity.enemy !== self.enemy) {
2474
+ return { candidate: level.sightEntity, heardit: false };
2475
+ }
2476
+ return { candidate: null, heardit: false };
2477
+ }
2478
+ if (level.soundEntity && level.soundEntityFrame >= level.frameNumber - 1) {
2479
+ return { candidate: level.soundEntity, heardit: true };
2480
+ }
2481
+ if (!self.enemy && level.sound2Entity && level.sound2EntityFrame >= level.frameNumber - 1 && (self.spawnflags & SPAWNFLAG_MONSTER_AMBUSH) === 0) {
2482
+ return { candidate: level.sound2Entity, heardit: true };
2483
+ }
2484
+ if (level.sightClient) {
2485
+ return { candidate: level.sightClient, heardit: false };
2486
+ }
2487
+ return { candidate: null, heardit: false };
2488
+ }
2489
+ function rejectNotargetEntity(client) {
2490
+ if ((client.flags & FL_NOTARGET) !== 0) return true;
2491
+ if ((client.svflags & 4 /* Monster */) !== 0 && client.enemy) {
2492
+ return (client.enemy.flags & FL_NOTARGET) !== 0;
2493
+ }
2494
+ if (client.enemy && (client.enemy.flags & FL_NOTARGET) !== 0) return true;
2495
+ return false;
2496
+ }
2497
+ function findTarget(self, level, hearability = {}) {
2498
+ if ((self.monsterinfo.aiflags & 256 /* GoodGuy */) !== 0) {
2499
+ if (self.goalentity?.classname === "target_actor") {
2500
+ return false;
2501
+ }
2502
+ return false;
2503
+ }
2504
+ if ((self.monsterinfo.aiflags & 4096 /* CombatPoint */) !== 0) {
2505
+ return false;
2506
+ }
2507
+ const { candidate, heardit } = chooseCandidate(self, level);
2508
+ if (!candidate || !candidate.inUse) return false;
2509
+ if (candidate === self.enemy) return true;
2510
+ if (rejectNotargetEntity(candidate)) return false;
2511
+ if (!heardit) {
2512
+ if (!classifyClientVisibility(self, candidate, level)) return false;
2513
+ self.monsterinfo.aiflags &= ~4 /* SoundTarget */;
2514
+ self.enemy = candidate;
2515
+ } else if (!updateSoundChase(self, candidate, level, hearability)) {
2516
+ return false;
2517
+ }
2518
+ foundTarget(self, level);
2519
+ if ((self.monsterinfo.aiflags & 4 /* SoundTarget */) === 0) {
2520
+ self.monsterinfo.sight?.(self, self.enemy);
2521
+ }
2522
+ return true;
2523
+ }
2524
+
2356
2525
  // src/checksum.ts
2357
2526
  var FNV_OFFSET_BASIS = 2166136261;
2358
2527
  var FNV_PRIME = 16777619;
@@ -3816,6 +3985,7 @@ function createGame(engine, options) {
3816
3985
  EntityDamageFlags,
3817
3986
  EntitySystem,
3818
3987
  EnvironmentalFlags,
3988
+ FL_NOTARGET,
3819
3989
  FL_NOVISIBLE,
3820
3990
  KeyId,
3821
3991
  MoveType,
@@ -3869,6 +4039,8 @@ function createGame(engine, options) {
3869
4039
  damageModName,
3870
4040
  equipArmor,
3871
4041
  facingIdeal,
4042
+ findTarget,
4043
+ foundTarget,
3872
4044
  getAmmoItemDefinition,
3873
4045
  giveAmmo,
3874
4046
  giveAmmoItem,
@@ -3878,6 +4050,7 @@ function createGame(engine, options) {
3878
4050
  hasPowerup,
3879
4051
  hasWeapon,
3880
4052
  hashGameState,
4053
+ huntTarget,
3881
4054
  infront,
3882
4055
  isZeroVector,
3883
4056
  killBox,