quake2ts 0.0.168 → 0.0.170

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.
@@ -1581,6 +1581,10 @@ var Entity = class {
1581
1581
  this.max_health = 0;
1582
1582
  this.takedamage = false;
1583
1583
  this.dmg = 0;
1584
+ this.radius_dmg = 0;
1585
+ // Damage amount for radius damage (used by BFG, rockets, etc.)
1586
+ this.dmg_radius = 0;
1587
+ // Radius for damage effects
1584
1588
  this.speed = 0;
1585
1589
  this.accel = 0;
1586
1590
  this.decel = 0;
@@ -2934,7 +2938,7 @@ function deserializeInventory(value) {
2934
2938
  return parsed;
2935
2939
  }
2936
2940
  var EntitySystem = class {
2937
- constructor(engine, imports, gravity, maxEntities, callbackRegistry) {
2941
+ constructor(engine, imports, gravity, maxEntities, callbackRegistry, deathmatch) {
2938
2942
  this.targetNameIndex = /* @__PURE__ */ new Map();
2939
2943
  this.random = createRandomGenerator();
2940
2944
  this.currentTimeSeconds = 0;
@@ -2942,6 +2946,7 @@ var EntitySystem = class {
2942
2946
  this.pool = new EntityPool(maxEntities);
2943
2947
  this.thinkScheduler = new ThinkScheduler();
2944
2948
  this.engine = engine;
2949
+ this.deathmatch = deathmatch ?? false;
2945
2950
  this.imports = imports || {
2946
2951
  trace: () => ({
2947
2952
  allsolid: false,
@@ -5753,58 +5758,211 @@ function createBlasterBolt(sys, owner, start, dir, damage, speed, mod) {
5753
5758
  };
5754
5759
  sys.finalizeSpawn(bolt);
5755
5760
  }
5761
+ function fireBfgPiercingLaser(sys, bfg, target, damage) {
5762
+ const start = { ...bfg.origin };
5763
+ const targetCenter2 = {
5764
+ x: (target.absmin.x + target.absmax.x) * 0.5,
5765
+ y: (target.absmin.y + target.absmax.y) * 0.5,
5766
+ z: (target.absmin.z + target.absmax.z) * 0.5
5767
+ };
5768
+ const dir = normalizeVec3(subtractVec3(targetCenter2, start));
5769
+ const end = {
5770
+ x: start.x + dir.x * 2048,
5771
+ y: start.y + dir.y * 2048,
5772
+ z: start.z + dir.z * 2048
5773
+ };
5774
+ const MAX_PIERCE = 16;
5775
+ const pierced = [];
5776
+ const piercedSolidities = [];
5777
+ let currentStart = { ...start };
5778
+ try {
5779
+ for (let i = 0; i < MAX_PIERCE; i++) {
5780
+ const tr = sys.trace(
5781
+ currentStart,
5782
+ null,
5783
+ null,
5784
+ end,
5785
+ bfg,
5786
+ CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_PLAYER | CONTENTS_DEADMONSTER
5787
+ );
5788
+ if (!tr.ent || tr.fraction >= 1) {
5789
+ break;
5790
+ }
5791
+ if (tr.ent.takedamage && tr.ent !== bfg.owner) {
5792
+ T_Damage(
5793
+ tr.ent,
5794
+ bfg,
5795
+ bfg.owner,
5796
+ dir,
5797
+ tr.endpos,
5798
+ ZERO_VEC3,
5799
+ damage,
5800
+ 1,
5801
+ // kick
5802
+ 4 /* ENERGY */,
5803
+ 12 /* BFG_LASER */,
5804
+ sys.multicast.bind(sys)
5805
+ );
5806
+ }
5807
+ if (!(tr.ent.svflags & 4 /* Monster */) && !tr.ent.client && tr.ent.classname !== "misc_explobox") {
5808
+ break;
5809
+ }
5810
+ pierced.push(tr.ent);
5811
+ piercedSolidities.push(tr.ent.solid);
5812
+ tr.ent.solid = 0 /* Not */;
5813
+ currentStart = { ...tr.endpos };
5814
+ }
5815
+ const finalTrace = sys.trace(start, null, null, end, bfg, CONTENTS_SOLID);
5816
+ sys.multicast(
5817
+ bfg.origin,
5818
+ 2 /* Phs */,
5819
+ ServerCommand.temp_entity,
5820
+ TempEntity.BFG_LASER,
5821
+ start,
5822
+ finalTrace.endpos
5823
+ );
5824
+ } finally {
5825
+ for (let i = 0; i < pierced.length; i++) {
5826
+ pierced[i].solid = piercedSolidities[i];
5827
+ }
5828
+ }
5829
+ }
5830
+ function bfgThink(self, sys) {
5831
+ const dmg = sys.deathmatch ? 5 : 10;
5832
+ const nearbyEntities = sys.findByRadius(self.origin, 256);
5833
+ for (const ent of nearbyEntities) {
5834
+ if (ent === self || ent === self.owner) {
5835
+ continue;
5836
+ }
5837
+ if (!ent.takedamage) {
5838
+ continue;
5839
+ }
5840
+ if (!(ent.svflags & 4 /* Monster */) && !ent.client && ent.classname !== "misc_explobox") {
5841
+ continue;
5842
+ }
5843
+ const point = {
5844
+ x: (ent.absmin.x + ent.absmax.x) * 0.5,
5845
+ y: (ent.absmin.y + ent.absmax.y) * 0.5,
5846
+ z: (ent.absmin.z + ent.absmax.z) * 0.5
5847
+ };
5848
+ const sightTrace = sys.trace(self.origin, null, null, point, null, MASK_SOLID);
5849
+ if (sightTrace.fraction < 1) {
5850
+ continue;
5851
+ }
5852
+ fireBfgPiercingLaser(sys, self, ent, dmg);
5853
+ }
5854
+ sys.scheduleThink(self, sys.timeSeconds + 0.1);
5855
+ }
5856
+ function bfgExplode(self, sys) {
5857
+ if (self.frame === void 0 || self.frame < 0) {
5858
+ self.frame = 0;
5859
+ }
5860
+ if (self.frame === 0) {
5861
+ const entities = sys.findByRadius(self.origin, self.dmg_radius || 100);
5862
+ for (const ent of entities) {
5863
+ if (!ent.takedamage) continue;
5864
+ if (ent === self.owner) continue;
5865
+ if (!(ent.svflags & 4 /* Monster */) && !ent.client && ent.classname !== "misc_explobox") {
5866
+ continue;
5867
+ }
5868
+ const centroid = {
5869
+ x: (ent.absmin.x + ent.absmax.x) * 0.5,
5870
+ y: (ent.absmin.y + ent.absmax.y) * 0.5,
5871
+ z: (ent.absmin.z + ent.absmax.z) * 0.5
5872
+ };
5873
+ const delta = subtractVec3(self.origin, centroid);
5874
+ const dist = lengthVec3(delta);
5875
+ const dmgRadius = self.dmg_radius || 100;
5876
+ const points = (self.radius_dmg || 200) * (1 - Math.sqrt(dist / dmgRadius));
5877
+ if (points > 0) {
5878
+ T_Damage(
5879
+ ent,
5880
+ self,
5881
+ self.owner,
5882
+ self.velocity,
5883
+ centroid,
5884
+ ZERO_VEC3,
5885
+ Math.floor(points),
5886
+ 0,
5887
+ 4 /* ENERGY */,
5888
+ 14 /* BFG_EFFECT */,
5889
+ sys.multicast.bind(sys)
5890
+ );
5891
+ }
5892
+ }
5893
+ }
5894
+ self.frame++;
5895
+ if (self.frame >= 5) {
5896
+ sys.free(self);
5897
+ return;
5898
+ }
5899
+ sys.scheduleThink(self, sys.timeSeconds + 0.1);
5900
+ }
5756
5901
  function createBfgBall(sys, owner, start, dir, damage, speed, damageRadius) {
5757
5902
  const bfgBall = sys.spawn();
5758
- bfgBall.classname = "bfg_ball";
5903
+ bfgBall.classname = "bfg blast";
5759
5904
  bfgBall.owner = owner;
5760
5905
  bfgBall.origin = { ...start };
5761
5906
  bfgBall.velocity = { x: dir.x * speed, y: dir.y * speed, z: dir.z * speed };
5762
5907
  bfgBall.movetype = 8 /* FlyMissile */;
5763
5908
  bfgBall.clipmask = 268566530;
5764
5909
  bfgBall.solid = 2 /* BoundingBox */;
5765
- bfgBall.modelindex = sys.modelIndex("models/objects/bfgball/tris.md2");
5910
+ bfgBall.modelindex = sys.modelIndex("sprites/s_bfg1.sp2");
5911
+ bfgBall.svflags = 128 /* Projectile */;
5912
+ bfgBall.radius_dmg = damage;
5913
+ bfgBall.dmg_radius = damageRadius;
5766
5914
  bfgBall.mins = { x: -10, y: -10, z: -10 };
5767
5915
  bfgBall.maxs = { x: 10, y: 10, z: 10 };
5768
5916
  bfgBall.touch = (self, other, plane, surf) => {
5769
5917
  if (other === self.owner) {
5770
5918
  return;
5771
5919
  }
5772
- const entities = sys.findByRadius(self.origin, damageRadius);
5773
- T_RadiusDamage(entities, self, self.owner, damage, self.owner, damageRadius, 0 /* NONE */, 13 /* BFG_BLAST */, {}, sys.multicast.bind(sys));
5774
- sys.multicast(self.origin, 2 /* Phs */, ServerCommand.temp_entity, TempEntity.BFG_EXPLOSION, self.origin);
5775
- if (self.owner) {
5776
- const targets = sys.findByRadius(self.origin, 1e3);
5777
- const playerOrigin = self.owner.origin;
5778
- for (const target of targets) {
5779
- if (target === self.owner || !target.takedamage) continue;
5780
- const tr = sys.trace(playerOrigin, null, null, target.origin, self.owner, 1 | 2);
5781
- if (tr.ent !== target && tr.fraction < 1) {
5782
- continue;
5783
- }
5784
- const dir2 = normalizeVec3(subtractVec3(target.origin, self.origin));
5785
- let laserDamage = 10;
5786
- T_Damage(
5787
- target,
5788
- self,
5789
- self.owner,
5790
- dir2,
5791
- target.origin,
5792
- ZERO_VEC3,
5793
- laserDamage,
5794
- 10,
5795
- 4 /* ENERGY */,
5796
- 12 /* BFG_LASER */,
5797
- sys.multicast.bind(sys)
5798
- );
5799
- sys.multicast(self.origin, 2 /* Phs */, ServerCommand.temp_entity, TempEntity.BFG_LASER, playerOrigin, target.origin);
5800
- }
5920
+ if (other && other.takedamage) {
5921
+ T_Damage(
5922
+ other,
5923
+ self,
5924
+ self.owner,
5925
+ self.velocity,
5926
+ self.origin,
5927
+ plane ? plane.normal : ZERO_VEC3,
5928
+ 200,
5929
+ 0,
5930
+ 4 /* ENERGY */,
5931
+ 13 /* BFG_BLAST */,
5932
+ sys.multicast.bind(sys)
5933
+ );
5801
5934
  }
5802
- sys.free(self);
5803
- };
5804
- bfgBall.think = (self) => {
5805
- self.nextthink = sys.timeSeconds + 0.1;
5806
- };
5807
- sys.scheduleThink(bfgBall, sys.timeSeconds + 0.1);
5935
+ const entities = sys.findByRadius(self.origin, 100);
5936
+ T_RadiusDamage(
5937
+ entities,
5938
+ self,
5939
+ self.owner,
5940
+ 200,
5941
+ other,
5942
+ 100,
5943
+ 4 /* ENERGY */,
5944
+ 13 /* BFG_BLAST */,
5945
+ {},
5946
+ sys.multicast.bind(sys)
5947
+ );
5948
+ sys.multicast(
5949
+ self.origin,
5950
+ 2 /* Phs */,
5951
+ ServerCommand.temp_entity,
5952
+ TempEntity.BFG_BIGEXPLOSION,
5953
+ self.origin
5954
+ );
5955
+ self.solid = 0 /* Not */;
5956
+ self.touch = void 0;
5957
+ self.velocity = ZERO_VEC3;
5958
+ self.modelindex = sys.modelIndex("sprites/s_bfg3.sp2");
5959
+ self.frame = 0;
5960
+ self.enemy = other;
5961
+ self.think = (self2, context) => bfgExplode(self2, context);
5962
+ sys.scheduleThink(self, sys.timeSeconds + 0.1);
5963
+ };
5964
+ bfgBall.think = (self, context) => bfgThink(self, context);
5965
+ sys.scheduleThink(bfgBall, sys.timeSeconds + 0.016);
5808
5966
  sys.finalizeSpawn(bfgBall);
5809
5967
  }
5810
5968
 
@@ -12624,7 +12782,7 @@ function createGame({ trace, pointcontents, multicast, unicast }, engine, option
12624
12782
  z: ent.origin.z + ent.maxs.z
12625
12783
  };
12626
12784
  };
12627
- const entities = new EntitySystem(engine, { trace, pointcontents, linkentity, multicast, unicast }, gravity);
12785
+ const entities = new EntitySystem(engine, { trace, pointcontents, linkentity, multicast, unicast }, gravity, void 0, void 0, deathmatch);
12628
12786
  frameLoop.addStage("prep", (context) => {
12629
12787
  levelClock.tick(context);
12630
12788
  entities.beginFrame(levelClock.current.timeSeconds);