quake2ts 0.0.263 → 0.0.268

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 (53) hide show
  1. package/package.json +1 -1
  2. package/packages/client/dist/browser/index.global.js +13 -13
  3. package/packages/client/dist/browser/index.global.js.map +1 -1
  4. package/packages/client/dist/cjs/index.cjs +31 -18
  5. package/packages/client/dist/cjs/index.cjs.map +1 -1
  6. package/packages/client/dist/esm/index.js +31 -18
  7. package/packages/client/dist/esm/index.js.map +1 -1
  8. package/packages/client/dist/tsconfig.tsbuildinfo +1 -1
  9. package/packages/engine/dist/browser/index.global.js +6 -6
  10. package/packages/engine/dist/browser/index.global.js.map +1 -1
  11. package/packages/engine/dist/cjs/index.cjs +25 -12
  12. package/packages/engine/dist/cjs/index.cjs.map +1 -1
  13. package/packages/engine/dist/esm/index.js +25 -12
  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/demo/parser.d.ts +2 -0
  17. package/packages/engine/dist/types/demo/parser.d.ts.map +1 -1
  18. package/packages/engine/dist/types/demo/playback.d.ts +1 -0
  19. package/packages/engine/dist/types/demo/playback.d.ts.map +1 -1
  20. package/packages/game/dist/browser/index.global.js +3 -2
  21. package/packages/game/dist/browser/index.global.js.map +1 -1
  22. package/packages/game/dist/cjs/index.cjs +1234 -381
  23. package/packages/game/dist/cjs/index.cjs.map +1 -1
  24. package/packages/game/dist/esm/index.js +1234 -381
  25. package/packages/game/dist/esm/index.js.map +1 -1
  26. package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
  27. package/packages/game/dist/types/combat/weapons/animation.d.ts +9 -0
  28. package/packages/game/dist/types/combat/weapons/animation.d.ts.map +1 -1
  29. package/packages/game/dist/types/combat/weapons/firing.d.ts.map +1 -1
  30. package/packages/game/dist/types/combat/weapons/switching.d.ts +1 -0
  31. package/packages/game/dist/types/combat/weapons/switching.d.ts.map +1 -1
  32. package/packages/game/dist/types/entities/entity.d.ts +2 -1
  33. package/packages/game/dist/types/entities/entity.d.ts.map +1 -1
  34. package/packages/game/dist/types/entities/monsters/actor.d.ts +6 -0
  35. package/packages/game/dist/types/entities/monsters/actor.d.ts.map +1 -0
  36. package/packages/game/dist/types/entities/monsters/index.d.ts.map +1 -1
  37. package/packages/game/dist/types/entities/monsters/jorg.d.ts.map +1 -1
  38. package/packages/game/dist/types/entities/monsters/makron.d.ts.map +1 -1
  39. package/packages/game/dist/types/entities/player.d.ts +2 -0
  40. package/packages/game/dist/types/entities/player.d.ts.map +1 -1
  41. package/packages/game/dist/types/entities/player_anim.d.ts +50 -0
  42. package/packages/game/dist/types/entities/player_anim.d.ts.map +1 -0
  43. package/packages/game/dist/types/entities/targets.d.ts.map +1 -1
  44. package/packages/game/dist/types/index.d.ts.map +1 -1
  45. package/packages/shared/dist/browser/index.global.js +1 -1
  46. package/packages/shared/dist/browser/index.global.js.map +1 -1
  47. package/packages/shared/dist/cjs/index.cjs +36 -12
  48. package/packages/shared/dist/cjs/index.cjs.map +1 -1
  49. package/packages/shared/dist/esm/index.js +36 -12
  50. package/packages/shared/dist/esm/index.js.map +1 -1
  51. package/packages/shared/dist/tsconfig.tsbuildinfo +1 -1
  52. package/packages/shared/dist/types/pmove/apply.d.ts.map +1 -1
  53. package/packages/shared/dist/types/pmove/pmove.d.ts.map +1 -1
