quake2ts 0.0.484 → 0.0.486

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.
@@ -1878,6 +1878,13 @@ var DamageFlags = /* @__PURE__ */ ((DamageFlags2) => {
1878
1878
  DamageFlags2[DamageFlags2["NO_DAMAGE_EFFECTS"] = 1024] = "NO_DAMAGE_EFFECTS";
1879
1879
  return DamageFlags2;
1880
1880
  })(DamageFlags || {});
1881
+ var EntityDamageFlags = /* @__PURE__ */ ((EntityDamageFlags2) => {
1882
+ EntityDamageFlags2[EntityDamageFlags2["GODMODE"] = 1] = "GODMODE";
1883
+ EntityDamageFlags2[EntityDamageFlags2["IMMORTAL"] = 2] = "IMMORTAL";
1884
+ EntityDamageFlags2[EntityDamageFlags2["NO_KNOCKBACK"] = 4] = "NO_KNOCKBACK";
1885
+ EntityDamageFlags2[EntityDamageFlags2["NO_DAMAGE_EFFECTS"] = 8] = "NO_DAMAGE_EFFECTS";
1886
+ return EntityDamageFlags2;
1887
+ })(EntityDamageFlags || {});
1881
1888
  function hasAnyDamageFlag(flags, mask) {
1882
1889
  return (flags & mask) !== 0;
1883
1890
  }
@@ -3864,13 +3871,6 @@ var MulticastType = /* @__PURE__ */ ((MulticastType2) => {
3864
3871
  })(MulticastType || {});
3865
3872
 
3866
3873
  // src/combat/damage.ts
