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.
@@ -153,6 +153,7 @@ __export(index_exports, {
153
153
  getAmmoItemDefinition: () => getAmmoItemDefinition,
154
154
  getWeaponState: () => getWeaponState,
155
155
  giveAmmoItem: () => giveAmmoItem,
156
+ giveItem: () => giveItem,
156
157
  giveWeapon: () => giveWeapon,
157
158
  hasAnyDamageFlag: () => hasAnyDamageFlag,
158
159
  hasItem: () => hasItem,
@@ -2077,6 +2078,13 @@ var DamageFlags = /* @__PURE__ */ ((DamageFlags2) => {
2077
2078
  DamageFlags2[DamageFlags2["NO_DAMAGE_EFFECTS"] = 1024] = "NO_DAMAGE_EFFECTS";
2078
2079
  return DamageFlags2;
2079
2080
  })(DamageFlags || {});
2081
+ var EntityDamageFlags = /* @__PURE__ */ ((EntityDamageFlags2) => {
2082
+ EntityDamageFlags2[EntityDamageFlags2["GODMODE"] = 1] = "GODMODE";
2083
+ EntityDamageFlags2[EntityDamageFlags2["IMMORTAL"] = 2] = "IMMORTAL";
2084
+ EntityDamageFlags2[EntityDamageFlags2["NO_KNOCKBACK"] = 4] = "NO_KNOCKBACK";
2085
+ EntityDamageFlags2[EntityDamageFlags2["NO_DAMAGE_EFFECTS"] = 8] = "NO_DAMAGE_EFFECTS";
2086
+ return EntityDamageFlags2;
2087
+ })(EntityDamageFlags || {});
2080
2088
  function hasAnyDamageFlag(flags, mask) {
2081
2089
  return (flags & mask) !== 0;
2082
2090
  }
@@ -4063,13 +4071,6 @@ var MulticastType = /* @__PURE__ */ ((MulticastType2) => {
4063
4071
  })(MulticastType || {});
4064
4072
 
4065
4073
  // src/combat/damage.ts
4066
- var EntityDamageFlags = /* @__PURE__ */ ((EntityDamageFlags2) => {
4067
- EntityDamageFlags2[EntityDamageFlags2["GODMODE"] = 1] = "GODMODE";
4068
- EntityDamageFlags2[EntityDamageFlags2["IMMORTAL"] = 2] = "IMMORTAL";
4069
- EntityDamageFlags2[EntityDamageFlags2["NO_KNOCKBACK"] = 4] = "NO_KNOCKBACK";
4070
- EntityDamageFlags2[EntityDamageFlags2["NO_DAMAGE_EFFECTS"] = 8] = "NO_DAMAGE_EFFECTS";
4071
- return EntityDamageFlags2;
4072
- })(EntityDamageFlags || {});
4073
4074
  function getDamageModifier(attacker, time) {
4074
4075
  if (!attacker) {
4075
4076
  return 1;
@@ -4133,6 +4134,18 @@ function T_Damage(targ, inflictor, attacker, dir, point, normal, damage, knockba
4133
4134
  if (!targ.takedamage) {
4134
4135
  return null;
4135
4136
  }
4137
+ const client = targ.client;
4138
+ if (client && client.enviro_time && client.enviro_time > time) {
4139
+ if (mod === 18 /* SLIME */ || mod === 19 /* LAVA */) {
4140
+ return {
4141
+ take: 0,
4142
+ psave: 0,
4143
+ asave: 0,
4144
+ knocked: { x: 0, y: 0, z: 0 },
4145
+ killed: false
4146
+ };
4147
+ }
4148
+ }
4136
4149
  const modifier = getDamageModifier(attacker, time);
4137
4150
  const modifiedDamage = damage * modifier;
4138
4151
  const modifiedKnockback = knockback * modifier;
@@ -5314,8 +5327,14 @@ var EntitySystem = class {
5314
5327
  linkentity(ent) {
5315
5328
  this.imports.linkentity(ent);
5316
5329
  }
5317
- multicast(origin, type, event, ...args) {
5318
- this.imports.multicast(origin, type, event, ...args);
5330
+ link(ent) {
5331
+ this.linkentity(ent);
5332
+ }
5333
+ unlink(ent) {
5334
+ this.spatialGrid.remove(ent);
5335
+ }
5336
+ multicast(origin, type, ServerCommand6, ...args) {
5337
+ this.imports.multicast(origin, type, ServerCommand6, ...args);
5319
5338
  }
5320
5339
  unicast(ent, reliable, event, ...args) {
5321
5340
  this.imports.unicast(ent, reliable, event, ...args);
@@ -9037,12 +9056,49 @@ function fireHyperBlaster(game, player) {
9037
9056
  }
9038
9057
  function fireBlaster(game, player) {
9039
9058
  if (!player.client) return;
9040
- game.multicast(player.origin, 1 /* Pvs */, ServerCommand.muzzleflash, player.index, MZ_BLASTER);
9041
- applyKick(player, -0.5, 0, 0);
9042
- setPlayerAttackAnim(player);
9043
- const { forward, right, up } = angleVectors(player.angles);
9044
- const source = P_ProjectSource(game, player, { x: 8, y: 8, z: -8 }, forward, right, up);
9045
- createBlasterBolt(game.entities, player, source, forward, 15, 1500, 1 /* BLASTER */);
9059
+ if (player.client.buttons & 32) {
9060
+ game.sound(player, 0, "weapons/swing.wav", 1, ATTN_NORM, 0);
9061
+ applyKick(player, -2, 0, 0);
9062
+ setPlayerAttackAnim(player);
9063
+ const { forward, right, up } = angleVectors(player.angles);
9064
+ const source = P_ProjectSource(game, player, { x: 8, y: 8, z: -8 }, forward, right, up);
9065
+ const range = 64;
9066
+ const damage = 50;
9067
+ const kick = 100;
9068
+ const end = { x: source.x + forward.x * range, y: source.y + forward.y * range, z: source.z + forward.z * range };
9069
+ const trace = game.trace(source, null, null, end, player, MASK_SHOT);
9070
+ if (trace.fraction < 1) {
9071
+ if (trace.ent && trace.ent.takedamage) {
9072
+ T_Damage(
9073
+ trace.ent,
9074
+ player,
9075
+ player,
9076
+ forward,
9077
+ trace.endpos,
9078
+ trace.plane ? trace.plane.normal : ZERO_VEC3,
9079
+ damage,
9080
+ kick,
9081
+ 0,
9082
+ 1 /* BLASTER */,
9083
+ game.time,
9084
+ game.multicast
9085
+ );
9086
+ game.sound(player, 0, "weapons/tink1.wav", 1, ATTN_NORM, 0);
9087
+ } else {
9088
+ game.sound(player, 0, "weapons/hithard.wav", 1, ATTN_NORM, 0);
9089
+ if (trace.plane) {
9090
+ game.multicast(trace.endpos, 1 /* Pvs */, ServerCommand.temp_entity, TempEntity.GUNSHOT, trace.endpos, trace.plane.normal);
9091
+ }
9092
+ }
9093
+ }
9094
+ } else {
9095
+ game.multicast(player.origin, 1 /* Pvs */, ServerCommand.muzzleflash, player.index, MZ_BLASTER);
9096
+ applyKick(player, -0.5, 0, 0);
9097
+ setPlayerAttackAnim(player);
9098
+ const { forward, right, up } = angleVectors(player.angles);
9099
+ const source = P_ProjectSource(game, player, { x: 8, y: 8, z: -8 }, forward, right, up);
9100
+ createBlasterBolt(game.entities, player, source, forward, 15, 1500, 1 /* BLASTER */);
9101
+ }
9046
9102
  }
9047
9103
  function fireRocket(game, player) {
9048
9104
  if (!player.client) return;
@@ -9265,7 +9321,7 @@ function Weapon_Generic(ent, FRAME_ACTIVATE_LAST, FRAME_FIRE_LAST, FRAME_IDLE_LA
9265
9321
  return;
9266
9322
  }
9267
9323
  if (client.weaponstate === 0 /* WEAPON_READY */) {
9268
- if (client.buttons & 1) {
9324
+ if (client.buttons & 1 || client.buttons & 32) {
9269
9325
  client.weaponstate = 3 /* WEAPON_FIRING */;
9270
9326
  client.gun_frame = FRAME_ACTIVATE_LAST + 1;
9271
9327
  return;
@@ -10254,6 +10310,64 @@ var FLAG_ITEMS = {
10254
10310
  }
10255
10311
  };
10256
10312
 
10313
+ // src/inventory/give.ts
10314
+ function giveItem(entity, classname) {
10315
+ if (!entity.client) return false;
10316
+ const client = entity.client;
10317
+ const inventory = client.inventory;
10318
+ const time = 0;
10319
+ const weapon = WEAPON_ITEMS[classname];
10320
+ if (weapon) {
10321
+ return pickupWeapon(inventory, weapon, time);
10322
+ }
10323
+ const isAmmo = Object.values(AmmoItemId).includes(classname);
10324
+ if (isAmmo) {
10325
+ const res = giveAmmoItem(inventory, classname);
10326
+ return res.pickedUp;
10327
+ }
10328
+ const healthItem = HEALTH_ITEMS[classname];
10329
+ if (healthItem) {
10330
+ if (canPickupHealth(inventory, entity.health, healthItem)) {
10331
+ const count = healthItem.amount;
10332
+ const max = healthItem.max;
10333
+ if (entity.health < max) {
10334
+ entity.health += count;
10335
+ if (entity.health > max) entity.health = max;
10336
+ return true;
10337
+ }
10338
+ if (classname === "item_health_mega") {
10339
+ if (entity.health < max) {
10340
+ entity.health += count;
10341
+ return true;
10342
+ }
10343
+ return false;
10344
+ }
10345
+ }
10346
+ return false;
10347
+ }
10348
+ const armorItem = ARMOR_ITEMS[classname];
10349
+ if (armorItem) {
10350
+ return pickupArmor(inventory, armorItem, time);
10351
+ }
10352
+ const powerupItem = POWERUP_ITEMS[classname];
10353
+ if (powerupItem) {
10354
+ return pickupPowerup(client, powerupItem, time);
10355
+ }
10356
+ const powerArmorItem = POWER_ARMOR_ITEMS[classname];
10357
+ if (powerArmorItem) {
10358
+ return pickupPowerArmor(inventory, powerArmorItem, time);
10359
+ }
10360
+ const keyItem = KEY_ITEMS[classname];
10361
+ if (keyItem) {
10362
+ return pickupKey(inventory, keyItem, time);
10363
+ }
10364
+ const flagItem = FLAG_ITEMS[classname];
10365
+ if (flagItem) {
10366
+ return pickupFlag(client, flagItem, time);
10367
+ }
10368
+ return false;
10369
+ }
10370
+
10257
10371
  // src/entities/items/common.ts
10258
10372
  function handleItemPickup(game, self, other, respawnTime = 30) {
10259
10373
  if (!game.deathmatch) {
@@ -26010,6 +26124,11 @@ function player_think(self, sys) {
26010
26124
  return;
26011
26125
  }
26012
26126
  const nowMs = sys.timeSeconds * 1e3;
26127
+ if (self.client.invincible_time && self.client.invincible_time > sys.timeSeconds) {
26128
+ self.flags = (self.flags || 0) | 1 /* GODMODE */;
26129
+ } else {
26130
+ self.flags = (self.flags || 0) & ~1 /* GODMODE */;
26131
+ }
26013
26132
  const quadTime = self.client.quad_time || 0;
26014
26133
  const doubleTime = self.client.double_time || 0;
26015
26134
  const soundTime = self.client.quadsound_time || 0;
@@ -26114,106 +26233,6 @@ function populatePlayerStats(player, timeSeconds) {
26114
26233
  return statArray;
26115
26234
  }
26116
26235
 
26117
- // src/save/adapter.ts
26118
- function createSerializedGameState(context) {
26119
- const { entitySystem, levelClock, random: random5 } = context;
26120
- const player = entitySystem.find((e) => e.classname === "player");
26121
- const sysSnapshot = entitySystem.createSnapshot();
26122
- const playerState = {
26123
- origin: player ? { ...player.origin } : { x: 0, y: 0, z: 0 },
26124
- velocity: player ? { ...player.velocity } : { x: 0, y: 0, z: 0 },
26125
- viewAngles: player ? { ...player.angles } : { x: 0, y: 0, z: 0 },
26126
- onGround: player ? player.groundentity !== null : false,
26127
- waterLevel: player ? player.waterlevel : 0,
26128
- mins: player ? { ...player.mins } : { x: -16, y: -16, z: -24 },
26129
- maxs: player ? { ...player.maxs } : { x: 16, y: 16, z: 32 },
26130
- damageAlpha: player?.client?.damage_alpha ?? 0,
26131
- damageIndicators: [],
26132
- // Transient
26133
- blend: [0, 0, 0, 0],
26134
- // Transient
26135
- stats: player ? populatePlayerStats(player, levelClock.current.timeSeconds) : [],
26136
- kick_angles: player?.client?.kick_angles ?? { x: 0, y: 0, z: 0 },
26137
- kick_origin: player?.client?.kick_origin ?? { x: 0, y: 0, z: 0 },
26138
- gunoffset: { x: 0, y: 0, z: 0 },
26139
- gunangles: { x: 0, y: 0, z: 0 },
26140
- gunindex: 0,
26141
- // Q2 Network Compatibility
26142
- pm_type: player?.client?.pm_type ?? 0,
26143
- pm_time: player?.client?.pm_time ?? 0,
26144
- pm_flags: player?.client?.pm_flags ?? 0,
26145
- gun_frame: player?.client?.gun_frame ?? 0,
26146
- rdflags: player?.client?.rdflags ?? 0,
26147
- fov: player?.client?.fov ?? 90,
26148
- renderfx: player?.renderfx ?? 0
26149
- };
26150
- return {
26151
- mapName: entitySystem.level.mapname || "unknown",
26152
- playerState,
26153
- entities: sysSnapshot.entities,
26154
- levelState: sysSnapshot.level,
26155
- time: levelClock.current.timeSeconds,
26156
- playerInventory: player?.client?.inventory ? serializePlayerInventory(player.client.inventory) : void 0,
26157
- rngState: random5?.getState(),
26158
- _internalSnapshot: sysSnapshot
26159
- };
26160
- }
26161
- function applySerializedGameState(state, context) {
26162
- const { entitySystem, levelClock, random: random5 } = context;
26163
- levelClock.restore({
26164
- frameNumber: 0,
26165
- // Unknown in this format, reset to 0
26166
- timeSeconds: state.time,
26167
- previousTimeSeconds: state.time,
26168
- deltaSeconds: 0
26169
- });
26170
- if (random5 && state.rngState) {
26171
- random5.setState(state.rngState);
26172
- }
26173
- if (state._internalSnapshot) {
26174
- entitySystem.restore(state._internalSnapshot);
26175
- } else {
26176
- console.warn("Restoring from partial SerializedGameState. Thinks and Pool state may be lost.");
26177
- const partialSnapshot = {
26178
- timeSeconds: state.time,
26179
- pool: {
26180
- capacity: state.entities.length + 32,
26181
- // Estimate
26182
- activeOrder: state.entities.map((e) => e.index),
26183
- // Naive
26184
- freeList: [],
26185
- // Assume none
26186
- pendingFree: []
26187
- },
26188
- entities: state.entities,
26189
- thinks: [],
26190
- // LOST
26191
- awareness: {
26192
- frameNumber: 0,
26193
- sightEntityIndex: null,
26194
- sightEntityFrame: 0,
26195
- soundEntityIndex: null,
26196
- soundEntityFrame: 0,
26197
- sound2EntityIndex: null,
26198
- sound2EntityFrame: 0,
26199
- sightClientIndex: null
26200
- },
26201
- crossLevelFlags: 0,
26202
- crossUnitFlags: 0,
26203
- level: state.levelState
26204
- };
26205
- entitySystem.restore(partialSnapshot);
26206
- }
26207
- const player = entitySystem.find((e) => e.classname === "player");
26208
- if (player && state.playerInventory) {
26209
- const inventory = deserializePlayerInventory(state.playerInventory);
26210
- player.client = player.client || {};
26211
- if (player.client) {
26212
- player.client.inventory = inventory;
26213
- }
26214
- }
26215
- }
26216
-
26217
26236
  // src/combat/weapon.ts
26218
26237
  var WeaponType = /* @__PURE__ */ ((WeaponType2) => {
26219
26238
  WeaponType2[WeaponType2["BLASTER"] = 0] = "BLASTER";
@@ -26321,6 +26340,106 @@ var WEAPONS = {
26321
26340
  }
26322
26341
  };
26323
26342
 
26343
+ // src/save/adapter.ts
26344
+ function createSerializedGameState(context) {
26345
+ const { entitySystem, levelClock, random: random5 } = context;
26346
+ const player = entitySystem.find((e) => e.classname === "player");
26347
+ const sysSnapshot = entitySystem.createSnapshot();
26348
+ const playerState = {
26349
+ origin: player ? { ...player.origin } : { x: 0, y: 0, z: 0 },
26350
+ velocity: player ? { ...player.velocity } : { x: 0, y: 0, z: 0 },
26351
+ viewAngles: player ? { ...player.angles } : { x: 0, y: 0, z: 0 },
26352
+ onGround: player ? player.groundentity !== null : false,
26353
+ waterLevel: player ? player.waterlevel : 0,
26354
+ mins: player ? { ...player.mins } : { x: -16, y: -16, z: -24 },
26355
+ maxs: player ? { ...player.maxs } : { x: 16, y: 16, z: 32 },
26356
+ damageAlpha: player?.client?.damage_alpha ?? 0,
26357
+ damageIndicators: [],
26358
+ // Transient
26359
+ blend: [0, 0, 0, 0],
26360
+ // Transient
26361
+ stats: player ? populatePlayerStats(player, levelClock.current.timeSeconds) : [],
26362
+ kick_angles: player?.client?.kick_angles ?? { x: 0, y: 0, z: 0 },
26363
+ kick_origin: player?.client?.kick_origin ?? { x: 0, y: 0, z: 0 },
26364
+ gunoffset: { x: 0, y: 0, z: 0 },
26365
+ gunangles: { x: 0, y: 0, z: 0 },
26366
+ gunindex: 0,
26367
+ // Q2 Network Compatibility
26368
+ pm_type: player?.client?.pm_type ?? 0,
26369
+ pm_time: player?.client?.pm_time ?? 0,
26370
+ pm_flags: player?.client?.pm_flags ?? 0,
26371
+ gun_frame: player?.client?.gun_frame ?? 0,
26372
+ rdflags: player?.client?.rdflags ?? 0,
26373
+ fov: player?.client?.fov ?? 90,
26374
+ renderfx: player?.renderfx ?? 0
26375
+ };
26376
+ return {
26377
+ mapName: entitySystem.level.mapname || "unknown",
26378
+ playerState,
26379
+ entities: sysSnapshot.entities,
26380
+ levelState: sysSnapshot.level,
26381
+ time: levelClock.current.timeSeconds,
26382
+ playerInventory: player?.client?.inventory ? serializePlayerInventory(player.client.inventory) : void 0,
26383
+ rngState: random5?.getState(),
26384
+ _internalSnapshot: sysSnapshot
26385
+ };
26386
+ }
26387
+ function applySerializedGameState(state, context) {
26388
+ const { entitySystem, levelClock, random: random5 } = context;
26389
+ levelClock.restore({
26390
+ frameNumber: 0,
26391
+ // Unknown in this format, reset to 0
26392
+ timeSeconds: state.time,
26393
+ previousTimeSeconds: state.time,
26394
+ deltaSeconds: 0
26395
+ });
26396
+ if (random5 && state.rngState) {
26397
+ random5.setState(state.rngState);
26398
+ }
26399
+ if (state._internalSnapshot) {
26400
+ entitySystem.restore(state._internalSnapshot);
26401
+ } else {
26402
+ console.warn("Restoring from partial SerializedGameState. Thinks and Pool state may be lost.");
26403
+ const partialSnapshot = {
26404
+ timeSeconds: state.time,
26405
+ pool: {
26406
+ capacity: state.entities.length + 32,
26407
+ // Estimate
26408
+ activeOrder: state.entities.map((e) => e.index),
26409
+ // Naive
26410
+ freeList: [],
26411
+ // Assume none
26412
+ pendingFree: []
26413
+ },
26414
+ entities: state.entities,
26415
+ thinks: [],
26416
+ // LOST
26417
+ awareness: {
26418
+ frameNumber: 0,
26419
+ sightEntityIndex: null,
26420
+ sightEntityFrame: 0,
26421
+ soundEntityIndex: null,
26422
+ soundEntityFrame: 0,
26423
+ sound2EntityIndex: null,
26424
+ sound2EntityFrame: 0,
26425
+ sightClientIndex: null
26426
+ },
26427
+ crossLevelFlags: 0,
26428
+ crossUnitFlags: 0,
26429
+ level: state.levelState
26430
+ };
26431
+ entitySystem.restore(partialSnapshot);
26432
+ }
26433
+ const player = entitySystem.find((e) => e.classname === "player");
26434
+ if (player && state.playerInventory) {
26435
+ const inventory = deserializePlayerInventory(state.playerInventory);
26436
+ player.client = player.client || {};
26437
+ if (player.client) {
26438
+ player.client.inventory = inventory;
26439
+ }
26440
+ }
26441
+ }
26442
+
26324
26443
  // src/index.ts
26325
26444
  var ZERO_VEC312 = { x: 0, y: 0, z: 0 };
26326
26445
  function createGame(imports, engine, options) {
@@ -26781,6 +26900,57 @@ function createGame(imports, engine, options) {
26781
26900
  velocity = { ...ZERO_VEC312 };
26782
26901
  }
26783
26902
  frameLoop.reset(state.time * 1e3);
26903
+ },
26904
+ setGodMode(enabled) {
26905
+ const player = entities.find((e) => e.classname === "player");
26906
+ if (player) {
26907
+ if (enabled) {
26908
+ player.flags |= 16 /* GodMode */;
26909
+ } else {
26910
+ player.flags &= ~16 /* GodMode */;
26911
+ }
26912
+ }
26913
+ },
26914
+ setNoclip(enabled) {
26915
+ const player = entities.find((e) => e.classname === "player");
26916
+ if (player) {
26917
+ if (enabled) {
26918
+ player.movetype = 1 /* Noclip */;
26919
+ } else {
26920
+ player.movetype = 4 /* Walk */;
26921
+ }
26922
+ }
26923
+ },
26924
+ setNotarget(enabled) {
26925
+ const player = entities.find((e) => e.classname === "player");
26926
+ if (player) {
26927
+ if (enabled) {
26928
+ player.flags |= 32 /* NoTarget */;
26929
+ } else {
26930
+ player.flags &= ~32 /* NoTarget */;
26931
+ }
26932
+ }
26933
+ },
26934
+ giveItem(itemClassname) {
26935
+ const player = entities.find((e) => e.classname === "player");
26936
+ if (player) {
26937
+ giveItem(player, itemClassname);
26938
+ }
26939
+ },
26940
+ damage(amount) {
26941
+ const player = entities.find((e) => e.classname === "player");
26942
+ if (player) {
26943
+ T_Damage(player, null, null, ZERO_VEC312, player.origin, ZERO_VEC312, amount, 0, 0 /* NONE */, 0 /* UNKNOWN */, levelClock.current.timeSeconds);
26944
+ }
26945
+ },
26946
+ teleport(origin2) {
26947
+ const player = entities.find((e) => e.classname === "player");
26948
+ if (player) {
26949
+ entities.unlink(player);
26950
+ player.origin = { ...origin2 };
26951
+ player.velocity = { ...ZERO_VEC312 };
26952
+ entities.link(player);
26953
+ }
26784
26954
  }
26785
26955
  };
26786
26956
  registerDefaultSpawns(spawnRegistry, gameExports);
@@ -26923,6 +27093,7 @@ function createGame(imports, engine, options) {
26923
27093
  getAmmoItemDefinition,
26924
27094
  getWeaponState,
26925
27095
  giveAmmoItem,
27096
+ giveItem,
26926
27097
  giveWeapon,
26927
27098
  hasAnyDamageFlag,
26928
27099
  hasItem,