@@ -294,15 +294,15 @@ function rotatePointAroundVector(dir, point, degrees) {
294
294
  const vf = normalizeVec3(dir);
295
295
  const vr = perpendicularVec3(vf);
296
296
  const vup = crossVec3(vr, vf);
297
- const m2 = [
297
+ const m3 = [
298
298
  [vr.x, vup.x, vf.x],
299
299
  [vr.y, vup.y, vf.y],
300
300
  [vr.z, vup.z, vf.z]
301
301
  ];
302
302
  const im = [
303
- [m2[0][0], m2[1][0], m2[2][0]],
304
- [m2[0][1], m2[1][1], m2[2][1]],
305
- [m2[0][2], m2[1][2], m2[2][2]]
303
+ [m3[0][0], m3[1][0], m3[2][0]],
304
+ [m3[0][1], m3[1][1], m3[2][1]],
305
+ [m3[0][2], m3[1][2], m3[2][2]]
306
306
  ];
307
307
  const radians = degrees * DEG_TO_RAD;
308
308
  const cos = Math.cos(radians);
@@ -312,7 +312,7 @@ function rotatePointAroundVector(dir, point, degrees) {
312
312
  [-sin, cos, 0],
313
313
  [0, 0, 1]
314
314
  ];
315
- const rot = concatRotationMatrices(concatRotationMatrices(m2, zrot), im);
315
+ const rot = concatRotationMatrices(concatRotationMatrices(m3, zrot), im);
316
316
  return {
317
317
  x: rot[0][0] * point.x + rot[0][1] * point.y + rot[0][2] * point.z,
318
318
  y: rot[1][0] * point.x + rot[1][1] * point.y + rot[1][2] * point.z,
@@ -678,12 +678,12 @@ function addReplayFrame(session, cmd, serverFrame, startTime) {
678
678
  timestamp: Date.now() - startTime
679
679
  });
680
680
  }
681
- var WaterLevel = /* @__PURE__ */ ((WaterLevel3) => {
682
- WaterLevel3[WaterLevel3["None"] = 0] = "None";
683
- WaterLevel3[WaterLevel3["Feet"] = 1] = "Feet";
684
- WaterLevel3[WaterLevel3["Waist"] = 2] = "Waist";
685
- WaterLevel3[WaterLevel3["Under"] = 3] = "Under";
686
- return WaterLevel3;
681
+ var WaterLevel = /* @__PURE__ */ ((WaterLevel4) => {
682
+ WaterLevel4[WaterLevel4["None"] = 0] = "None";
683
+ WaterLevel4[WaterLevel4["Feet"] = 1] = "Feet";
684
+ WaterLevel4[WaterLevel4["Waist"] = 2] = "Waist";
685
+ WaterLevel4[WaterLevel4["Under"] = 3] = "Under";
686
+ return WaterLevel4;
687
687
  })(WaterLevel || {});
688
688
  function applyPmoveFriction(params) {
689
689
  const {
@@ -760,12 +760,14 @@ function buildWaterWish(params) {
760
760
  let wishvel = {
761
761
  x: forward.x * cmd.forwardmove + right.x * cmd.sidemove,
762
762
  y: forward.y * cmd.forwardmove + right.y * cmd.sidemove,
763
- z: 0
763
+ z: forward.z * cmd.forwardmove + right.z * cmd.sidemove
764
764
  };
765
765
  if (cmd.upmove > 10) {
766
766
  wishvel = addVec3(wishvel, { x: 0, y: 0, z: cmd.upmove });
767
767
  } else if (cmd.upmove < -10) {
768
768
  wishvel = addVec3(wishvel, { x: 0, y: 0, z: cmd.upmove });
769
+ } else if (Math.abs(cmd.forwardmove) < 10 && Math.abs(cmd.sidemove) < 10) {
770
+ wishvel = addVec3(wishvel, { x: 0, y: 0, z: -60 });
769
771
  } else {
770
772
  wishvel = addVec3(wishvel, { x: 0, y: 0, z: 10 });
771
773
  }
@@ -1153,6 +1155,13 @@ var U_MODEL3 = 1 << 1;
1153
1155
  var U_MODEL4 = 1 << 2;
1154
1156
  var U_REMOVE = 32768;
1155
1157
  var FRAMETIME = 0.025;
1158
+ var MASK_WATER2 = 33554432;
1159
+ var WaterLevel3 = {
1160
+ None: 0,
1161
+ Feet: 1,
1162
+ Waist: 2,
1163
+ Under: 3
1164
+ };
1156
1165
  var categorizePosition2 = (state, trace) => {
1157
1166
  const point = { ...state.origin };
1158
1167
  point.z -= 0.25;
@@ -1164,12 +1173,26 @@ var categorizePosition2 = (state, trace) => {
1164
1173
  };
1165
1174
  var checkWater = (state, pointContents2) => {
1166
1175
  const point = { ...state.origin };
1167
- point.z += state.mins.z + 1;
1176
+ const { mins, maxs } = state;
1177
+ point.z = state.origin.z + mins.z + 1;
1168
1178
  const contents = pointContents2(point);
1169
- if (contents & 33554432) {
1170
- return { ...state, waterLevel: 1 };
1171
- }
1172
- return { ...state, waterLevel: 0 };
1179
+ if (!(contents & MASK_WATER2)) {
1180
+ return { ...state, waterLevel: WaterLevel3.None };
1181
+ }
1182
+ let waterLevel = WaterLevel3.Feet;
1183
+ const waist = state.origin.z + (mins.z + maxs.z) * 0.5;
1184
+ point.z = waist;
1185
+ const waistContents = pointContents2(point);
1186
+ if (waistContents & MASK_WATER2) {
1187
+ waterLevel = WaterLevel3.Waist;
1188
+ const head = state.origin.z + 22;
1189
+ point.z = head;
1190
+ const headContents = pointContents2(point);
1191
+ if (headContents & MASK_WATER2) {
1192
+ waterLevel = WaterLevel3.Under;
1193
+ }
1194
+ }
1195
+ return { ...state, waterLevel };
1173
1196
  };
1174
1197
  var applyPmove = (state, cmd, trace, pointContents2) => {
1175
1198
  let newState = { ...state };
@@ -1209,7 +1232,8 @@ var applyPmove = (state, cmd, trace, pointContents2) => {
1209
1232
  velocity: frictionedVelocity,
1210
1233
  wishdir: wish.wishdir,
1211
1234
  wishspeed: wish.wishspeed,
1212
- accel: onGround ? 10 : 1,
1235
+ // Water movement uses ground acceleration (10), not air acceleration (1)
1236
+ accel: onGround || waterLevel >= 2 ? 10 : 1,
1213
1237
  frametime: FRAMETIME
1214
1238
  });
1215
1239
  const traceResult = trace(origin, {
@@ -4600,6 +4624,131 @@ function useTargetBlaster(self, other, activator, context) {
4600
4624
  }
4601
4625
  context.entities.sound(self, 2, "weapons/laser2.wav", 1, ATTN_NORM, 0);
4602
4626
  }
4627
+ var TARGET_LASER_START_ON = 1;
4628
+ var TARGET_LASER_RED = 2;
4629
+ var TARGET_LASER_GREEN = 4;
4630
+ var TARGET_LASER_BLUE = 8;
4631
+ var TARGET_LASER_YELLOW = 16;
4632
+ var TARGET_LASER_ORANGE = 32;
4633
+ var TARGET_LASER_FAT = 64;
4634
+ function target_laser_think(self, context) {
4635
+ let count;
4636
+ if (self.spawnflags & 2147483648) {
4637
+ count = 8;
4638
+ } else {
4639
+ count = 4;
4640
+ }
4641
+ if (self.enemy) {
4642
+ const last_movedir = { ...self.movedir };
4643
+ const size = subtractVec3(self.enemy.maxs, self.enemy.mins);
4644
+ const centerOffset = scaleVec3(size, 0.5);
4645
+ const enemyCenter = addVec3(self.enemy.mins, centerOffset);
4646
+ const dir = subtractVec3(enemyCenter, self.origin);
4647
+ self.movedir = normalizeVec3(dir);
4648
+ if (Math.abs(self.movedir.x - last_movedir.x) > 1e-3 || Math.abs(self.movedir.y - last_movedir.y) > 1e-3 || Math.abs(self.movedir.z - last_movedir.z) > 1e-3) {
4649
+ self.spawnflags |= 2147483648;
4650
+ }
4651
+ }
4652
+ let ignore = self;
4653
+ let start = { ...self.origin };
4654
+ const end = addVec3(start, scaleVec3(self.movedir, 2048));
4655
+ let traceResult;
4656
+ while (true) {
4657
+ traceResult = context.entities.trace(start, end, ZERO_VEC3, ZERO_VEC3, ignore, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_DEADMONSTER);
4658
+ if (!traceResult.ent) {
4659
+ break;
4660
+ }
4661
+ const trEnt = traceResult.ent;
4662
+ if (trEnt.takedamage && !(trEnt.flags & 2)) {
4663
+ T_Damage(trEnt, self, self.activator, self.movedir, traceResult.endpos, ZERO_VEC3, self.dmg, 1, 4 /* ENERGY */, 31 /* TARGET_LASER */, context.entities.timeSeconds);
4664
+ }
4665
+ if (!(trEnt.svflags & 1) && !trEnt.client) {
4666
+ if (self.spawnflags & 2147483648) {
4667
+ self.spawnflags &= ~2147483648;
4668
+ context.entities.multicast(traceResult.endpos, 1 /* Pvs */, ServerCommand.temp_entity, TempEntity.LASER_SPARKS, count, traceResult.endpos, traceResult.plane?.normal || ZERO_VEC3, self.skin);
4669
+ }
4670
+ break;
4671
+ }
4672
+ ignore = trEnt;
4673
+ start = { ...traceResult.endpos };
4674
+ }
4675
+ self.old_origin = { ...traceResult.endpos };
4676
+ self.nextthink = context.entities.timeSeconds + 0.1;
4677
+ }
4678
+ function target_laser_on(self, context) {
4679
+ if (!self.activator) {
4680
+ self.activator = self;
4681
+ }
4682
+ self.spawnflags |= 2147483649;
4683
+ self.svflags &= ~1 /* NoClient */;
4684
+ target_laser_think(self, context);
4685
+ }
4686
+ function target_laser_off(self) {
4687
+ self.spawnflags &= ~1;
4688
+ self.svflags |= 1 /* NoClient */;
4689
+ self.nextthink = 0;
4690
+ }
4691
+ function target_laser_use(self, other, activator, context) {
4692
+ self.activator = activator;
4693
+ if (self.spawnflags & 1) {
4694
+ target_laser_off(self);
4695
+ } else {
4696
+ target_laser_on(self, context);
4697
+ }
4698
+ }
4699
+ function target_laser_start(self, context) {
4700
+ self.movetype = 0 /* None */;
4701
+ self.solid = 0 /* Not */;
4702
+ self.renderfx |= 8 | 64;
4703
+ self.modelindex = 1;
4704
+ if (self.spawnflags & TARGET_LASER_FAT) {
4705
+ self.frame = 16;
4706
+ } else {
4707
+ self.frame = 4;
4708
+ }
4709
+ if (self.spawnflags & TARGET_LASER_RED) {
4710
+ self.skin = 4076007664;
4711
+ } else if (self.spawnflags & TARGET_LASER_GREEN) {
4712
+ self.skin = 3503411923;
4713
+ } else if (self.spawnflags & TARGET_LASER_BLUE) {
4714
+ self.skin = 4092850673;
4715
+ } else if (self.spawnflags & TARGET_LASER_YELLOW) {
4716
+ self.skin = 3705528031;
4717
+ } else if (self.spawnflags & TARGET_LASER_ORANGE) {
4718
+ self.skin = 3772900067;
4719
+ }
4720
+ if (!self.enemy) {
4721
+ if (self.target) {
4722
+ let found = null;
4723
+ context.entities.forEachEntity((ent) => {
4724
+ if (ent.targetname === self.target) {
4725
+ found = ent;
4726
+ }
4727
+ });
4728
+ if (found) {
4729
+ self.enemy = found;
4730
+ } else {
4731
+ context.warn(`${self.classname} at ${self.origin}: ${self.target} is a bad target`);
4732
+ self.movedir = setMovedir(self.angles);
4733
+ }
4734
+ } else {
4735
+ self.movedir = setMovedir(self.angles);
4736
+ }
4737
+ }
4738
+ self.use = (s, o, a) => target_laser_use(s, o, a || null, context);
4739
+ self.think = (s) => target_laser_think(s, context);
4740
+ if (!self.dmg) {
4741
+ self.dmg = 1;
4742
+ }
4743
+ self.absmin = addVec3(self.origin, { x: -8, y: -8, z: -8 });
4744
+ self.absmax = addVec3(self.origin, { x: 8, y: 8, z: 8 });
4745
+ context.entities.linkentity(self);
4746
+ if (self.spawnflags & TARGET_LASER_START_ON) {
4747
+ target_laser_on(self, context);
4748
+ } else {
4749
+ target_laser_off(self);
4750
+ }
4751
+ }
4603
4752
  function registerTargetSpawns(registry) {
4604
4753
  registry.register("target_temp_entity", (entity, context) => {
4605
4754
  entity.style = context.keyValues.style ? parseInt(context.keyValues.style) : 0;
@@ -4682,6 +4831,10 @@ function registerTargetSpawns(registry) {
4682
4831
  if (!entity.speed) entity.speed = 1e3;
4683
4832
  entity.svflags |= 1 /* NoClient */;
4684
4833
  });
4834
+ registry.register("target_laser", (entity, context) => {
4835
+ entity.think = (self) => target_laser_start(self, context);
4836
+ entity.nextthink = context.entities.timeSeconds + 1;
4837
+ });
4685
4838
  }
4686
4839
 
4687
4840
  // src/entities/triggers.ts
@@ -10101,11 +10254,11 @@ function registerInfantrySpawns(registry) {
10101
10254
  registry.register("monster_infantry", SP_monster_infantry);
10102
10255
  }
10103
10256
 
10104
- // src/entities/monsters/jorg.ts
10257
+ // src/entities/monsters/makron.ts
10105
10258
  var MONSTER_TICK13 = 0.1;
10106
- var JORG_MACHINEGUN_R1_OFFSET = { x: 40, y: -20, z: 20 };
10107
- var JORG_MACHINEGUN_L1_OFFSET = { x: 40, y: 20, z: 20 };
10108
- var JORG_BFG_OFFSET = { x: 30, y: 0, z: 40 };
10259
+ var MAKRON_BFG_OFFSET = { x: 30, y: 28, z: 24 };
10260
+ var MAKRON_BLASTER_OFFSET_1 = { x: 26, y: 16, z: 24 };
10261
+ var MAKRON_RAILGUN_OFFSET = { x: 26, y: -14, z: 24 };
10109
10262
  function monster_ai_stand13(self, dist, context) {
10110
10263
  ai_stand(self, MONSTER_TICK13, context);
10111
10264
  }
@@ -10124,49 +10277,36 @@ function monster_ai_move13(self, dist, context) {
10124
10277
  var stand_move12;
10125
10278
  var walk_move11;
10126
10279
  var run_move11;
10127
- var attack1_move3;
10128
- var attack1_end_move;
10129
- var attack2_move2;
10130
- var pain1_move5;
10131
- var pain2_move5;
10132
- var pain3_move4;
10280
+ var attack_bfg_move;
10281
+ var attack_hyperblaster_move;
10282
+ var attack_railgun_move;
10283
+ var pain4_move;
10284
+ var pain5_move;
10285
+ var pain6_move;
10133
10286
  var death_move10;
10134
- function jorg_stand(self) {
10287
+ var sight_move;
10288
+ function makron_stand(self) {
10135
10289
  self.monsterinfo.current_move = stand_move12;
10136
10290
  }
10137
- function jorg_walk(self) {
10291
+ function makron_walk(self) {
10138
10292
  self.monsterinfo.current_move = walk_move11;
10139
10293
  }
10140
- function jorg_run(self) {
10294
+ function makron_run(self) {
10141
10295
  if (self.enemy && self.enemy.health > 0) {
10142
10296
  self.monsterinfo.current_move = run_move11;
10143
10297
  } else {
10144
10298
  self.monsterinfo.current_move = stand_move12;
10145
10299
  }
10146
10300
  }
10147
- function jorg_attack(self, context) {
10301
+ function makron_attack(self) {
10148
10302
  if (!self.enemy) return;
10149
- if (Math.random() <= 0.75) {
10150
- context.sound(self, 0, "boss3/bs3atck1.wav", 1, 1, 0);
10151
- self.monsterinfo.current_move = attack1_move3;
10152
- } else {
10153
- context.sound(self, 0, "boss3/bs3atck2.wav", 1, 1, 0);
10154
- self.monsterinfo.current_move = attack2_move2;
10155
- }
10156
- }
10157
- function jorg_reattack1(self, context) {
10158
- const traceFn = (start, mins, maxs, end, ignore, mask) => {
10159
- const tr = context.trace(start, mins, maxs, end, ignore, mask);
10160
- return { fraction: tr.fraction, ent: tr.ent };
10161
- };
10162
- if (self.enemy && visible(self, self.enemy, traceFn)) {
10163
- if (Math.random() < 0.9) {
10164
- self.monsterinfo.current_move = attack1_move3;
10165
- } else {
10166
- self.monsterinfo.current_move = attack1_end_move;
10167
- }
10303
+ const r = Math.random();
10304
+ if (r <= 0.3) {
10305
+ self.monsterinfo.current_move = attack_bfg_move;
10306
+ } else if (r <= 0.6) {
10307
+ self.monsterinfo.current_move = attack_hyperblaster_move;
10168
10308
  } else {
10169
- self.monsterinfo.current_move = attack1_end_move;
10309
+ self.monsterinfo.current_move = attack_railgun_move;
10170
10310
  }
10171
10311
  }
10172
10312
  function getProjectedOffset2(self, offset) {
@@ -10177,136 +10317,408 @@ function getProjectedOffset2(self, offset) {
10177
10317
  const z = scaleVec3(up, offset.z);
10178
10318
  return addVec3(addVec3(addVec3(start, x), y), z);
10179
10319
  }
10180
- function jorg_fire_bullet(self, context) {
10181
- if (!self.enemy) return;
10182
- const startL = getProjectedOffset2(self, JORG_MACHINEGUN_L1_OFFSET);
10183
- const dirL = normalizeVec3(subtractVec3(self.enemy.origin, startL));
10184
- monster_fire_bullet_v2(self, startL, dirL, 6, 4, 0.05, 0.05, 0, context, 4 /* MACHINEGUN */);
10185
- const startR = getProjectedOffset2(self, JORG_MACHINEGUN_R1_OFFSET);
10186
- const dirR = normalizeVec3(subtractVec3(self.enemy.origin, startR));
10187
- monster_fire_bullet_v2(self, startR, dirR, 6, 4, 0.05, 0.05, 0, context, 4 /* MACHINEGUN */);
10188
- }
10189
- function jorg_fire_bfg(self, context) {
10320
+ function makron_fire_bfg(self, context) {
10190
10321
  if (!self.enemy) return;
10191
- const start = getProjectedOffset2(self, JORG_BFG_OFFSET);
10322
+ context.engine.sound?.(self, 0, "makron/bfg_fire.wav", 1, 1, 0);
10323
+ const start = getProjectedOffset2(self, MAKRON_BFG_OFFSET);
10192
10324
  const target = { ...self.enemy.origin };
10193
10325
  target.z += self.enemy.viewheight || 0;
10194
10326
  const dir = normalizeVec3(subtractVec3(target, start));
10195
- monster_fire_bfg(self, start, dir, 50, 300, 100, 200, 0, context);
10327
+ monster_fire_bfg(self, start, dir, 50, 300, 100, 300, 0, context);
10196
10328
  }
10197
- function jorg_pain(self, other, kick, damage, context) {
10329
+ function makron_fire_railgun(self, context) {
10330
+ if (!self.pos1) return;
10331
+ context.engine.sound?.(self, 0, "makron/rail_fire.wav", 1, 1, 0);
10332
+ const start = getProjectedOffset2(self, MAKRON_RAILGUN_OFFSET);
10333
+ const dir = normalizeVec3(subtractVec3(self.pos1, start));
10334
+ monster_fire_railgun(self, start, dir, 50, 100, 0, context);
10335
+ }
10336
+ function makron_save_loc(self) {
10337
+ if (!self.enemy) return;
10338
+ self.pos1 = { ...self.enemy.origin };
10339
+ self.pos1 = { ...self.pos1, z: self.pos1.z + (self.enemy.viewheight || 0) };
10340
+ }
10341
+ function makron_fire_hyperblaster(self, context) {
10342
+ context.engine.sound?.(self, 0, "makron/blaster.wav", 1, 1, 0);
10343
+ const start = getProjectedOffset2(self, MAKRON_BLASTER_OFFSET_1);
10344
+ const relFrame = (self.monsterinfo.nextframe || 0) - attack_hyperblaster_move.firstframe;
10345
+ let yawDelta = 0;
10346
+ let dir;
10347
+ if (self.enemy) {
10348
+ const target = { ...self.enemy.origin };
10349
+ target.z += self.enemy.viewheight || 0;
10350
+ const vec = subtractVec3(target, start);
10351
+ const baseAngles = vectorToAngles(vec);
10352
+ const enemyAngles = { ...baseAngles };
10353
+ if (relFrame <= 12) {
10354
+ enemyAngles.y -= 5 * (relFrame - 4);
10355
+ } else {
10356
+ enemyAngles.y -= 40 - 5 * (relFrame - 12);
10357
+ }
10358
+ const forward = angleVectors(enemyAngles).forward;
10359
+ dir = forward;
10360
+ } else {
10361
+ const { forward } = angleVectors(self.angles);
10362
+ dir = forward;
10363
+ }
10364
+ monster_fire_blaster(self, start, dir, 15, 1e3, 0, 0, context, 1 /* BLASTER */);
10365
+ }
10366
+ function makron_pain(self, other, kick, damage, context) {
10198
10367
  if (self.health < self.max_health / 2) {
10199
10368
  self.skin = 1;
10200
10369
  }
10201
10370
  if (self.timestamp < (self.pain_finished_time || 0)) return;
10202
- if (damage <= 40 && Math.random() <= 0.6) return;
10203
- if (self.monsterinfo.current_move === attack1_move3 || self.monsterinfo.current_move === attack2_move2) {
10204
- if (Math.random() <= 5e-3) return;
10205
- }
10371
+ if (damage <= 25 && Math.random() < 0.2) return;
10206
10372
  self.pain_finished_time = self.timestamp + 3;
10207
- if (damage <= 50) {
10208
- context.engine.sound?.(self, 0, "boss3/bs3pain1.wav", 1, 1, 0);
10209
- self.monsterinfo.current_move = pain1_move5;
10210
- } else if (damage <= 100) {
10211
- context.engine.sound?.(self, 0, "boss3/bs3pain2.wav", 1, 1, 0);
10212
- self.monsterinfo.current_move = pain2_move5;
10373
+ if (damage <= 40) {
10374
+ context.engine.sound?.(self, 0, "makron/pain1.wav", 1, 1, 0);
10375
+ self.monsterinfo.current_move = pain4_move;
10376
+ } else if (damage <= 110) {
10377
+ context.engine.sound?.(self, 0, "makron/pain2.wav", 1, 1, 0);
10378
+ self.monsterinfo.current_move = pain5_move;
10213
10379
  } else {
10214
- if (Math.random() <= 0.3) {
10215
- context.engine.sound?.(self, 0, "boss3/bs3pain3.wav", 1, 1, 0);
10216
- self.monsterinfo.current_move = pain3_move4;
10380
+ if (Math.random() <= 0.45) {
10381
+ context.engine.sound?.(self, 0, "makron/pain3.wav", 1, 1, 0);
10382
+ self.monsterinfo.current_move = pain6_move;
10217
10383
  }
10218
10384
  }
10219
10385
  }
10220
- function jorg_die(self, context) {
10221
- context.engine.sound?.(self, 0, "boss3/bs3deth1.wav", 1, 1, 0);
10386
+ function makron_torso_think(self, context) {
10387
+ if (++self.frame >= 365)
10388
+ self.frame = 346;
10389
+ self.nextthink = context.timeSeconds + 0.1;
10390
+ if (self.angles.x > 0)
10391
+ self.angles = { ...self.angles, x: Math.max(0, self.angles.x - 15) };
10392
+ }
10393
+ function makron_torso(ent, context) {
10394
+ ent.frame = 346;
10395
+ ent.model = "models/monsters/boss3/rider/tris.md2";
10396
+ ent.skin = 1;
10397
+ ent.think = makron_torso_think;
10398
+ ent.nextthink = context.timeSeconds + 0.1;
10399
+ context.sound(ent, 0, "makron/spine.wav", 1, 1, 0);
10400
+ ent.movetype = 7 /* Toss */;
10401
+ const { forward, up } = angleVectors(ent.angles);
10402
+ const vUp = scaleVec3(up, 120);
10403
+ const vFwd = scaleVec3(forward, -120);
10404
+ ent.velocity = addVec3(addVec3(ent.velocity, vUp), vFwd);
10405
+ ent.origin = addVec3(ent.origin, scaleVec3(forward, -10));
10406
+ ent.angles = { ...ent.angles, x: 90 };
10407
+ ent.avelocity = ZERO_VEC3;
10408
+ context.linkentity(ent);
10409
+ }
10410
+ function makron_spawn_torso(self, context) {
10411
+ const tempent = context.spawn();
10412
+ tempent.classname = "makron_torso";
10413
+ tempent.origin = { ...self.origin };
10414
+ tempent.angles = { ...self.angles };
10415
+ tempent.origin.z += self.maxs.z - 15;
10416
+ makron_torso(tempent, context);
10417
+ }
10418
+ function makron_die(self, context) {
10419
+ context.engine.sound?.(self, 0, "makron/death.wav", 1, 1, 0);
10420
+ makron_spawn_torso(self, context);
10222
10421
  self.monsterinfo.current_move = death_move10;
10422
+ self.mins = { x: -60, y: -60, z: 0 };
10423
+ self.maxs = { x: 60, y: 60, z: 48 };
10223
10424
  }
10224
- function jorg_dead(self) {
10425
+ function makron_dead(self) {
10225
10426
  self.monsterinfo.nextframe = death_move10.lastframe;
10226
10427
  self.nextthink = -1;
10227
10428
  }
10228
- function makron_toss(self, context) {
10229
- const makron = context.spawn();
10230
- makron.classname = "monster_makron";
10231
- makron.origin = { ...self.origin };
10232
- makron.angles = { ...self.angles };
10233
- }
10234
- var stand_frames12 = Array.from({ length: 51 }, () => ({ ai: monster_ai_stand13, dist: 0 }));
10235
- stand_move12 = { firstframe: 0, lastframe: 50, frames: stand_frames12, endfunc: jorg_stand };
10236
- var walk_frames11 = Array.from({ length: 14 }, () => ({ ai: monster_ai_walk13, dist: 10 }));
10237
- walk_move11 = { firstframe: 51, lastframe: 64, frames: walk_frames11, endfunc: jorg_walk };
10238
- var run_frames10 = Array.from({ length: 14 }, () => ({ ai: monster_ai_run12, dist: 10 }));
10239
- run_move11 = { firstframe: 51, lastframe: 64, frames: run_frames10, endfunc: jorg_run };
10240
- var attack1_start_frames = Array.from({ length: 8 }, () => ({ ai: monster_ai_charge13, dist: 0 }));
10241
- var attack1_start_move = { firstframe: 65, lastframe: 72, frames: attack1_start_frames, endfunc: null };
10242
- var attack1_frames3 = Array.from({ length: 6 }, () => ({ ai: monster_ai_charge13, dist: 0, think: jorg_fire_bullet }));
10243
- attack1_move3 = { firstframe: 73, lastframe: 78, frames: attack1_frames3, endfunc: jorg_reattack1 };
10244
- attack1_start_move.endfunc = (self) => {
10245
- self.monsterinfo.current_move = attack1_move3;
10246
- };
10247
- var attack1_end_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10248
- attack1_end_move = { firstframe: 79, lastframe: 82, frames: attack1_end_frames, endfunc: jorg_run };
10249
- var attack2_frames2 = Array.from({ length: 13 }, (_, i) => ({
10429
+ var stand_frames12 = Array.from({ length: 60 }, () => ({ ai: monster_ai_stand13, dist: 0 }));
10430
+ stand_move12 = { firstframe: 0, lastframe: 59, frames: stand_frames12, endfunc: makron_stand };
10431
+ var walk_frames11 = Array.from({ length: 10 }, () => ({ ai: monster_ai_walk13, dist: 8 }));
10432
+ walk_move11 = { firstframe: 60, lastframe: 69, frames: walk_frames11, endfunc: makron_walk };
10433
+ var run_frames10 = Array.from({ length: 10 }, () => ({ ai: monster_ai_run12, dist: 8 }));
10434
+ run_move11 = { firstframe: 60, lastframe: 69, frames: run_frames10, endfunc: makron_run };
10435
+ var attack_bfg_frames = Array.from({ length: 8 }, (_, i) => ({
10250
10436
  ai: monster_ai_charge13,
10251
10437
  dist: 0,
10252
- think: i === 6 ? jorg_fire_bfg : null
10438
+ think: i === 3 ? makron_fire_bfg : null
10253
10439
  }));
10254
- attack2_move2 = { firstframe: 83, lastframe: 95, frames: attack2_frames2, endfunc: jorg_run };
10255
- var pain1_frames5 = Array.from({ length: 3 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10256
- pain1_move5 = { firstframe: 96, lastframe: 98, frames: pain1_frames5, endfunc: jorg_run };
10257
- var pain2_frames5 = Array.from({ length: 3 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10258
- pain2_move5 = { firstframe: 99, lastframe: 101, frames: pain2_frames5, endfunc: jorg_run };
10259
- var pain3_frames4 = Array.from({ length: 25 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10260
- pain3_move4 = { firstframe: 102, lastframe: 126, frames: pain3_frames4, endfunc: jorg_run };
10261
- var death_frames10 = Array.from({ length: 50 }, (_, i) => ({
10440
+ attack_bfg_move = { firstframe: 70, lastframe: 77, frames: attack_bfg_frames, endfunc: makron_run };
10441
+ var attack_hyperblaster_frames = Array.from({ length: 26 }, (_, i) => ({
10262
10442
  ai: monster_ai_move13,
10263
10443
  dist: 0,
10264
- think: i === 49 ? ((self, ctx) => {
10265
- }) : i === 48 ? makron_toss : null
10444
+ think: i >= 4 && i <= 20 ? makron_fire_hyperblaster : null
10266
10445
  }));
10267
- death_move10 = { firstframe: 127, lastframe: 176, frames: death_frames10, endfunc: jorg_dead };
10268
- function SP_monster_jorg(self, context) {
10269
- self.classname = "monster_jorg";
10270
- self.model = "models/monsters/boss3/jorg/tris.md2";
10271
- self.mins = { x: -80, y: -80, z: 0 };
10272
- self.maxs = { x: 80, y: 80, z: 140 };
10446
+ attack_hyperblaster_move = { firstframe: 78, lastframe: 103, frames: attack_hyperblaster_frames, endfunc: makron_run };
10447
+ var attack_railgun_frames = Array.from({ length: 16 }, (_, i) => ({
10448
+ ai: monster_ai_charge13,
10449
+ dist: 0,
10450
+ think: i === 7 ? makron_save_loc : i === 8 ? makron_fire_railgun : null
10451
+ }));
10452
+ attack_railgun_move = { firstframe: 104, lastframe: 119, frames: attack_railgun_frames, endfunc: makron_run };
10453
+ var pain4_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10454
+ pain4_move = { firstframe: 120, lastframe: 123, frames: pain4_frames, endfunc: makron_run };
10455
+ var pain5_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10456
+ pain5_move = { firstframe: 124, lastframe: 127, frames: pain5_frames, endfunc: makron_run };
10457
+ var pain6_frames = Array.from({ length: 27 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10458
+ pain6_move = { firstframe: 128, lastframe: 154, frames: pain6_frames, endfunc: makron_run };
10459
+ var death_frames10 = Array.from({ length: 95 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10460
+ death_move10 = { firstframe: 155, lastframe: 249, frames: death_frames10, endfunc: makron_dead };
10461
+ var sight_frames = Array.from({ length: 13 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10462
+ sight_move = { firstframe: 250, lastframe: 262, frames: sight_frames, endfunc: makron_run };
10463
+ function SP_monster_makron(self, context) {
10464
+ self.classname = "monster_makron";
10465
+ self.model = "models/monsters/boss3/rider/tris.md2";
10466
+ self.mins = { x: -30, y: -30, z: 0 };
10467
+ self.maxs = { x: 30, y: 30, z: 90 };
10273
10468
  self.movetype = 5 /* Step */;
10274
10469
  self.solid = 2 /* BoundingBox */;
10275
10470
  self.health = 3e3;
10276
10471
  self.max_health = 3e3;
10277
- self.mass = 1e3;
10472
+ self.mass = 500;
10278
10473
  self.takedamage = true;
10279
10474
  self.viewheight = 90;
10280
- self.pain = (ent, other, kick, dmg) => jorg_pain(ent, other, kick, dmg, context.entities);
10475
+ self.pain = (ent, other, kick, dmg) => makron_pain(ent, other, kick, dmg, context.entities);
10281
10476
  self.die = (self2, inflictor, attacker, damage, point) => {
10282
- self2.deadflag = 2 /* Dead */;
10283
- self2.solid = 0 /* Not */;
10284
- if (self2.health < -2e3) {
10477
+ if (self2.health <= -2e3) {
10285
10478
  throwGibs(context.entities, self2.origin, damage);
10286
10479
  context.entities.free(self2);
10287
10480
  return;
10288
10481
  }
10289
- jorg_die(self2, context.entities);
10482
+ self2.deadflag = 2 /* Dead */;
10483
+ self2.solid = 0 /* Not */;
10484
+ makron_die(self2, context.entities);
10290
10485
  };
10291
- self.monsterinfo.stand = jorg_stand;
10292
- self.monsterinfo.walk = jorg_walk;
10293
- self.monsterinfo.run = jorg_run;
10294
- self.monsterinfo.attack = (ent) => jorg_attack(ent, context.entities);
10486
+ self.monsterinfo.stand = makron_stand;
10487
+ self.monsterinfo.walk = makron_walk;
10488
+ self.monsterinfo.run = makron_run;
10489
+ self.monsterinfo.attack = makron_attack;
10295
10490
  self.monsterinfo.sight = (self2, other) => {
10296
- context.entities.sound?.(self2, 0, "boss3/sight1.wav", 1, 1, 0);
10491
+ context.entities.sound?.(self2, 0, "makron/sight.wav", 1, 1, 0);
10492
+ self2.monsterinfo.current_move = sight_move;
10297
10493
  };
10298
10494
  self.think = monster_think;
10299
- jorg_stand(self);
10495
+ self.monsterinfo.current_move = sight_move;
10300
10496
  self.nextthink = self.timestamp + MONSTER_TICK13;
10301
10497
  }
10302
- function registerJorgSpawns(registry) {
10303
- registry.register("monster_jorg", SP_monster_jorg);
10498
+ function registerMakronSpawns(registry) {
10499
+ registry.register("monster_makron", SP_monster_makron);
10304
10500
  }
10305
10501
 
10306
- // src/entities/monsters/insane.ts
10502
+ // src/entities/monsters/jorg.ts
10307
10503
  var MONSTER_TICK14 = 0.1;
10308
- var SPAWNFLAG_INSANE_CRAWL = 4;
10309
- var SPAWNFLAG_INSANE_CRUCIFIED = 8;
10504
+ var JORG_MACHINEGUN_R1_OFFSET = { x: 40, y: -20, z: 20 };
10505
+ var JORG_MACHINEGUN_L1_OFFSET = { x: 40, y: 20, z: 20 };
10506
+ var JORG_BFG_OFFSET = { x: 30, y: 0, z: 40 };
10507
+ function monster_ai_stand14(self, dist, context) {
10508
+ ai_stand(self, MONSTER_TICK14, context);
10509
+ }
10510
+ function monster_ai_walk14(self, dist, context) {
10511
+ ai_walk(self, dist, MONSTER_TICK14, context);
10512
+ }
10513
+ function monster_ai_run13(self, dist, context) {
10514
+ ai_run(self, dist, MONSTER_TICK14, context);
10515
+ }
10516
+ function monster_ai_charge14(self, dist, context) {
10517
+ ai_charge(self, dist, MONSTER_TICK14, context);
10518
+ }
10519
+ function monster_ai_move14(self, dist, context) {
10520
+ ai_move(self, dist);
10521
+ }
10522
+ var stand_move13;
10523
+ var walk_move12;
10524
+ var run_move12;
10525
+ var attack1_move3;
10526
+ var attack1_end_move;
10527
+ var attack2_move2;
10528
+ var pain1_move5;
10529
+ var pain2_move5;
10530
+ var pain3_move4;
10531
+ var death_move11;
10532
+ function jorg_stand(self) {
10533
+ self.monsterinfo.current_move = stand_move13;
10534
+ }
10535
+ function jorg_walk(self) {
10536
+ self.monsterinfo.current_move = walk_move12;
10537
+ }
10538
+ function jorg_run(self) {
10539
+ if (self.enemy && self.enemy.health > 0) {
10540
+ self.monsterinfo.current_move = run_move12;
10541
+ } else {
10542
+ self.monsterinfo.current_move = stand_move13;
10543
+ }
10544
+ }
10545
+ function jorg_attack(self, context) {
10546
+ if (!self.enemy) return;
10547
+ if (Math.random() <= 0.75) {
10548
+ context.sound(self, 0, "boss3/bs3atck1.wav", 1, 1, 0);
10549
+ self.monsterinfo.current_move = attack1_move3;
10550
+ } else {
10551
+ context.sound(self, 0, "boss3/bs3atck2.wav", 1, 1, 0);
10552
+ self.monsterinfo.current_move = attack2_move2;
10553
+ }
10554
+ }
10555
+ function jorg_reattack1(self, context) {
10556
+ const traceFn = (start, mins, maxs, end, ignore, mask) => {
10557
+ const tr = context.trace(start, mins, maxs, end, ignore, mask);
10558
+ return { fraction: tr.fraction, ent: tr.ent };
10559
+ };
10560
+ if (self.enemy && visible(self, self.enemy, traceFn)) {
10561
+ if (Math.random() < 0.9) {
10562
+ self.monsterinfo.current_move = attack1_move3;
10563
+ } else {
10564
+ self.monsterinfo.current_move = attack1_end_move;
10565
+ }
10566
+ } else {
10567
+ self.monsterinfo.current_move = attack1_end_move;
10568
+ }
10569
+ }
10570
+ function getProjectedOffset3(self, offset) {
10571
+ const { forward, right, up } = angleVectors(self.angles);
10572
+ const start = { ...self.origin };
10573
+ const x = scaleVec3(forward, offset.x);
10574
+ const y = scaleVec3(right, offset.y);
10575
+ const z = scaleVec3(up, offset.z);
10576
+ return addVec3(addVec3(addVec3(start, x), y), z);
10577
+ }
10578
+ function jorg_fire_bullet(self, context) {
10579
+ if (!self.enemy) return;
10580
+ const startL = getProjectedOffset3(self, JORG_MACHINEGUN_L1_OFFSET);
10581
+ const dirL = normalizeVec3(subtractVec3(self.enemy.origin, startL));
10582
+ monster_fire_bullet_v2(self, startL, dirL, 6, 4, 0.05, 0.05, 0, context, 4 /* MACHINEGUN */);
10583
+ const startR = getProjectedOffset3(self, JORG_MACHINEGUN_R1_OFFSET);
10584
+ const dirR = normalizeVec3(subtractVec3(self.enemy.origin, startR));
10585
+ monster_fire_bullet_v2(self, startR, dirR, 6, 4, 0.05, 0.05, 0, context, 4 /* MACHINEGUN */);
10586
+ }
10587
+ function jorg_fire_bfg(self, context) {
10588
+ if (!self.enemy) return;
10589
+ const start = getProjectedOffset3(self, JORG_BFG_OFFSET);
10590
+ const target = { ...self.enemy.origin };
10591
+ target.z += self.enemy.viewheight || 0;
10592
+ const dir = normalizeVec3(subtractVec3(target, start));
10593
+ monster_fire_bfg(self, start, dir, 50, 300, 100, 200, 0, context);
10594
+ }
10595
+ function jorg_pain(self, other, kick, damage, context) {
10596
+ if (self.health < self.max_health / 2) {
10597
+ self.skin = 1;
10598
+ }
10599
+ if (self.timestamp < (self.pain_finished_time || 0)) return;
10600
+ if (damage <= 40 && Math.random() <= 0.6) return;
10601
+ if (self.monsterinfo.current_move === attack1_move3 || self.monsterinfo.current_move === attack2_move2) {
10602
+ if (Math.random() <= 5e-3) return;
10603
+ }
10604
+ self.pain_finished_time = self.timestamp + 3;
10605
+ if (damage <= 50) {
10606
+ context.engine.sound?.(self, 0, "boss3/bs3pain1.wav", 1, 1, 0);
10607
+ self.monsterinfo.current_move = pain1_move5;
10608
+ } else if (damage <= 100) {
10609
+ context.engine.sound?.(self, 0, "boss3/bs3pain2.wav", 1, 1, 0);
10610
+ self.monsterinfo.current_move = pain2_move5;
10611
+ } else {
10612
+ if (Math.random() <= 0.3) {
10613
+ context.engine.sound?.(self, 0, "boss3/bs3pain3.wav", 1, 1, 0);
10614
+ self.monsterinfo.current_move = pain3_move4;
10615
+ }
10616
+ }
10617
+ }
10618
+ function jorg_die(self, context) {
10619
+ context.engine.sound?.(self, 0, "boss3/bs3deth1.wav", 1, 1, 0);
10620
+ self.monsterinfo.current_move = death_move11;
10621
+ }
10622
+ function jorg_dead(self) {
10623
+ self.monsterinfo.nextframe = death_move11.lastframe;
10624
+ self.nextthink = -1;
10625
+ }
10626
+ function makron_toss(self, context) {
10627
+ const makron = context.spawn();
10628
+ makron.classname = "monster_makron";
10629
+ makron.origin = { ...self.origin };
10630
+ makron.target = self.target;
10631
+ makron.enemy = self.enemy;
10632
+ const spawnContext = { entities: context };
10633
+ SP_monster_makron(makron, spawnContext);
10634
+ if (makron.enemy && makron.enemy.health > 0) {
10635
+ const vec = subtractVec3(makron.enemy.origin, makron.origin);
10636
+ makron.angles = { ...makron.angles, y: vectorToYaw(vec) };
10637
+ const dir = normalizeVec3(vec);
10638
+ const vel = scaleVec3(dir, 400);
10639
+ makron.velocity = { x: vel.x, y: vel.y, z: 200 };
10640
+ makron.groundentity = null;
10641
+ if (makron.monsterinfo.sight) {
10642
+ makron.monsterinfo.sight(makron, makron.enemy);
10643
+ }
10644
+ }
10645
+ }
10646
+ var stand_frames13 = Array.from({ length: 51 }, () => ({ ai: monster_ai_stand14, dist: 0 }));
10647
+ stand_move13 = { firstframe: 0, lastframe: 50, frames: stand_frames13, endfunc: jorg_stand };
10648
+ var walk_frames12 = Array.from({ length: 14 }, () => ({ ai: monster_ai_walk14, dist: 10 }));
10649
+ walk_move12 = { firstframe: 51, lastframe: 64, frames: walk_frames12, endfunc: jorg_walk };
10650
+ var run_frames11 = Array.from({ length: 14 }, () => ({ ai: monster_ai_run13, dist: 10 }));
10651
+ run_move12 = { firstframe: 51, lastframe: 64, frames: run_frames11, endfunc: jorg_run };
10652
+ var attack1_start_frames = Array.from({ length: 8 }, () => ({ ai: monster_ai_charge14, dist: 0 }));
10653
+ var attack1_start_move = { firstframe: 65, lastframe: 72, frames: attack1_start_frames, endfunc: null };
10654
+ var attack1_frames3 = Array.from({ length: 6 }, () => ({ ai: monster_ai_charge14, dist: 0, think: jorg_fire_bullet }));
10655
+ attack1_move3 = { firstframe: 73, lastframe: 78, frames: attack1_frames3, endfunc: jorg_reattack1 };
10656
+ attack1_start_move.endfunc = (self) => {
10657
+ self.monsterinfo.current_move = attack1_move3;
10658
+ };
10659
+ var attack1_end_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10660
+ attack1_end_move = { firstframe: 79, lastframe: 82, frames: attack1_end_frames, endfunc: jorg_run };
10661
+ var attack2_frames2 = Array.from({ length: 13 }, (_, i) => ({
10662
+ ai: monster_ai_charge14,
10663
+ dist: 0,
10664
+ think: i === 6 ? jorg_fire_bfg : null
10665
+ }));
10666
+ attack2_move2 = { firstframe: 83, lastframe: 95, frames: attack2_frames2, endfunc: jorg_run };
10667
+ var pain1_frames5 = Array.from({ length: 3 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10668
+ pain1_move5 = { firstframe: 96, lastframe: 98, frames: pain1_frames5, endfunc: jorg_run };
10669
+ var pain2_frames5 = Array.from({ length: 3 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10670
+ pain2_move5 = { firstframe: 99, lastframe: 101, frames: pain2_frames5, endfunc: jorg_run };
10671
+ var pain3_frames4 = Array.from({ length: 25 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10672
+ pain3_move4 = { firstframe: 102, lastframe: 126, frames: pain3_frames4, endfunc: jorg_run };
10673
+ var death_frames11 = Array.from({ length: 50 }, (_, i) => ({
10674
+ ai: monster_ai_move14,
10675
+ dist: 0,
10676
+ think: i === 49 ? ((self, ctx) => {
10677
+ }) : i === 48 ? makron_toss : null
10678
+ }));
10679
+ death_move11 = { firstframe: 127, lastframe: 176, frames: death_frames11, endfunc: jorg_dead };
10680
+ function SP_monster_jorg(self, context) {
10681
+ self.classname = "monster_jorg";
10682
+ self.model = "models/monsters/boss3/jorg/tris.md2";
10683
+ self.mins = { x: -80, y: -80, z: 0 };
10684
+ self.maxs = { x: 80, y: 80, z: 140 };
10685
+ self.movetype = 5 /* Step */;
10686
+ self.solid = 2 /* BoundingBox */;
10687
+ self.health = 3e3;
10688
+ self.max_health = 3e3;
10689
+ self.mass = 1e3;
10690
+ self.takedamage = true;
10691
+ self.viewheight = 90;
10692
+ self.pain = (ent, other, kick, dmg) => jorg_pain(ent, other, kick, dmg, context.entities);
10693
+ self.die = (self2, inflictor, attacker, damage, point) => {
10694
+ self2.deadflag = 2 /* Dead */;
10695
+ self2.solid = 0 /* Not */;
10696
+ if (self2.health < -2e3) {
10697
+ throwGibs(context.entities, self2.origin, damage);
10698
+ context.entities.free(self2);
10699
+ return;
10700
+ }
10701
+ jorg_die(self2, context.entities);
10702
+ };
10703
+ self.monsterinfo.stand = jorg_stand;
10704
+ self.monsterinfo.walk = jorg_walk;
10705
+ self.monsterinfo.run = jorg_run;
10706
+ self.monsterinfo.attack = (ent) => jorg_attack(ent, context.entities);
10707
+ self.monsterinfo.sight = (self2, other) => {
10708
+ context.entities.sound?.(self2, 0, "boss3/sight1.wav", 1, 1, 0);
10709
+ };
10710
+ self.think = monster_think;
10711
+ jorg_stand(self);
10712
+ self.nextthink = self.timestamp + MONSTER_TICK14;
10713
+ }
10714
+ function registerJorgSpawns(registry) {
10715
+ registry.register("monster_jorg", SP_monster_jorg);
10716
+ }
10717
+
10718
+ // src/entities/monsters/insane.ts
10719
+ var MONSTER_TICK15 = 0.1;
10720
+ var SPAWNFLAG_INSANE_CRAWL = 4;
10721
+ var SPAWNFLAG_INSANE_CRUCIFIED = 8;
10310
10722
  var SPAWNFLAG_INSANE_STAND_GROUND = 16;
10311
10723
  var SPAWNFLAG_INSANE_ALWAYS_STAND = 32;
10312
10724
  var SPAWNFLAG_INSANE_QUIET = 64;
@@ -10474,7 +10886,7 @@ function insane_dead(self, context) {
10474
10886
  function m(ai, dist = 0, think) {
10475
10887
  return { ai: (s, d, c) => {
10476
10888
  if (think) think(s, c);
10477
- ai(s, dist, MONSTER_TICK14, c);
10889
+ ai(s, dist, MONSTER_TICK15, c);
10478
10890
  }, dist };
10479
10891
  }
10480
10892
  var frames_stand_normal = [
@@ -10713,7 +11125,7 @@ insane_move_run_normal = {
10713
11125
  frames: frames_walk_normal.map((f) => ({
10714
11126
  ai: (s, d, c) => {
10715
11127
  if (f.ai === frames_walk_normal[0].ai) insane_scream(s, c);
10716
- ai_run(s, d, MONSTER_TICK14, c);
11128
+ ai_run(s, d, MONSTER_TICK15, c);
10717
11129
  },
10718
11130
  dist: f.dist
10719
11131
  })),
@@ -10759,7 +11171,7 @@ insane_move_run_insane = {
10759
11171
  frames: frames_walk_insane.map((f) => ({
10760
11172
  ai: (s, d, c) => {
10761
11173
  if (f.ai === frames_walk_insane[0].ai) insane_scream(s, c);
10762
- ai_run(s, d, MONSTER_TICK14, c);
11174
+ ai_run(s, d, MONSTER_TICK15, c);
10763
11175
  },
10764
11176
  dist: f.dist
10765
11177
  })),
@@ -10986,7 +11398,7 @@ function SP_misc_insane(self, context) {
10986
11398
  self.monsterinfo.current_move = insane_move_stand_normal;
10987
11399
  self.monsterinfo.scale = 1;
10988
11400
  self.think = monster_think;
10989
- self.nextthink = context.entities.timeSeconds + MONSTER_TICK14;
11401
+ self.nextthink = context.entities.timeSeconds + MONSTER_TICK15;
10990
11402
  if (self.spawnflags & SPAWNFLAG_INSANE_CRUCIFIED) {
10991
11403
  self.mass = 1e5;
10992
11404
  }
@@ -10996,218 +11408,548 @@ function registerInsaneSpawns(registry) {
10996
11408
  registry.register("misc_insane", SP_misc_insane);
10997
11409
  }
10998
11410
 
10999
- // src/entities/monsters/makron.ts
11000
- var MONSTER_TICK15 = 0.1;
11001
- var MAKRON_BFG_OFFSET = { x: 30, y: 28, z: 24 };
11002
- var MAKRON_BLASTER_OFFSET_1 = { x: 26, y: 16, z: 24 };
11003
- var MAKRON_RAILGUN_OFFSET = { x: 26, y: -14, z: 24 };
11004
- function monster_ai_stand14(self, dist, context) {
11005
- ai_stand(self, MONSTER_TICK15, context);
11006
- }
11007
- function monster_ai_walk14(self, dist, context) {
11008
- ai_walk(self, dist, MONSTER_TICK15, context);
11009
- }
11010
- function monster_ai_run13(self, dist, context) {
11011
- ai_run(self, dist, MONSTER_TICK15, context);
11012
- }
11013
- function monster_ai_charge14(self, dist, context) {
11014
- ai_charge(self, dist, MONSTER_TICK15, context);
11015
- }
11016
- function monster_ai_move14(self, dist, context) {
11017
- ai_move(self, dist);
11411
+ // src/entities/monsters/actor.ts
11412
+ var MONSTER_TICK16 = 0.1;
11413
+ var MZ2_ACTOR_MACHINEGUN_1 = 0;
11414
+ var actor_names = [
11415
+ "Hellrot",
11416
+ "Tokay",
11417
+ "Killme",
11418
+ "Disruptor",
11419
+ "Adrianator",
11420
+ "Rambear",
11421
+ "Titus",
11422
+ "Bitterman"
11423
+ ];
11424
+ var FRAME_stand101 = 0;
11425
+ var FRAME_stand140 = 39;
11426
+ var FRAME_walk01 = 40;
11427
+ var FRAME_walk08 = 47;
11428
+ var FRAME_run02 = 48;
11429
+ var FRAME_run07 = 53;
11430
+ var FRAME_pain101 = 54;
11431
+ var FRAME_pain103 = 56;
11432
+ var FRAME_pain201 = 57;
11433
+ var FRAME_pain203 = 59;
11434
+ var FRAME_pain301 = 60;
11435
+ var FRAME_pain303 = 62;
11436
+ var FRAME_flip01 = 63;
11437
+ var FRAME_flip14 = 76;
11438
+ var FRAME_taunt01 = 77;
11439
+ var FRAME_taunt17 = 93;
11440
+ var FRAME_death101 = 94;
11441
+ var FRAME_death107 = 100;
11442
+ var FRAME_death201 = 101;
11443
+ var FRAME_death213 = 113;
11444
+ var FRAME_attak01 = 114;
11445
+ var FRAME_attak04 = 117;
11446
+ var actor_move_stand;
11447
+ var actor_move_walk;
11448
+ var actor_move_run;
11449
+ var actor_move_pain1;
11450
+ var actor_move_pain2;
11451
+ var actor_move_pain3;
11452
+ var actor_move_flipoff;
11453
+ var actor_move_taunt;
11454
+ var actor_move_death1;
11455
+ var actor_move_death2;
11456
+ var actor_move_attack;
11457
+ function m2(ai, dist = 0, think) {
11458
+ return { ai: (s, d, c) => {
11459
+ if (think) think(s, c);
11460
+ ai(s, dist, MONSTER_TICK16, c);
11461
+ }, dist };
11018
11462
  }
11019
- var stand_move13;
11020
- var walk_move12;
11021
- var run_move12;
11022
- var attack_bfg_move;
11023
- var attack_hyperblaster_move;
11024
- var attack_railgun_move;
11025
- var pain4_move;
11026
- var pain5_move;
11027
- var pain6_move;
11028
- var death_move11;
11029
- var sight_move;
11030
- function makron_stand(self) {
11031
- self.monsterinfo.current_move = stand_move13;
11463
+ function actor_stand(self, context) {
11464
+ self.monsterinfo.current_move = actor_move_stand;
11465
+ if (context.timeSeconds < 1) {
11466
+ self.frame = FRAME_stand101 + Math.floor(Math.random() * (FRAME_stand140 - FRAME_stand101 + 1));
11467
+ }
11032
11468
  }
11033
- function makron_walk(self) {
11034
- self.monsterinfo.current_move = walk_move12;
11469
+ function actor_walk(self, context) {
11470
+ self.monsterinfo.current_move = actor_move_walk;
11035
11471
  }
11036
- function makron_run(self) {
11037
- if (self.enemy && self.enemy.health > 0) {
11038
- self.monsterinfo.current_move = run_move12;
11039
- } else {
11040
- self.monsterinfo.current_move = stand_move13;
11472
+ function actor_run(self, context) {
11473
+ if (context.timeSeconds < self.pain_debounce_time && !self.enemy) {
11474
+ if (self.movetarget)
11475
+ actor_walk(self, context);
11476
+ else
11477
+ actor_stand(self, context);
11478
+ return;
11041
11479
  }
11042
- }
11043
- function makron_attack(self) {
11044
- if (!self.enemy) return;
11045
- const r = Math.random();
11046
- if (r <= 0.3) {
11047
- self.monsterinfo.current_move = attack_bfg_move;
11048
- } else if (r <= 0.6) {
11049
- self.monsterinfo.current_move = attack_hyperblaster_move;
11050
- } else {
11051
- self.monsterinfo.current_move = attack_railgun_move;
11480
+ if (self.monsterinfo.aiflags & 1 /* StandGround */) {
11481
+ actor_stand(self, context);
11482
+ return;
11052
11483
  }
11484
+ self.monsterinfo.current_move = actor_move_run;
11053
11485
  }
11054
- function getProjectedOffset3(self, offset) {
11055
- const { forward, right, up } = angleVectors(self.angles);
11056
- const start = { ...self.origin };
11057
- const x = scaleVec3(forward, offset.x);
11058
- const y = scaleVec3(right, offset.y);
11059
- const z = scaleVec3(up, offset.z);
11060
- return addVec3(addVec3(addVec3(start, x), y), z);
11061
- }
11062
- function makron_fire_bfg(self, context) {
11063
- if (!self.enemy) return;
11064
- context.engine.sound?.(self, 0, "makron/bfg_fire.wav", 1, 1, 0);
11065
- const start = getProjectedOffset3(self, MAKRON_BFG_OFFSET);
11066
- const target = { ...self.enemy.origin };
11067
- target.z += self.enemy.viewheight || 0;
11068
- const dir = normalizeVec3(subtractVec3(target, start));
11069
- monster_fire_bfg(self, start, dir, 50, 300, 100, 300, 0, context);
11070
- }
11071
- function makron_fire_railgun(self, context) {
11072
- if (!self.pos1) return;
11073
- context.engine.sound?.(self, 0, "makron/rail_fire.wav", 1, 1, 0);
11074
- const start = getProjectedOffset3(self, MAKRON_RAILGUN_OFFSET);
11075
- const dir = normalizeVec3(subtractVec3(self.pos1, start));
11076
- monster_fire_railgun(self, start, dir, 50, 100, 0, context);
11486
+ var messages = [
11487
+ "Watch it",
11488
+ "#$@*&",
11489
+ "Idiot",
11490
+ "Check your targets"
11491
+ ];
11492
+ function actor_pain(self, other, kick, damage) {
11493
+ const context = self.monsterinfo.context;
11494
+ if (!context) return;
11495
+ if (context.timeSeconds < self.pain_debounce_time)
11496
+ return;
11497
+ self.pain_debounce_time = context.timeSeconds + 3;
11498
+ const random10 = Math.random();
11499
+ if (other && other.client && random10 < 0.4) {
11500
+ const v = subtractVec3(other.origin, self.origin);
11501
+ self.ideal_yaw = vectorToYaw(v);
11502
+ if (Math.random() < 0.5)
11503
+ self.monsterinfo.current_move = actor_move_flipoff;
11504
+ else
11505
+ self.monsterinfo.current_move = actor_move_taunt;
11506
+ const name = actor_names[Math.floor(Math.random() * actor_names.length)];
11507
+ const message = messages[Math.floor(Math.random() * messages.length)];
11508
+ context.centerprintf(other, `${name}: ${message}!
11509
+ `);
11510
+ return;
11511
+ }
11512
+ const n = Math.floor(Math.random() * 3);
11513
+ if (n === 0)
11514
+ self.monsterinfo.current_move = actor_move_pain1;
11515
+ else if (n === 1)
11516
+ self.monsterinfo.current_move = actor_move_pain2;
11517
+ else
11518
+ self.monsterinfo.current_move = actor_move_pain3;
11077
11519
  }
11078
- function makron_save_loc(self) {
11079
- if (!self.enemy) return;
11080
- self.pos1 = { ...self.enemy.origin };
11081
- self.pos1 = { ...self.pos1, z: self.pos1.z + (self.enemy.viewheight || 0) };
11520
+ function actor_setskin(self, context) {
11521
+ if (self.health < self.max_health / 2)
11522
+ self.skin = 1;
11523
+ else
11524
+ self.skin = 0;
11082
11525
  }
11083
- function makron_fire_hyperblaster(self, context) {
11084
- context.engine.sound?.(self, 0, "makron/blaster.wav", 1, 1, 0);
11085
- const start = getProjectedOffset3(self, MAKRON_BLASTER_OFFSET_1);
11086
- const relFrame = (self.monsterinfo.nextframe || 0) - attack_hyperblaster_move.firstframe;
11087
- let yawDelta = 0;
11526
+ function actorMachineGun(self, context) {
11527
+ const flashOffset = { x: 0, y: 0, z: 0 };
11528
+ const vectors = angleVectors(self.angles);
11529
+ const forward = vectors.forward;
11530
+ const start = copyVec3(self.origin);
11531
+ start.z += self.viewheight;
11088
11532
  let dir;
11089
11533
  if (self.enemy) {
11090
- const target = { ...self.enemy.origin };
11091
- target.z += self.enemy.viewheight || 0;
11092
- const vec = subtractVec3(target, start);
11093
- const baseAngles = vectorToAngles(vec);
11094
- const enemyAngles = { ...baseAngles };
11095
- if (relFrame <= 12) {
11096
- enemyAngles.y -= 5 * (relFrame - 4);
11534
+ let target;
11535
+ if (self.enemy.health > 0) {
11536
+ target = subtractVec3(self.enemy.origin, scaleVec3(self.enemy.velocity, 0.2));
11537
+ target.z += self.enemy.viewheight;
11097
11538
  } else {
11098
- enemyAngles.y -= 40 - 5 * (relFrame - 12);
11539
+ target = copyVec3(self.enemy.absmin);
11540
+ target.z += self.enemy.size.z / 2 + 1;
11099
11541
  }
11100
- const forward = angleVectors(enemyAngles).forward;
11101
- dir = forward;
11542
+ dir = subtractVec3(target, start);
11543
+ dir = normalizeVec3(dir);
11102
11544
  } else {
11103
- const { forward } = angleVectors(self.angles);
11104
11545
  dir = forward;
11105
11546
  }
11106
- monster_fire_blaster(self, start, dir, 15, 1e3, 0, 0, context, 1 /* BLASTER */);
11547
+ monster_fire_bullet(self, start, dir, 3, 4, 0, 0, MZ2_ACTOR_MACHINEGUN_1, context);
11107
11548
  }
11108
- function makron_pain(self, other, kick, damage, context) {
11109
- if (self.health < self.max_health / 2) {
11110
- self.skin = 1;
11111
- }
11112
- if (self.timestamp < (self.pain_finished_time || 0)) return;
11113
- if (damage <= 25 && Math.random() < 0.2) return;
11114
- self.pain_finished_time = self.timestamp + 3;
11115
- if (damage <= 40) {
11116
- context.engine.sound?.(self, 0, "makron/pain1.wav", 1, 1, 0);
11117
- self.monsterinfo.current_move = pain4_move;
11118
- } else if (damage <= 110) {
11119
- context.engine.sound?.(self, 0, "makron/pain2.wav", 1, 1, 0);
11120
- self.monsterinfo.current_move = pain5_move;
11121
- } else {
11122
- if (Math.random() <= 0.45) {
11123
- context.engine.sound?.(self, 0, "makron/pain3.wav", 1, 1, 0);
11124
- self.monsterinfo.current_move = pain6_move;
11125
- }
11126
- }
11549
+ function actor_dead(self, context) {
11550
+ self.mins = { x: -16, y: -16, z: -24 };
11551
+ self.maxs = { x: 16, y: 16, z: -8 };
11552
+ self.movetype = 7 /* Toss */;
11553
+ self.svflags |= 1;
11554
+ self.nextthink = -1;
11555
+ context.linkentity(self);
11127
11556
  }
11128
- function makron_die(self, context) {
11129
- context.engine.sound?.(self, 0, "makron/death.wav", 1, 1, 0);
11130
- self.monsterinfo.current_move = death_move11;
11557
+ function actor_die(self, inflictor, attacker, damage, point, mod) {
11558
+ const context = self.monsterinfo.context;
11559
+ if (!context) return;
11560
+ if (self.health <= -80) {
11561
+ throwGibs(context, self.origin, damage);
11562
+ self.deadflag = 2 /* Dead */;
11563
+ return;
11564
+ }
11565
+ if (self.deadflag === 2 /* Dead */)
11566
+ return;
11567
+ self.deadflag = 2 /* Dead */;
11568
+ self.takedamage = true;
11569
+ if (Math.random() < 0.5)
11570
+ self.monsterinfo.current_move = actor_move_death1;
11571
+ else
11572
+ self.monsterinfo.current_move = actor_move_death2;
11573
+ }
11574
+ function actor_fire(self, context) {
11575
+ actorMachineGun(self, context);
11576
+ const fire_wait = self.monsterinfo.fire_wait ?? 0;
11577
+ if (context.timeSeconds >= fire_wait)
11578
+ self.monsterinfo.aiflags &= ~128 /* HoldFrame */;
11579
+ else
11580
+ self.monsterinfo.aiflags |= 128 /* HoldFrame */;
11131
11581
  }
11132
- function makron_dead(self) {
11133
- self.monsterinfo.nextframe = death_move11.lastframe;
11134
- self.nextthink = -1;
11582
+ function actor_attack(self, context) {
11583
+ self.monsterinfo.current_move = actor_move_attack;
11584
+ self.monsterinfo.fire_wait = context.timeSeconds + 1 + Math.random() * 1.6;
11135
11585
  }
11136
- var stand_frames13 = Array.from({ length: 60 }, () => ({ ai: monster_ai_stand14, dist: 0 }));
11137
- stand_move13 = { firstframe: 0, lastframe: 59, frames: stand_frames13, endfunc: makron_stand };
11138
- var walk_frames12 = Array.from({ length: 10 }, () => ({ ai: monster_ai_walk14, dist: 8 }));
11139
- walk_move12 = { firstframe: 60, lastframe: 69, frames: walk_frames12, endfunc: makron_walk };
11140
- var run_frames11 = Array.from({ length: 10 }, () => ({ ai: monster_ai_run13, dist: 8 }));
11141
- run_move12 = { firstframe: 60, lastframe: 69, frames: run_frames11, endfunc: makron_run };
11142
- var attack_bfg_frames = Array.from({ length: 8 }, (_, i) => ({
11143
- ai: monster_ai_charge14,
11144
- dist: 0,
11145
- think: i === 3 ? makron_fire_bfg : null
11146
- }));
11147
- attack_bfg_move = { firstframe: 70, lastframe: 77, frames: attack_bfg_frames, endfunc: makron_run };
11148
- var attack_hyperblaster_frames = Array.from({ length: 26 }, (_, i) => ({
11149
- ai: monster_ai_move14,
11150
- dist: 0,
11151
- think: i >= 4 && i <= 20 ? makron_fire_hyperblaster : null
11152
- }));
11153
- attack_hyperblaster_move = { firstframe: 78, lastframe: 103, frames: attack_hyperblaster_frames, endfunc: makron_run };
11154
- var attack_railgun_frames = Array.from({ length: 16 }, (_, i) => ({
11155
- ai: monster_ai_charge14,
11156
- dist: 0,
11157
- think: i === 7 ? makron_save_loc : i === 8 ? makron_fire_railgun : null
11158
- }));
11159
- attack_railgun_move = { firstframe: 104, lastframe: 119, frames: attack_railgun_frames, endfunc: makron_run };
11160
- var pain4_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move14, dist: 0 }));
11161
- pain4_move = { firstframe: 120, lastframe: 123, frames: pain4_frames, endfunc: makron_run };
11162
- var pain5_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move14, dist: 0 }));
11163
- pain5_move = { firstframe: 124, lastframe: 127, frames: pain5_frames, endfunc: makron_run };
11164
- var pain6_frames = Array.from({ length: 27 }, () => ({ ai: monster_ai_move14, dist: 0 }));
11165
- pain6_move = { firstframe: 128, lastframe: 154, frames: pain6_frames, endfunc: makron_run };
11166
- var death_frames11 = Array.from({ length: 95 }, () => ({ ai: monster_ai_move14, dist: 0 }));
11167
- death_move11 = { firstframe: 155, lastframe: 249, frames: death_frames11, endfunc: makron_dead };
11168
- var sight_frames = Array.from({ length: 13 }, () => ({ ai: monster_ai_move14, dist: 0 }));
11169
- sight_move = { firstframe: 250, lastframe: 262, frames: sight_frames, endfunc: makron_run };
11170
- function SP_monster_makron(self, context) {
11171
- self.classname = "monster_makron";
11172
- self.model = "models/monsters/boss3/rider/tris.md2";
11173
- self.mins = { x: -30, y: -30, z: 0 };
11174
- self.maxs = { x: 30, y: 30, z: 90 };
11586
+ function actor_use(self, other, activator) {
11587
+ const context = self.monsterinfo.context;
11588
+ const target = context.pickTarget(self.target);
11589
+ self.goalentity = target;
11590
+ self.movetarget = target;
11591
+ if (!self.movetarget || self.movetarget.classname !== "target_actor") {
11592
+ console.log(`${self.classname}: bad target ${self.target}`);
11593
+ self.target = void 0;
11594
+ self.monsterinfo.pausetime = 1e8;
11595
+ if (self.monsterinfo.stand) self.monsterinfo.stand(self, context);
11596
+ return;
11597
+ }
11598
+ const goalPos = self.goalentity ? self.goalentity.origin : self.movetarget ? self.movetarget.origin : self.origin;
11599
+ const v = subtractVec3(goalPos, self.origin);
11600
+ self.ideal_yaw = vectorToYaw(v);
11601
+ self.angles.y = self.ideal_yaw;
11602
+ if (self.monsterinfo.walk) self.monsterinfo.walk(self, context);
11603
+ self.target = void 0;
11604
+ }
11605
+ function actor_stand_wrapper(self, context) {
11606
+ actor_stand(self, context);
11607
+ }
11608
+ var frames_stand = [
11609
+ m2(ai_stand),
11610
+ m2(ai_stand),
11611
+ m2(ai_stand),
11612
+ m2(ai_stand),
11613
+ m2(ai_stand),
11614
+ m2(ai_stand),
11615
+ m2(ai_stand),
11616
+ m2(ai_stand),
11617
+ m2(ai_stand),
11618
+ m2(ai_stand),
11619
+ m2(ai_stand),
11620
+ m2(ai_stand),
11621
+ m2(ai_stand),
11622
+ m2(ai_stand),
11623
+ m2(ai_stand),
11624
+ m2(ai_stand),
11625
+ m2(ai_stand),
11626
+ m2(ai_stand),
11627
+ m2(ai_stand),
11628
+ m2(ai_stand),
11629
+ m2(ai_stand),
11630
+ m2(ai_stand),
11631
+ m2(ai_stand),
11632
+ m2(ai_stand),
11633
+ m2(ai_stand),
11634
+ m2(ai_stand),
11635
+ m2(ai_stand),
11636
+ m2(ai_stand),
11637
+ m2(ai_stand),
11638
+ m2(ai_stand),
11639
+ m2(ai_stand),
11640
+ m2(ai_stand),
11641
+ m2(ai_stand),
11642
+ m2(ai_stand),
11643
+ m2(ai_stand),
11644
+ m2(ai_stand),
11645
+ m2(ai_stand),
11646
+ m2(ai_stand),
11647
+ m2(ai_stand),
11648
+ m2(ai_stand)
11649
+ ];
11650
+ actor_move_stand = {
11651
+ firstframe: FRAME_stand101,
11652
+ lastframe: FRAME_stand140,
11653
+ frames: frames_stand,
11654
+ endfunc: null
11655
+ };
11656
+ var frames_walk = [
11657
+ m2(ai_walk),
11658
+ m2(ai_walk, 6),
11659
+ m2(ai_walk, 10),
11660
+ m2(ai_walk, 3),
11661
+ m2(ai_walk, 2),
11662
+ m2(ai_walk, 7),
11663
+ m2(ai_walk, 10),
11664
+ m2(ai_walk, 1)
11665
+ ];
11666
+ actor_move_walk = {
11667
+ firstframe: FRAME_walk01,
11668
+ lastframe: FRAME_walk08,
11669
+ frames: frames_walk,
11670
+ endfunc: null
11671
+ };
11672
+ var frames_run = [
11673
+ m2(ai_run, 4),
11674
+ m2(ai_run, 15),
11675
+ m2(ai_run, 15),
11676
+ m2(ai_run, 8),
11677
+ m2(ai_run, 20),
11678
+ m2(ai_run, 15)
11679
+ ];
11680
+ actor_move_run = {
11681
+ firstframe: FRAME_run02,
11682
+ lastframe: FRAME_run07,
11683
+ frames: frames_run,
11684
+ endfunc: null
11685
+ };
11686
+ var frames_pain1 = [
11687
+ m2(ai_move, -5),
11688
+ m2(ai_move, 4),
11689
+ m2(ai_move, 1)
11690
+ ];
11691
+ actor_move_pain1 = {
11692
+ firstframe: FRAME_pain101,
11693
+ lastframe: FRAME_pain103,
11694
+ frames: frames_pain1,
11695
+ endfunc: actor_run
11696
+ };
11697
+ var frames_pain2 = [
11698
+ m2(ai_move, -4),
11699
+ m2(ai_move, 4),
11700
+ m2(ai_move)
11701
+ ];
11702
+ actor_move_pain2 = {
11703
+ firstframe: FRAME_pain201,
11704
+ lastframe: FRAME_pain203,
11705
+ frames: frames_pain2,
11706
+ endfunc: actor_run
11707
+ };
11708
+ var frames_pain3 = [
11709
+ m2(ai_move, -1),
11710
+ m2(ai_move, 1),
11711
+ m2(ai_move, 0)
11712
+ ];
11713
+ actor_move_pain3 = {
11714
+ firstframe: FRAME_pain301,
11715
+ lastframe: FRAME_pain303,
11716
+ frames: frames_pain3,
11717
+ endfunc: actor_run
11718
+ };
11719
+ var frames_flipoff = [
11720
+ m2(ai_turn),
11721
+ m2(ai_turn),
11722
+ m2(ai_turn),
11723
+ m2(ai_turn),
11724
+ m2(ai_turn),
11725
+ m2(ai_turn),
11726
+ m2(ai_turn),
11727
+ m2(ai_turn),
11728
+ m2(ai_turn),
11729
+ m2(ai_turn),
11730
+ m2(ai_turn),
11731
+ m2(ai_turn),
11732
+ m2(ai_turn),
11733
+ m2(ai_turn)
11734
+ ];
11735
+ actor_move_flipoff = {
11736
+ firstframe: FRAME_flip01,
11737
+ lastframe: FRAME_flip14,
11738
+ frames: frames_flipoff,
11739
+ endfunc: actor_run
11740
+ };
11741
+ var frames_taunt = [
11742
+ m2(ai_turn),
11743
+ m2(ai_turn),
11744
+ m2(ai_turn),
11745
+ m2(ai_turn),
11746
+ m2(ai_turn),
11747
+ m2(ai_turn),
11748
+ m2(ai_turn),
11749
+ m2(ai_turn),
11750
+ m2(ai_turn),
11751
+ m2(ai_turn),
11752
+ m2(ai_turn),
11753
+ m2(ai_turn),
11754
+ m2(ai_turn),
11755
+ m2(ai_turn),
11756
+ m2(ai_turn),
11757
+ m2(ai_turn),
11758
+ m2(ai_turn)
11759
+ ];
11760
+ actor_move_taunt = {
11761
+ firstframe: FRAME_taunt01,
11762
+ lastframe: FRAME_taunt17,
11763
+ frames: frames_taunt,
11764
+ endfunc: actor_run
11765
+ };
11766
+ var frames_death1 = [
11767
+ m2(ai_move),
11768
+ m2(ai_move),
11769
+ m2(ai_move, -13),
11770
+ m2(ai_move, 14),
11771
+ m2(ai_move, 3),
11772
+ m2(ai_move, -2),
11773
+ m2(ai_move, 1)
11774
+ ];
11775
+ actor_move_death1 = {
11776
+ firstframe: FRAME_death101,
11777
+ lastframe: FRAME_death107,
11778
+ frames: frames_death1,
11779
+ endfunc: actor_dead
11780
+ };
11781
+ var frames_death2 = [
11782
+ m2(ai_move),
11783
+ m2(ai_move, 7),
11784
+ m2(ai_move, -6),
11785
+ m2(ai_move, -5),
11786
+ m2(ai_move, 1),
11787
+ m2(ai_move),
11788
+ m2(ai_move, -1),
11789
+ m2(ai_move, -2),
11790
+ m2(ai_move, -1),
11791
+ m2(ai_move, -9),
11792
+ m2(ai_move, -13),
11793
+ m2(ai_move, -13),
11794
+ m2(ai_move)
11795
+ ];
11796
+ actor_move_death2 = {
11797
+ firstframe: FRAME_death201,
11798
+ lastframe: FRAME_death213,
11799
+ frames: frames_death2,
11800
+ endfunc: actor_dead
11801
+ };
11802
+ var frames_attack = [
11803
+ m2(ai_charge, -2, actor_fire),
11804
+ m2(ai_charge, -2),
11805
+ m2(ai_charge, 3),
11806
+ m2(ai_charge, 2)
11807
+ ];
11808
+ actor_move_attack = {
11809
+ firstframe: FRAME_attak01,
11810
+ lastframe: FRAME_attak04,
11811
+ frames: frames_attack,
11812
+ endfunc: actor_run
11813
+ };
11814
+ function SP_misc_actor(self, context) {
11815
+ if (!self.targetname) {
11816
+ console.log(`${self.classname}: no targetname`);
11817
+ context.entities.free(self);
11818
+ return;
11819
+ }
11820
+ if (!self.target) {
11821
+ console.log(`${self.classname}: no target`);
11822
+ context.entities.free(self);
11823
+ return;
11824
+ }
11825
+ self.movetarget = null;
11175
11826
  self.movetype = 5 /* Step */;
11176
11827
  self.solid = 2 /* BoundingBox */;
11177
- self.health = 3e3;
11178
- self.max_health = 3e3;
11179
- self.mass = 500;
11180
- self.takedamage = true;
11181
- self.viewheight = 90;
11182
- self.pain = (ent, other, kick, dmg) => makron_pain(ent, other, kick, dmg, context.entities);
11183
- self.die = (self2, inflictor, attacker, damage, point) => {
11184
- if (self2.health <= -2e3) {
11185
- throwGibs(context.entities, self2.origin, damage);
11186
- context.entities.free(self2);
11187
- return;
11188
- }
11189
- self2.deadflag = 2 /* Dead */;
11190
- self2.solid = 0 /* Not */;
11191
- makron_die(self2, context.entities);
11828
+ self.model = "players/male/tris.md2";
11829
+ self.mins = { x: -16, y: -16, z: -24 };
11830
+ self.maxs = { x: 16, y: 16, z: 32 };
11831
+ if (!self.health)
11832
+ self.health = 100;
11833
+ self.max_health = self.health;
11834
+ self.mass = 200;
11835
+ self.pain = actor_pain;
11836
+ self.die = actor_die;
11837
+ self.monsterinfo = {
11838
+ ...self.monsterinfo,
11839
+ // Preserve default properties like last_sighting, trail_time, pausetime
11840
+ stand: (s) => actor_stand_wrapper(s, context.entities),
11841
+ // Wrap to match signature
11842
+ walk: actor_walk,
11843
+ run: actor_run,
11844
+ attack: actor_attack,
11845
+ melee: void 0,
11846
+ sight: void 0,
11847
+ setskin: (s) => actor_setskin(s, context.entities),
11848
+ // Wrap to match signature
11849
+ aiflags: 256 /* GoodGuy */,
11850
+ scale: 1
11851
+ // MODEL_SCALE
11192
11852
  };
11193
- self.monsterinfo.stand = makron_stand;
11194
- self.monsterinfo.walk = makron_walk;
11195
- self.monsterinfo.run = makron_run;
11196
- self.monsterinfo.attack = makron_attack;
11197
- self.monsterinfo.sight = (self2, other) => {
11198
- context.entities.sound?.(self2, 0, "makron/sight.wav", 1, 1, 0);
11199
- self2.monsterinfo.current_move = sight_move;
11853
+ self.monsterinfo.context = context.entities;
11854
+ context.entities.linkentity(self);
11855
+ self.monsterinfo.current_move = actor_move_stand;
11856
+ self.think = (s) => {
11857
+ const c = s.monsterinfo.context;
11858
+ if (c) monster_think(s, c);
11200
11859
  };
11201
- self.think = monster_think;
11202
- self.monsterinfo.current_move = sight_move;
11203
- self.nextthink = self.timestamp + MONSTER_TICK15;
11860
+ self.nextthink = context.entities.timeSeconds + MONSTER_TICK16;
11861
+ self.use = (self2, other, activator = null) => actor_use(self2, other, activator);
11862
+ }
11863
+ var SPAWNFLAG_TARGET_ACTOR_JUMP = 1;
11864
+ var SPAWNFLAG_TARGET_ACTOR_SHOOT = 2;
11865
+ var SPAWNFLAG_TARGET_ACTOR_ATTACK = 4;
11866
+ var SPAWNFLAG_TARGET_ACTOR_HOLD = 16;
11867
+ var SPAWNFLAG_TARGET_ACTOR_BRUTAL = 32;
11868
+ function target_actor_touch(self, other, plane, surf) {
11869
+ if (!other) return;
11870
+ const context = self.monsterinfo.context;
11871
+ if (other.movetarget !== self)
11872
+ return;
11873
+ if (other.enemy)
11874
+ return;
11875
+ other.goalentity = null;
11876
+ other.movetarget = null;
11877
+ if (self.message) {
11878
+ const name = actor_names[Math.floor(Math.random() * actor_names.length)];
11879
+ }
11880
+ if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_JUMP) {
11881
+ const v = other.velocity;
11882
+ v.x = self.movedir.x * self.speed;
11883
+ v.y = self.movedir.y * self.speed;
11884
+ if (other.groundentity) {
11885
+ other.groundentity = null;
11886
+ v.z = self.movedir.z;
11887
+ context.sound(other, 2, "player/male/jump1.wav", 1, 1, 0);
11888
+ }
11889
+ }
11890
+ if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_SHOOT) {
11891
+ } else if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_ATTACK) {
11892
+ other.enemy = context.pickTarget(self.pathtarget);
11893
+ if (other.enemy) {
11894
+ other.goalentity = other.enemy;
11895
+ if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_BRUTAL)
11896
+ other.monsterinfo.aiflags |= 512 /* Brutal */;
11897
+ if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_HOLD) {
11898
+ other.monsterinfo.aiflags |= 1 /* StandGround */;
11899
+ actor_stand(other, context);
11900
+ } else {
11901
+ actor_run(other, context);
11902
+ }
11903
+ }
11904
+ }
11905
+ if (!(self.spawnflags & (SPAWNFLAG_TARGET_ACTOR_ATTACK | SPAWNFLAG_TARGET_ACTOR_SHOOT)) && self.pathtarget) {
11906
+ const savetarget = self.target;
11907
+ self.target = self.pathtarget;
11908
+ context.useTargets(self, other);
11909
+ self.target = savetarget;
11910
+ }
11911
+ other.movetarget = context.pickTarget(self.target);
11912
+ if (!other.goalentity)
11913
+ other.goalentity = other.movetarget;
11914
+ if (!other.movetarget && !other.enemy) {
11915
+ other.monsterinfo.pausetime = 1e8;
11916
+ if (other.monsterinfo.stand) other.monsterinfo.stand(other, context);
11917
+ } else if (other.movetarget === other.goalentity && other.movetarget) {
11918
+ const v = subtractVec3(other.movetarget.origin, other.origin);
11919
+ other.ideal_yaw = vectorToYaw(v);
11920
+ }
11204
11921
  }
11205
- function registerMakronSpawns(registry) {
11206
- registry.register("monster_makron", SP_monster_makron);
11922
+ function SP_target_actor(self, context) {
11923
+ if (!self.targetname)
11924
+ console.log(`${self.classname}: no targetname`);
11925
+ self.solid = 1 /* Trigger */;
11926
+ self.touch = target_actor_touch;
11927
+ self.mins = { x: -8, y: -8, z: -8 };
11928
+ self.maxs = { x: 8, y: 8, z: 8 };
11929
+ self.svflags = 1 << 6;
11930
+ self.monsterinfo = {
11931
+ ...self.monsterinfo
11932
+ };
11933
+ self.monsterinfo.context = context.entities;
11934
+ if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_JUMP) {
11935
+ if (!self.speed)
11936
+ self.speed = 200;
11937
+ const height = self.height || 200;
11938
+ if (self.angles.y === 0)
11939
+ self.angles.y = 360;
11940
+ const dir = setMovedir(self.angles);
11941
+ dir.z = height;
11942
+ self.movedir = dir;
11943
+ }
11944
+ context.entities.linkentity(self);
11945
+ }
11946
+ function registerActorSpawns(registry) {
11947
+ registry.register("misc_actor", SP_misc_actor);
11948
+ registry.register("target_actor", SP_target_actor);
11207
11949
  }
11208
11950
 
11209
11951
  // src/entities/monsters/medic.ts
11210
- var MONSTER_TICK16 = 0.1;
11952
+ var MONSTER_TICK17 = 0.1;
11211
11953
  function monster_ai_stand15(self, dist, context) {
11212
11954
  if (self.classname === "monster_medic") {
11213
11955
  if (medic_find_dead(self, context)) {
@@ -11215,24 +11957,24 @@ function monster_ai_stand15(self, dist, context) {
11215
11957
  return;
11216
11958
  }
11217
11959
  }
11218
- ai_stand(self, MONSTER_TICK16, context);
11960
+ ai_stand(self, MONSTER_TICK17, context);
11219
11961
  }
11220
11962
  function monster_ai_walk15(self, dist, context) {
11221
- ai_walk(self, dist, MONSTER_TICK16, context);
11963
+ ai_walk(self, dist, MONSTER_TICK17, context);
11222
11964
  }
11223
11965
  function monster_ai_run14(self, dist, context) {
11224
11966
  if (self.classname === "monster_medic") {
11225
11967
  if (medic_find_dead(self, context)) {
11226
11968
  self.monsterinfo.current_move = run_move13;
11227
11969
  } else {
11228
- ai_run(self, dist, MONSTER_TICK16, context);
11970
+ ai_run(self, dist, MONSTER_TICK17, context);
11229
11971
  }
11230
11972
  } else {
11231
- ai_run(self, dist, MONSTER_TICK16, context);
11973
+ ai_run(self, dist, MONSTER_TICK17, context);
11232
11974
  }
11233
11975
  }
11234
11976
  function monster_ai_charge15(self, dist, context) {
11235
- ai_charge(self, dist, MONSTER_TICK16, context);
11977
+ ai_charge(self, dist, MONSTER_TICK17, context);
11236
11978
  }
11237
11979
  function monster_ai_move15(self, dist, context) {
11238
11980
  ai_move(self, dist);
@@ -11568,7 +12310,7 @@ function SP_monster_medic(self, context) {
11568
12310
  self.monsterinfo.attack = medic_attack;
11569
12311
  self.think = monster_think;
11570
12312
  medic_stand(self);
11571
- self.nextthink = self.timestamp + MONSTER_TICK16;
12313
+ self.nextthink = self.timestamp + MONSTER_TICK17;
11572
12314
  }
11573
12315
  function SP_monster_medic_commander(self, context) {
11574
12316
  SP_monster_medic(self, context);
@@ -11583,25 +12325,25 @@ function registerMedicSpawns(registry) {
11583
12325
  }
11584
12326
 
11585
12327
  // src/entities/monsters/mutant.ts
11586
- var MONSTER_TICK17 = 0.1;
12328
+ var MONSTER_TICK18 = 0.1;
11587
12329
  var random6 = () => Math.random();
11588
12330
  function monster_ai_stand16(self, dist, context) {
11589
- ai_stand(self, MONSTER_TICK17, context);
12331
+ ai_stand(self, MONSTER_TICK18, context);
11590
12332
  }
11591
12333
  function monster_ai_walk16(self, dist, context) {
11592
- ai_walk(self, dist, MONSTER_TICK17, context);
12334
+ ai_walk(self, dist, MONSTER_TICK18, context);
11593
12335
  }
11594
12336
  function monster_ai_run15(self, dist, context) {
11595
- ai_run(self, dist, MONSTER_TICK17, context);
12337
+ ai_run(self, dist, MONSTER_TICK18, context);
11596
12338
  }
11597
12339
  function monster_ai_charge16(self, dist, context) {
11598
- ai_charge(self, dist, MONSTER_TICK17, context);
12340
+ ai_charge(self, dist, MONSTER_TICK18, context);
11599
12341
  }
11600
12342
  function monster_ai_move16(self, dist, context) {
11601
12343
  ai_move(self, dist);
11602
12344
  }
11603
12345
  function monster_ai_face(self, dist, context) {
11604
- ai_face(self, null, dist, MONSTER_TICK17);
12346
+ ai_face(self, null, dist, MONSTER_TICK18);
11605
12347
  }
11606
12348
  var stand_move15;
11607
12349
  var walk_move14;
@@ -11965,26 +12707,26 @@ function SP_monster_mutant(self, context) {
11965
12707
  self.monsterinfo.idle = mutant_stand;
11966
12708
  self.think = monster_think;
11967
12709
  mutant_stand(self);
11968
- self.nextthink = self.timestamp + MONSTER_TICK17;
12710
+ self.nextthink = self.timestamp + MONSTER_TICK18;
11969
12711
  }
11970
12712
  function registerMutantSpawns(registry) {
11971
12713
  registry.register("monster_mutant", SP_monster_mutant);
11972
12714
  }
11973
12715
 
11974
12716
  // src/entities/monsters/parasite.ts
11975
- var MONSTER_TICK18 = 0.1;
12717
+ var MONSTER_TICK19 = 0.1;
11976
12718
  var random7 = () => Math.random();
11977
12719
  function monster_ai_stand17(self, dist, context) {
11978
- ai_stand(self, MONSTER_TICK18, context);
12720
+ ai_stand(self, MONSTER_TICK19, context);
11979
12721
  }
11980
12722
  function monster_ai_walk17(self, dist, context) {
11981
- ai_walk(self, dist, MONSTER_TICK18, context);
12723
+ ai_walk(self, dist, MONSTER_TICK19, context);
11982
12724
  }
11983
12725
  function monster_ai_run16(self, dist, context) {
11984
- ai_run(self, dist, MONSTER_TICK18, context);
12726
+ ai_run(self, dist, MONSTER_TICK19, context);
11985
12727
  }
11986
12728
  function monster_ai_charge17(self, dist, context) {
11987
- ai_charge(self, dist, MONSTER_TICK18, context);
12729
+ ai_charge(self, dist, MONSTER_TICK19, context);
11988
12730
  }
11989
12731
  function monster_ai_move17(self, dist, context) {
11990
12732
  ai_move(self, dist);
@@ -12361,28 +13103,28 @@ function SP_monster_parasite(self, context) {
12361
13103
  self.monsterinfo.idle = parasite_idle;
12362
13104
  self.think = monster_think;
12363
13105
  parasite_stand(self);
12364
- self.nextthink = self.timestamp + MONSTER_TICK18;
13106
+ self.nextthink = self.timestamp + MONSTER_TICK19;
12365
13107
  }
12366
13108
  function registerParasiteSpawns(registry) {
12367
13109
  registry.register("monster_parasite", SP_monster_parasite);
12368
13110
  }
12369
13111
 
12370
13112
  // src/entities/monsters/soldier.ts
12371
- var MONSTER_TICK19 = 0.1;
13113
+ var MONSTER_TICK20 = 0.1;
12372
13114
  var SOLDIER_LIGHT = 1;
12373
13115
  var SOLDIER_SSG = 2;
12374
13116
  var SOLDIER_MACHINEGUN = 4;
12375
13117
  function monster_ai_stand18(self, dist, context) {
12376
- ai_stand(self, MONSTER_TICK19, context);
13118
+ ai_stand(self, MONSTER_TICK20, context);
12377
13119
  }
12378
13120
  function monster_ai_walk18(self, dist, context) {
12379
- ai_walk(self, dist, MONSTER_TICK19, context);
13121
+ ai_walk(self, dist, MONSTER_TICK20, context);
12380
13122
  }
12381
13123
  function monster_ai_run17(self, dist, context) {
12382
- ai_run(self, dist, MONSTER_TICK19, context);
13124
+ ai_run(self, dist, MONSTER_TICK20, context);
12383
13125
  }
12384
13126
  function monster_ai_charge18(self, dist, context) {
12385
- ai_charge(self, dist, MONSTER_TICK19, context);
13127
+ ai_charge(self, dist, MONSTER_TICK20, context);
12386
13128
  }
12387
13129
  function monster_ai_move18(self, dist, context) {
12388
13130
  ai_move(self, dist);
@@ -12666,7 +13408,7 @@ function SP_monster_soldier(self, context) {
12666
13408
  };
12667
13409
  self.think = monster_think;
12668
13410
  soldier_stand(self);
12669
- self.nextthink = self.timestamp + MONSTER_TICK19;
13411
+ self.nextthink = self.timestamp + MONSTER_TICK20;
12670
13412
  }
12671
13413
  function SP_monster_soldier_light(self, context) {
12672
13414
  self.spawnflags |= SOLDIER_LIGHT;
@@ -12706,12 +13448,12 @@ function registerMonsterSpawns(registry) {
12706
13448
  }
12707
13449
 
12708
13450
  // src/entities/monsters/supertank.ts
12709
- var MONSTER_TICK20 = 0.1;
13451
+ var MONSTER_TICK21 = 0.1;
12710
13452
  var SUPERTANK_MACHINEGUN_OFFSET = { x: 30, y: 30, z: 40 };
12711
13453
  var SUPERTANK_ROCKET_OFFSET = { x: 30, y: -30, z: 40 };
12712
13454
  var SUPERTANK_GRENADE_OFFSET = { x: 20, y: 0, z: 70 };
12713
13455
  function monster_ai_stand19(self, dist, context) {
12714
- ai_stand(self, MONSTER_TICK20, context);
13456
+ ai_stand(self, MONSTER_TICK21, context);
12715
13457
  }
12716
13458
  function monster_ai_run18(self, dist, context) {
12717
13459
  if (self.enemy && self.enemy.health > 0) {
@@ -12721,7 +13463,7 @@ function monster_ai_run18(self, dist, context) {
12721
13463
  }
12722
13464
  }
12723
13465
  function monster_ai_charge19(self, dist, context) {
12724
- ai_charge(self, dist, MONSTER_TICK20, context);
13466
+ ai_charge(self, dist, MONSTER_TICK21, context);
12725
13467
  }
12726
13468
  function monster_ai_move19(self, dist, context) {
12727
13469
  ai_move(self, dist);
@@ -12917,7 +13659,7 @@ function SP_monster_supertank(self, context) {
12917
13659
  };
12918
13660
  self.think = monster_think;
12919
13661
  supertank_stand(self);
12920
- self.nextthink = self.timestamp + MONSTER_TICK20;
13662
+ self.nextthink = self.timestamp + MONSTER_TICK21;
12921
13663
  }
12922
13664
  function registerSupertankSpawns(registry) {
12923
13665
  registry.register("monster_supertank", SP_monster_supertank);
@@ -12930,7 +13672,7 @@ function registerSupertankSpawns(registry) {
12930
13672
  }
12931
13673
 
12932
13674
  // src/entities/monsters/tank.ts
12933
- var MONSTER_TICK21 = 0.1;
13675
+ var MONSTER_TICK22 = 0.1;
12934
13676
  function M_AdjustBlindfireTarget(self, start, target, right, context) {
12935
13677
  const tr = context.trace(start, target, ZERO_VEC3, ZERO_VEC3, self, MASK_SHOT);
12936
13678
  if (!tr.startsolid && !tr.allsolid && tr.fraction >= 0.5) {
@@ -12957,10 +13699,10 @@ function tank_blind_check(self, context) {
12957
13699
  }
12958
13700
  }
12959
13701
  function monster_ai_stand20(self, dist, context) {
12960
- ai_stand(self, MONSTER_TICK21, context);
13702
+ ai_stand(self, MONSTER_TICK22, context);
12961
13703
  }
12962
13704
  function monster_ai_walk19(self, dist, context) {
12963
- ai_walk(self, dist, MONSTER_TICK21, context);
13705
+ ai_walk(self, dist, MONSTER_TICK22, context);
12964
13706
  }
12965
13707
  function monster_ai_run19(self, dist, context) {
12966
13708
  if (self.enemy && self.enemy.health > 0) {
@@ -12970,7 +13712,7 @@ function monster_ai_run19(self, dist, context) {
12970
13712
  }
12971
13713
  }
12972
13714
  function monster_ai_charge20(self, dist, context) {
12973
- ai_charge(self, dist, MONSTER_TICK21, context);
13715
+ ai_charge(self, dist, MONSTER_TICK22, context);
12974
13716
  }
12975
13717
  function monster_ai_move20(self, dist, context) {
12976
13718
  ai_move(self, dist);
@@ -13281,7 +14023,7 @@ function SP_monster_tank(self, context) {
13281
14023
  self.monsterinfo.blindfire = true;
13282
14024
  self.think = monster_think;
13283
14025
  tank_stand(self);
13284
- self.nextthink = self.timestamp + MONSTER_TICK21;
14026
+ self.nextthink = self.timestamp + MONSTER_TICK22;
13285
14027
  }
13286
14028
  function registerTankSpawns(registry) {
13287
14029
  registry.register("monster_tank", SP_monster_tank);
@@ -13300,15 +14042,15 @@ function registerTankCommanderSpawns(registry) {
13300
14042
  }
13301
14043
 
13302
14044
  // src/entities/monsters/turret.ts
13303
- var MONSTER_TICK22 = 0.1;
14045
+ var MONSTER_TICK23 = 0.1;
13304
14046
  function monster_ai_stand21(self, dist, context) {
13305
- ai_stand(self, MONSTER_TICK22, context);
14047
+ ai_stand(self, MONSTER_TICK23, context);
13306
14048
  }
13307
14049
  function monster_ai_run20(self, dist, context) {
13308
- ai_run(self, dist, MONSTER_TICK22, context);
14050
+ ai_run(self, dist, MONSTER_TICK23, context);
13309
14051
  }
13310
14052
  function monster_ai_charge21(self, dist, context) {
13311
- ai_charge(self, dist, MONSTER_TICK22, context);
14053
+ ai_charge(self, dist, MONSTER_TICK23, context);
13312
14054
  }
13313
14055
  var stand_move20;
13314
14056
  var run_move19;
@@ -13444,7 +14186,7 @@ function SP_monster_turret(self, context) {
13444
14186
  };
13445
14187
  self.think = monster_think;
13446
14188
  turret_stand(self);
13447
- self.nextthink = self.timestamp + MONSTER_TICK22;
14189
+ self.nextthink = self.timestamp + MONSTER_TICK23;
13448
14190
  }
13449
14191
  function registerTurretSpawns(registry) {
13450
14192
  registry.register("monster_turret", SP_monster_turret);
@@ -13475,6 +14217,7 @@ function registerMonsterSpawns2(registry) {
13475
14217
  registerJorgSpawns(registry);
13476
14218
  registerMakronSpawns(registry);
13477
14219
  registerInsaneSpawns(registry);
14220
+ registerActorSpawns(registry);
13478
14221
  }
13479
14222
 
13480
14223
  // src/entities/worldspawn.ts
@@ -14922,7 +15665,97 @@ function ClientObituary(self, inflictor, attacker, mod, sys) {
14922
15665
  }
14923
15666
  }
14924
15667
 
15668
+ // src/entities/player_anim.ts
15669
+ var FRAME_stand01 = 0;
15670
+ var FRAME_stand402 = 39;
15671
+ var FRAME_run1 = 40;
15672
+ var FRAME_run6 = 45;
15673
+ var FRAME_pain1012 = 54;
15674
+ var FRAME_pain104 = 57;
15675
+ var FRAME_pain2012 = 58;
15676
+ var FRAME_pain204 = 61;
15677
+ var FRAME_pain3012 = 62;
15678
+ var FRAME_pain304 = 65;
15679
+ var FRAME_death1012 = 66;
15680
+ var FRAME_death106 = 71;
15681
+ var FRAME_death2012 = 72;
15682
+ var FRAME_death206 = 77;
15683
+ var FRAME_death301 = 78;
15684
+ var FRAME_death306 = 83;
15685
+ var ANIM_BASIC = 0;
15686
+ var ANIM_PAIN = 2;
15687
+ var ANIM_DEATH = 3;
15688
+
15689
+ // src/combat/weapons/firing.ts
15690
+ var random9 = createRandomGenerator();
15691
+
14925
15692
  // src/entities/player.ts
15693
+ function P_PlayerThink(ent, sys) {
15694
+ if (!ent.client) return;
15695
+ const client = ent.client;
15696
+ let animChanged = false;
15697
+ if (ent.deadflag) {
15698
+ } else {
15699
+ const speed = Math.sqrt(ent.velocity.x * ent.velocity.x + ent.velocity.y * ent.velocity.y);
15700
+ const moving = speed > 10;
15701
+ if (client.anim_priority === ANIM_BASIC || client.anim_priority === void 0) {
15702
+ if (moving) {
15703
+ if (ent.frame < FRAME_run1 || ent.frame > FRAME_run6) {
15704
+ ent.frame = FRAME_run1;
15705
+ client.anim_end = FRAME_run6;
15706
+ client.anim_priority = ANIM_BASIC;
15707
+ animChanged = true;
15708
+ }
15709
+ } else {
15710
+ if (ent.frame >= FRAME_run1 && ent.frame <= FRAME_run6 || client.anim_priority === ANIM_BASIC && client.anim_end !== FRAME_stand402 || client.anim_priority === void 0) {
15711
+ ent.frame = FRAME_stand01;
15712
+ client.anim_end = FRAME_stand402;
15713
+ client.anim_priority = ANIM_BASIC;
15714
+ animChanged = true;
15715
+ }
15716
+ }
15717
+ }
15718
+ }
15719
+ if (animChanged) {
15720
+ return;
15721
+ }
15722
+ if (client.anim_end !== void 0 && client.anim_end !== ent.frame) {
15723
+ if (ent.frame < client.anim_end) {
15724
+ ent.frame++;
15725
+ } else if (ent.frame > client.anim_end) {
15726
+ ent.frame--;
15727
+ }
15728
+ } else if (client.anim_end === ent.frame) {
15729
+ if (client.anim_priority === ANIM_BASIC) {
15730
+ if (ent.frame === FRAME_run6) ent.frame = FRAME_run1;
15731
+ else if (ent.frame === FRAME_stand402) ent.frame = FRAME_stand01;
15732
+ } else {
15733
+ if (client.anim_priority !== ANIM_DEATH) {
15734
+ client.anim_priority = ANIM_BASIC;
15735
+ }
15736
+ }
15737
+ }
15738
+ }
15739
+ function player_pain(self, damage) {
15740
+ if (!self.client) return;
15741
+ if (self.health < 40) {
15742
+ }
15743
+ if (self.client.anim_priority && self.client.anim_priority >= ANIM_PAIN) {
15744
+ return;
15745
+ }
15746
+ self.client.anim_priority = ANIM_PAIN;
15747
+ const r = random9.frandom();
15748
+ if (r < 0.33) {
15749
+ self.frame = FRAME_pain1012;
15750
+ self.client.anim_end = FRAME_pain104;
15751
+ } else if (r < 0.66) {
15752
+ self.frame = FRAME_pain2012;
15753
+ self.client.anim_end = FRAME_pain204;
15754
+ } else {
15755
+ self.frame = FRAME_pain3012;
15756
+ self.client.anim_end = FRAME_pain304;
15757
+ }
15758
+ }
14926
15759
  function player_die(self, inflictor, attacker, damage, point, mod, sys) {
14927
15760
  self.deadflag = 2 /* Dead */;
14928
15761
  self.solid = 0 /* Not */;
@@ -14930,8 +15763,24 @@ function player_die(self, inflictor, attacker, damage, point, mod, sys) {
14930
15763
  self.takedamage = false;
14931
15764
  if (self.health < -40 && sys) {
14932
15765
  throwGibs(sys, self.origin, damage);
15766
+ return;
15767
+ }
15768
+ if (self.client) {
15769
+ self.client.anim_priority = ANIM_DEATH;
15770
+ const r = random9.frandom();
15771
+ if (r < 0.33) {
15772
+ self.frame = FRAME_death1012;
15773
+ self.client.anim_end = FRAME_death106;
15774
+ } else if (r < 0.66) {
15775
+ self.frame = FRAME_death2012;
15776
+ self.client.anim_end = FRAME_death206;
15777
+ } else {
15778
+ self.frame = FRAME_death301;
15779
+ self.client.anim_end = FRAME_death306;
15780
+ }
15781
+ } else {
15782
+ self.frame = 0;
14933
15783
  }
14934
- self.frame = 0;
14935
15784
  if (sys) {
14936
15785
  ClientObituary(self, inflictor, attacker, mod, sys);
14937
15786
  }
@@ -14965,6 +15814,7 @@ function player_think(self, sys) {
14965
15814
  weaponItem.think(self, sys);
14966
15815
  }
14967
15816
  }
15817
+ P_PlayerThink(self, sys);
14968
15818
  self.nextthink = sys.timeSeconds + 0.1;
14969
15819
  sys.scheduleThink(self, self.nextthink);
14970
15820
  }
@@ -15311,7 +16161,7 @@ var WEAPONS = {
15311
16161
  };
15312
16162
 
15313
16163
  // src/index.ts
15314
- var ZERO_VEC37 = { x: 0, y: 0, z: 0 };
16164
+ var ZERO_VEC36 = { x: 0, y: 0, z: 0 };
15315
16165
  function createGame(imports, engine, options) {
15316
16166
  const gravity = options.gravity;
15317
16167
  const deathmatch = options.deathmatch ?? false;
@@ -15380,8 +16230,8 @@ function createGame(imports, engine, options) {
15380
16230
  };
15381
16231
  entities.runFrame();
15382
16232
  });
15383
- let origin = { ...ZERO_VEC37 };
15384
- let velocity = { ...ZERO_VEC37 };
16233
+ let origin = { ...ZERO_VEC36 };
16234
+ let velocity = { ...ZERO_VEC36 };
15385
16235
  const calculateBlend = (player, time) => {
15386
16236
  const blend = [0, 0, 0, 0];
15387
16237
  if (!player || !player.client) return blend;
@@ -15463,10 +16313,10 @@ function createGame(imports, engine, options) {
15463
16313
  // TODO
15464
16314
  damageIndicators: [],
15465
16315
  stats: player ? populatePlayerStats(player, levelClock.current.timeSeconds) : [],
15466
- kick_angles: player?.client?.kick_angles ?? ZERO_VEC37,
15467
- kick_origin: player?.client?.kick_origin ?? ZERO_VEC37,
15468
- gunoffset: ZERO_VEC37,
15469
- gunangles: ZERO_VEC37,
16316
+ kick_angles: player?.client?.kick_angles ?? ZERO_VEC36,
16317
+ kick_origin: player?.client?.kick_origin ?? ZERO_VEC36,
16318
+ gunoffset: ZERO_VEC36,
16319
+ gunangles: ZERO_VEC36,
15470
16320
  gunindex: 0,
15471
16321
  gun_frame: player?.client?.gun_frame ?? 0,
15472
16322
  rdflags: player?.client?.rdflags ?? 0,
@@ -15480,8 +16330,8 @@ function createGame(imports, engine, options) {
15480
16330
  const resetState = (startTimeMs) => {
15481
16331
  frameLoop.reset(startTimeMs);
15482
16332
  levelClock.start(startTimeMs);
15483
- origin = { ...ZERO_VEC37 };
15484
- velocity = { ...ZERO_VEC37 };
16333
+ origin = { ...ZERO_VEC36 };
16334
+ velocity = { ...ZERO_VEC36 };
15485
16335
  entities.beginFrame(startTimeMs / 1e3);
15486
16336
  entities.runFrame();
15487
16337
  };
@@ -15509,10 +16359,10 @@ function createGame(imports, engine, options) {
15509
16359
  blend: [0, 0, 0, 0],
15510
16360
  // Stubs
15511
16361
  stats: populatePlayerStats(player, levelClock.current.timeSeconds),
15512
- kick_angles: ZERO_VEC37,
15513
- kick_origin: ZERO_VEC37,
15514
- gunoffset: ZERO_VEC37,
15515
- gunangles: ZERO_VEC37,
16362
+ kick_angles: ZERO_VEC36,
16363
+ kick_origin: ZERO_VEC36,
16364
+ gunoffset: ZERO_VEC36,
16365
+ gunangles: ZERO_VEC36,
15516
16366
  gunindex: 0,
15517
16367
  pm_type: 0,
15518
16368
  pm_time: 0,
@@ -15570,6 +16420,9 @@ function createGame(imports, engine, options) {
15570
16420
  player.die = (self, inflictor, attacker, damage, point, mod) => {
15571
16421
  player_die(self, inflictor, attacker, damage, point, mod, entities);
15572
16422
  };
16423
+ player.pain = (self, other, kick, damage) => {
16424
+ player_pain(self, damage);
16425
+ };
15573
16426
  player.think = (self) => {
15574
16427
  player_think(self, entities);
15575
16428
  };
@@ -15639,8 +16492,8 @@ function createGame(imports, engine, options) {
15639
16492
  rng,
15640
16493
  player: player?.client?.inventory
15641
16494
  });
15642
- origin = player ? { ...player.origin } : { ...ZERO_VEC37 };
15643
- velocity = player ? { ...player.velocity } : { ...ZERO_VEC37 };
16495
+ origin = player ? { ...player.origin } : { ...ZERO_VEC36 };
16496
+ velocity = player ? { ...player.velocity } : { ...ZERO_VEC36 };
15644
16497
  frameLoop.reset(save.level.timeSeconds * 1e3);
15645
16498
  }
15646
16499
  };