3867
- var EntityDamageFlags = /* @__PURE__ */ ((EntityDamageFlags2) => {
3868
- EntityDamageFlags2[EntityDamageFlags2["GODMODE"] = 1] = "GODMODE";
3869
- EntityDamageFlags2[EntityDamageFlags2["IMMORTAL"] = 2] = "IMMORTAL";
3870
- EntityDamageFlags2[EntityDamageFlags2["NO_KNOCKBACK"] = 4] = "NO_KNOCKBACK";
3871
- EntityDamageFlags2[EntityDamageFlags2["NO_DAMAGE_EFFECTS"] = 8] = "NO_DAMAGE_EFFECTS";
3872
- return EntityDamageFlags2;
3873
- })(EntityDamageFlags || {});
3874
3874
  function getDamageModifier(attacker, time) {
3875
3875
  if (!attacker) {
3876
3876
  return 1;
@@ -3934,6 +3934,18 @@ function T_Damage(targ, inflictor, attacker, dir, point, normal, damage, knockba
3934
3934
  if (!targ.takedamage) {
3935
3935
  return null;
3936
3936
  }
3937
+ const client = targ.client;
3938
+ if (client && client.enviro_time && client.enviro_time > time) {
3939
+ if (mod === 18 /* SLIME */ || mod === 19 /* LAVA */) {
3940
+ return {
3941
+ take: 0,
3942
+ psave: 0,
3943
+ asave: 0,
3944
+ knocked: { x: 0, y: 0, z: 0 },
3945
+ killed: false
3946
+ };
3947
+ }
3948
+ }
3937
3949
  const modifier = getDamageModifier(attacker, time);
3938
3950
  const modifiedDamage = damage * modifier;
3939
3951
  const modifiedKnockback = knockback * modifier;
@@ -5115,8 +5127,14 @@ var EntitySystem = class {
5115
5127
  linkentity(ent) {
5116
5128
  this.imports.linkentity(ent);
5117
5129
  }
5118
- multicast(origin, type, event, ...args) {
5119
- this.imports.multicast(origin, type, event, ...args);
5130
+ link(ent) {
5131
+ this.linkentity(ent);
5132
+ }
5133
+ unlink(ent) {
5134
+ this.spatialGrid.remove(ent);
5135
+ }
5136
+ multicast(origin, type, ServerCommand6, ...args) {
5137
+ this.imports.multicast(origin, type, ServerCommand6, ...args);
5120
5138
  }
5121
5139
  unicast(ent, reliable, event, ...args) {
5122
5140
  this.imports.unicast(ent, reliable, event, ...args);
@@ -8838,12 +8856,49 @@ function fireHyperBlaster(game, player) {
8838
8856
  }
8839
8857
  function fireBlaster(game, player) {
8840
8858
  if (!player.client) return;
8841
- game.multicast(player.origin, 1 /* Pvs */, ServerCommand.muzzleflash, player.index, MZ_BLASTER);
8842
- applyKick(player, -0.5, 0, 0);
8843
- setPlayerAttackAnim(player);
8844
- const { forward, right, up } = angleVectors(player.angles);
8845
- const source = P_ProjectSource(game, player, { x: 8, y: 8, z: -8 }, forward, right, up);
8846
- createBlasterBolt(game.entities, player, source, forward, 15, 1500, 1 /* BLASTER */);
8859
+ if (player.client.buttons & 32) {
8860
+ game.sound(player, 0, "weapons/swing.wav", 1, ATTN_NORM, 0);
8861
+ applyKick(player, -2, 0, 0);
8862
+ setPlayerAttackAnim(player);
8863
+ const { forward, right, up } = angleVectors(player.angles);
8864
+ const source = P_ProjectSource(game, player, { x: 8, y: 8, z: -8 }, forward, right, up);
8865
+ const range = 64;
8866
+ const damage = 50;
8867
+ const kick = 100;
8868
+ const end = { x: source.x + forward.x * range, y: source.y + forward.y * range, z: source.z + forward.z * range };
8869
+ const trace = game.trace(source, null, null, end, player, MASK_SHOT);
8870
+ if (trace.fraction < 1) {
8871
+ if (trace.ent && trace.ent.takedamage) {
8872
+ T_Damage(
8873
+ trace.ent,
8874
+ player,
8875
+ player,
8876
+ forward,
8877
+ trace.endpos,
8878
+ trace.plane ? trace.plane.normal : ZERO_VEC3,
8879
+ damage,
8880
+ kick,
8881
+ 0,
8882
+ 1 /* BLASTER */,
8883
+ game.time,
8884
+ game.multicast
8885
+ );
8886
+ game.sound(player, 0, "weapons/tink1.wav", 1, ATTN_NORM, 0);
8887
+ } else {
8888
+ game.sound(player, 0, "weapons/hithard.wav", 1, ATTN_NORM, 0);
8889
+ if (trace.plane) {
8890
+ game.multicast(trace.endpos, 1 /* Pvs */, ServerCommand.temp_entity, TempEntity.GUNSHOT, trace.endpos, trace.plane.normal);
8891
+ }
8892
+ }
8893
+ }
8894
+ } else {
8895
+ game.multicast(player.origin, 1 /* Pvs */, ServerCommand.muzzleflash, player.index, MZ_BLASTER);
8896
+ applyKick(player, -0.5, 0, 0);
8897
+ setPlayerAttackAnim(player);
8898
+ const { forward, right, up } = angleVectors(player.angles);
8899
+ const source = P_ProjectSource(game, player, { x: 8, y: 8, z: -8 }, forward, right, up);
8900
+ createBlasterBolt(game.entities, player, source, forward, 15, 1500, 1 /* BLASTER */);
8901
+ }
8847
8902
  }
8848
8903
  function fireRocket(game, player) {
8849
8904
  if (!player.client) return;
@@ -9066,7 +9121,7 @@ function Weapon_Generic(ent, FRAME_ACTIVATE_LAST, FRAME_FIRE_LAST, FRAME_IDLE_LA
9066
9121
  return;
9067
9122
  }
9068
9123
  if (client.weaponstate === 0 /* WEAPON_READY */) {
9069
- if (client.buttons & 1) {
9124
+ if (client.buttons & 1 || client.buttons & 32) {
9070
9125
  client.weaponstate = 3 /* WEAPON_FIRING */;
9071
9126
  client.gun_frame = FRAME_ACTIVATE_LAST + 1;
9072
9127
  return;
@@ -10055,6 +10110,64 @@ var FLAG_ITEMS = {
10055
10110
  }
10056
10111
  };
10057
10112
 
10113
+ // src/inventory/give.ts
10114
+ function giveItem(entity, classname) {
10115
+ if (!entity.client) return false;
10116
+ const client = entity.client;
10117
+ const inventory = client.inventory;
10118
+ const time = 0;
10119
+ const weapon = WEAPON_ITEMS[classname];
10120
+ if (weapon) {
10121
+ return pickupWeapon(inventory, weapon, time);
10122
+ }
10123
+ const isAmmo = Object.values(AmmoItemId).includes(classname);
10124
+ if (isAmmo) {
10125
+ const res = giveAmmoItem(inventory, classname);
10126
+ return res.pickedUp;
10127
+ }
10128
+ const healthItem = HEALTH_ITEMS[classname];
10129
+ if (healthItem) {
10130
+ if (canPickupHealth(inventory, entity.health, healthItem)) {
10131
+ const count = healthItem.amount;
10132
+ const max = healthItem.max;
10133
+ if (entity.health < max) {
10134
+ entity.health += count;
10135
+ if (entity.health > max) entity.health = max;
10136
+ return true;
10137
+ }
10138
+ if (classname === "item_health_mega") {
10139
+ if (entity.health < max) {
10140
+ entity.health += count;
10141
+ return true;
10142
+ }
10143
+ return false;
10144
+ }
10145
+ }
10146
+ return false;
10147
+ }
10148
+ const armorItem = ARMOR_ITEMS[classname];
10149
+ if (armorItem) {
10150
+ return pickupArmor(inventory, armorItem, time);
10151
+ }
10152
+ const powerupItem = POWERUP_ITEMS[classname];
10153
+ if (powerupItem) {
10154
+ return pickupPowerup(client, powerupItem, time);
10155
+ }
10156
+ const powerArmorItem = POWER_ARMOR_ITEMS[classname];
10157
+ if (powerArmorItem) {
10158
+ return pickupPowerArmor(inventory, powerArmorItem, time);
10159
+ }
10160
+ const keyItem = KEY_ITEMS[classname];
10161
+ if (keyItem) {
10162
+ return pickupKey(inventory, keyItem, time);
10163
+ }
10164
+ const flagItem = FLAG_ITEMS[classname];
10165
+ if (flagItem) {
10166
+ return pickupFlag(client, flagItem, time);
10167
+ }
10168
+ return false;
10169
+ }
10170
+
10058
10171
  // src/entities/items/common.ts
10059
10172
  function handleItemPickup(game, self, other, respawnTime = 30) {
10060
10173
  if (!game.deathmatch) {
@@ -25811,6 +25924,11 @@ function player_think(self, sys) {
25811
25924
  return;
25812
25925
  }
25813
25926
  const nowMs = sys.timeSeconds * 1e3;
25927
+ if (self.client.invincible_time && self.client.invincible_time > sys.timeSeconds) {
25928
+ self.flags = (self.flags || 0) | 1 /* GODMODE */;
25929
+ } else {
25930
+ self.flags = (self.flags || 0) & ~1 /* GODMODE */;
25931
+ }
25814
25932
  const quadTime = self.client.quad_time || 0;
25815
25933
  const doubleTime = self.client.double_time || 0;
25816
25934
  const soundTime = self.client.quadsound_time || 0;
@@ -25915,106 +26033,6 @@ function populatePlayerStats(player, timeSeconds) {
25915
26033
  return statArray;
25916
26034
  }
25917
26035
 
25918
- // src/save/adapter.ts
25919
- function createSerializedGameState(context) {
25920
- const { entitySystem, levelClock, random: random5 } = context;
25921
- const player = entitySystem.find((e) => e.classname === "player");
25922
- const sysSnapshot = entitySystem.createSnapshot();
25923
- const playerState = {
25924
- origin: player ? { ...player.origin } : { x: 0, y: 0, z: 0 },
25925
- velocity: player ? { ...player.velocity } : { x: 0, y: 0, z: 0 },
25926
- viewAngles: player ? { ...player.angles } : { x: 0, y: 0, z: 0 },
25927
- onGround: player ? player.groundentity !== null : false,
25928
- waterLevel: player ? player.waterlevel : 0,
25929
- mins: player ? { ...player.mins } : { x: -16, y: -16, z: -24 },
25930
- maxs: player ? { ...player.maxs } : { x: 16, y: 16, z: 32 },
25931
- damageAlpha: player?.client?.damage_alpha ?? 0,
25932
- damageIndicators: [],
25933
- // Transient
25934
- blend: [0, 0, 0, 0],
25935
- // Transient
25936
- stats: player ? populatePlayerStats(player, levelClock.current.timeSeconds) : [],
25937
- kick_angles: player?.client?.kick_angles ?? { x: 0, y: 0, z: 0 },
25938
- kick_origin: player?.client?.kick_origin ?? { x: 0, y: 0, z: 0 },
25939
- gunoffset: { x: 0, y: 0, z: 0 },
25940
- gunangles: { x: 0, y: 0, z: 0 },
25941
- gunindex: 0,
25942
- // Q2 Network Compatibility
25943
- pm_type: player?.client?.pm_type ?? 0,
25944
- pm_time: player?.client?.pm_time ?? 0,
25945
- pm_flags: player?.client?.pm_flags ?? 0,
25946
- gun_frame: player?.client?.gun_frame ?? 0,
25947
- rdflags: player?.client?.rdflags ?? 0,
25948
- fov: player?.client?.fov ?? 90,
25949
- renderfx: player?.renderfx ?? 0
25950
- };
25951
- return {
25952
- mapName: entitySystem.level.mapname || "unknown",
25953
- playerState,
25954
- entities: sysSnapshot.entities,
25955
- levelState: sysSnapshot.level,
25956
- time: levelClock.current.timeSeconds,
25957
- playerInventory: player?.client?.inventory ? serializePlayerInventory(player.client.inventory) : void 0,
25958
- rngState: random5?.getState(),
25959
- _internalSnapshot: sysSnapshot
25960
- };
25961
- }
25962
- function applySerializedGameState(state, context) {
25963
- const { entitySystem, levelClock, random: random5 } = context;
25964
- levelClock.restore({
25965
- frameNumber: 0,
25966
- // Unknown in this format, reset to 0
25967
- timeSeconds: state.time,
25968
- previousTimeSeconds: state.time,
25969
- deltaSeconds: 0
25970
- });
25971
- if (random5 && state.rngState) {
25972
- random5.setState(state.rngState);
25973
- }
25974
- if (state._internalSnapshot) {
25975
- entitySystem.restore(state._internalSnapshot);
25976
- } else {
25977
- console.warn("Restoring from partial SerializedGameState. Thinks and Pool state may be lost.");
25978
- const partialSnapshot = {
25979
- timeSeconds: state.time,
25980
- pool: {
25981
- capacity: state.entities.length + 32,
25982
- // Estimate
25983
- activeOrder: state.entities.map((e) => e.index),
25984
- // Naive
25985
- freeList: [],
25986
- // Assume none
25987
- pendingFree: []
25988
- },
25989
- entities: state.entities,
25990
- thinks: [],
25991
- // LOST
25992
- awareness: {
25993
- frameNumber: 0,
25994
- sightEntityIndex: null,
25995
- sightEntityFrame: 0,
25996
- soundEntityIndex: null,
25997
- soundEntityFrame: 0,
25998
- sound2EntityIndex: null,
25999
- sound2EntityFrame: 0,
26000
- sightClientIndex: null
26001
- },
26002
- crossLevelFlags: 0,
26003
- crossUnitFlags: 0,
26004
- level: state.levelState
26005
- };
26006
- entitySystem.restore(partialSnapshot);
26007
- }
26008
- const player = entitySystem.find((e) => e.classname === "player");
26009
- if (player && state.playerInventory) {
26010
- const inventory = deserializePlayerInventory(state.playerInventory);
26011
- player.client = player.client || {};
26012
- if (player.client) {
26013
- player.client.inventory = inventory;
26014
- }
26015
- }
26016
- }
26017
-
26018
26036
  // src/combat/weapon.ts
26019
26037
  var WeaponType = /* @__PURE__ */ ((WeaponType2) => {
26020
26038
  WeaponType2[WeaponType2["BLASTER"] = 0] = "BLASTER";
@@ -26122,6 +26140,106 @@ var WEAPONS = {
26122
26140
  }
26123
26141
  };
26124
26142
 
26143
+ // src/save/adapter.ts
26144
+ function createSerializedGameState(context) {
26145
+ const { entitySystem, levelClock, random: random5 } = context;
26146
+ const player = entitySystem.find((e) => e.classname === "player");
26147
+ const sysSnapshot = entitySystem.createSnapshot();
26148
+ const playerState = {
26149
+ origin: player ? { ...player.origin } : { x: 0, y: 0, z: 0 },
26150
+ velocity: player ? { ...player.velocity } : { x: 0, y: 0, z: 0 },
26151
+ viewAngles: player ? { ...player.angles } : { x: 0, y: 0, z: 0 },
26152
+ onGround: player ? player.groundentity !== null : false,
26153
+ waterLevel: player ? player.waterlevel : 0,
26154
+ mins: player ? { ...player.mins } : { x: -16, y: -16, z: -24 },
26155
+ maxs: player ? { ...player.maxs } : { x: 16, y: 16, z: 32 },
26156
+ damageAlpha: player?.client?.damage_alpha ?? 0,
26157
+ damageIndicators: [],
26158
+ // Transient
26159
+ blend: [0, 0, 0, 0],
26160
+ // Transient
26161
+ stats: player ? populatePlayerStats(player, levelClock.current.timeSeconds) : [],
26162
+ kick_angles: player?.client?.kick_angles ?? { x: 0, y: 0, z: 0 },
26163
+ kick_origin: player?.client?.kick_origin ?? { x: 0, y: 0, z: 0 },
26164
+ gunoffset: { x: 0, y: 0, z: 0 },
26165
+ gunangles: { x: 0, y: 0, z: 0 },
26166
+ gunindex: 0,
26167
+ // Q2 Network Compatibility
26168
+ pm_type: player?.client?.pm_type ?? 0,
26169
+ pm_time: player?.client?.pm_time ?? 0,
26170
+ pm_flags: player?.client?.pm_flags ?? 0,
26171
+ gun_frame: player?.client?.gun_frame ?? 0,
26172
+ rdflags: player?.client?.rdflags ?? 0,
26173
+ fov: player?.client?.fov ?? 90,
26174
+ renderfx: player?.renderfx ?? 0
26175
+ };
26176
+ return {
26177
+ mapName: entitySystem.level.mapname || "unknown",
26178
+ playerState,
26179
+ entities: sysSnapshot.entities,
26180
+ levelState: sysSnapshot.level,
26181
+ time: levelClock.current.timeSeconds,
26182
+ playerInventory: player?.client?.inventory ? serializePlayerInventory(player.client.inventory) : void 0,
26183
+ rngState: random5?.getState(),
26184
+ _internalSnapshot: sysSnapshot
26185
+ };
26186
+ }
26187
+ function applySerializedGameState(state, context) {
26188
+ const { entitySystem, levelClock, random: random5 } = context;
26189
+ levelClock.restore({
26190
+ frameNumber: 0,
26191
+ // Unknown in this format, reset to 0
26192
+ timeSeconds: state.time,
26193
+ previousTimeSeconds: state.time,
26194
+ deltaSeconds: 0
26195
+ });
26196
+ if (random5 && state.rngState) {
26197
+ random5.setState(state.rngState);
26198
+ }
26199
+ if (state._internalSnapshot) {
26200
+ entitySystem.restore(state._internalSnapshot);
26201
+ } else {
26202
+ console.warn("Restoring from partial SerializedGameState. Thinks and Pool state may be lost.");
26203
+ const partialSnapshot = {
26204
+ timeSeconds: state.time,
26205
+ pool: {
26206
+ capacity: state.entities.length + 32,
26207
+ // Estimate
26208
+ activeOrder: state.entities.map((e) => e.index),
26209
+ // Naive
26210
+ freeList: [],
26211
+ // Assume none
26212
+ pendingFree: []
26213
+ },
26214
+ entities: state.entities,
26215
+ thinks: [],
26216
+ // LOST
26217
+ awareness: {
26218
+ frameNumber: 0,
26219
+ sightEntityIndex: null,
26220
+ sightEntityFrame: 0,
26221
+ soundEntityIndex: null,
26222
+ soundEntityFrame: 0,
26223
+ sound2EntityIndex: null,
26224
+ sound2EntityFrame: 0,
26225
+ sightClientIndex: null
26226
+ },
26227
+ crossLevelFlags: 0,
26228
+ crossUnitFlags: 0,
26229
+ level: state.levelState
26230
+ };
26231
+ entitySystem.restore(partialSnapshot);
26232
+ }
26233
+ const player = entitySystem.find((e) => e.classname === "player");
26234
+ if (player && state.playerInventory) {
26235
+ const inventory = deserializePlayerInventory(state.playerInventory);
26236
+ player.client = player.client || {};
26237
+ if (player.client) {
26238
+ player.client.inventory = inventory;
26239
+ }
26240
+ }
26241
+ }
26242
+
26125
26243
  // src/index.ts
26126
26244
  var ZERO_VEC312 = { x: 0, y: 0, z: 0 };
26127
26245
  function createGame(imports, engine, options) {
@@ -26582,6 +26700,57 @@ function createGame(imports, engine, options) {
26582
26700
  velocity = { ...ZERO_VEC312 };
26583
26701
  }
26584
26702
  frameLoop.reset(state.time * 1e3);
26703
+ },
26704
+ setGodMode(enabled) {
26705
+ const player = entities.find((e) => e.classname === "player");
26706
+ if (player) {
26707
+ if (enabled) {
26708
+ player.flags |= 16 /* GodMode */;
26709
+ } else {
26710
+ player.flags &= ~16 /* GodMode */;
26711
+ }
26712
+ }
26713
+ },
26714
+ setNoclip(enabled) {
26715
+ const player = entities.find((e) => e.classname === "player");
26716
+ if (player) {
26717
+ if (enabled) {
26718
+ player.movetype = 1 /* Noclip */;
26719
+ } else {
26720
+ player.movetype = 4 /* Walk */;
26721
+ }
26722
+ }
26723
+ },
26724
+ setNotarget(enabled) {
26725
+ const player = entities.find((e) => e.classname === "player");
26726
+ if (player) {
26727
+ if (enabled) {
26728
+ player.flags |= 32 /* NoTarget */;
26729
+ } else {
26730
+ player.flags &= ~32 /* NoTarget */;
26731
+ }
26732
+ }
26733
+ },
26734
+ giveItem(itemClassname) {
26735
+ const player = entities.find((e) => e.classname === "player");
26736
+ if (player) {
26737
+ giveItem(player, itemClassname);
26738
+ }
26739
+ },
26740
+ damage(amount) {
26741
+ const player = entities.find((e) => e.classname === "player");
26742
+ if (player) {
26743
+ T_Damage(player, null, null, ZERO_VEC312, player.origin, ZERO_VEC312, amount, 0, 0 /* NONE */, 0 /* UNKNOWN */, levelClock.current.timeSeconds);
26744
+ }
26745
+ },
26746
+ teleport(origin2) {
26747
+ const player = entities.find((e) => e.classname === "player");
26748
+ if (player) {
26749
+ entities.unlink(player);
26750
+ player.origin = { ...origin2 };
26751
+ player.velocity = { ...ZERO_VEC312 };
26752
+ entities.link(player);
26753
+ }
26585
26754
  }
26586
26755
  };
26587
26756
  registerDefaultSpawns(spawnRegistry, gameExports);
@@ -26723,6 +26892,7 @@ export {
26723
26892
  getAmmoItemDefinition,
26724
26893
  getWeaponState,
26725
26894
  giveAmmoItem,
26895
+ giveItem,
26726
26896
  giveWeapon,
26727
26897
  hasAnyDamageFlag,
26728
26898
  hasItem,