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
@@ -128,15 +128,15 @@ function rotatePointAroundVector(dir, point, degrees) {
128
128
  const vf = normalizeVec3(dir);
129
129
  const vr = perpendicularVec3(vf);
130
130
  const vup = crossVec3(vr, vf);
131
- const m2 = [
131
+ const m3 = [
132
132
  [vr.x, vup.x, vf.x],
133
133
  [vr.y, vup.y, vf.y],
134
134
  [vr.z, vup.z, vf.z]
135
135
  ];
136
136
  const im = [
137
- [m2[0][0], m2[1][0], m2[2][0]],
138
- [m2[0][1], m2[1][1], m2[2][1]],
139
- [m2[0][2], m2[1][2], m2[2][2]]
137
+ [m3[0][0], m3[1][0], m3[2][0]],
138
+ [m3[0][1], m3[1][1], m3[2][1]],
139
+ [m3[0][2], m3[1][2], m3[2][2]]
140
140
  ];
141
141
  const radians = degrees * DEG_TO_RAD;
142
142
  const cos = Math.cos(radians);
@@ -146,7 +146,7 @@ function rotatePointAroundVector(dir, point, degrees) {
146
146
  [-sin, cos, 0],
147
147
  [0, 0, 1]
148
148
  ];
149
- const rot = concatRotationMatrices(concatRotationMatrices(m2, zrot), im);
149
+ const rot = concatRotationMatrices(concatRotationMatrices(m3, zrot), im);
150
150
  return {
151
151
  x: rot[0][0] * point.x + rot[0][1] * point.y + rot[0][2] * point.z,
152
152
  y: rot[1][0] * point.x + rot[1][1] * point.y + rot[1][2] * point.z,
@@ -512,12 +512,12 @@ function addReplayFrame(session, cmd, serverFrame, startTime) {
512
512
  timestamp: Date.now() - startTime
513
513
  });
514
514
  }
515
- var WaterLevel = /* @__PURE__ */ ((WaterLevel3) => {
516
- WaterLevel3[WaterLevel3["None"] = 0] = "None";
517
- WaterLevel3[WaterLevel3["Feet"] = 1] = "Feet";
518
- WaterLevel3[WaterLevel3["Waist"] = 2] = "Waist";
519
- WaterLevel3[WaterLevel3["Under"] = 3] = "Under";
520
- return WaterLevel3;
515
+ var WaterLevel = /* @__PURE__ */ ((WaterLevel4) => {
516
+ WaterLevel4[WaterLevel4["None"] = 0] = "None";
517
+ WaterLevel4[WaterLevel4["Feet"] = 1] = "Feet";
518
+ WaterLevel4[WaterLevel4["Waist"] = 2] = "Waist";
519
+ WaterLevel4[WaterLevel4["Under"] = 3] = "Under";
520
+ return WaterLevel4;
521
521
  })(WaterLevel || {});
522
522
  function applyPmoveFriction(params) {
523
523
  const {
@@ -594,12 +594,14 @@ function buildWaterWish(params) {
594
594
  let wishvel = {
595
595
  x: forward.x * cmd.forwardmove + right.x * cmd.sidemove,
596
596
  y: forward.y * cmd.forwardmove + right.y * cmd.sidemove,
597
- z: 0
597
+ z: forward.z * cmd.forwardmove + right.z * cmd.sidemove
598
598
  };
599
599
  if (cmd.upmove > 10) {
600
600
  wishvel = addVec3(wishvel, { x: 0, y: 0, z: cmd.upmove });
601
601
  } else if (cmd.upmove < -10) {
602
602
  wishvel = addVec3(wishvel, { x: 0, y: 0, z: cmd.upmove });
603
+ } else if (Math.abs(cmd.forwardmove) < 10 && Math.abs(cmd.sidemove) < 10) {
604
+ wishvel = addVec3(wishvel, { x: 0, y: 0, z: -60 });
603
605
  } else {
604
606
  wishvel = addVec3(wishvel, { x: 0, y: 0, z: 10 });
605
607
  }
@@ -987,6 +989,13 @@ var U_MODEL3 = 1 << 1;
987
989
  var U_MODEL4 = 1 << 2;
988
990
  var U_REMOVE = 32768;
989
991
  var FRAMETIME = 0.025;
992
+ var MASK_WATER2 = 33554432;
993
+ var WaterLevel3 = {
994
+ None: 0,
995
+ Feet: 1,
996
+ Waist: 2,
997
+ Under: 3
998
+ };
990
999
  var categorizePosition2 = (state, trace) => {
991
1000
  const point = { ...state.origin };
992
1001
  point.z -= 0.25;
@@ -998,12 +1007,26 @@ var categorizePosition2 = (state, trace) => {
998
1007
  };
999
1008
  var checkWater = (state, pointContents2) => {
1000
1009
  const point = { ...state.origin };
1001
- point.z += state.mins.z + 1;
1010
+ const { mins, maxs } = state;
1011
+ point.z = state.origin.z + mins.z + 1;
1002
1012
  const contents = pointContents2(point);
1003
- if (contents & 33554432) {
1004
- return { ...state, waterLevel: 1 };
1005
- }
1006
- return { ...state, waterLevel: 0 };
1013
+ if (!(contents & MASK_WATER2)) {
1014
+ return { ...state, waterLevel: WaterLevel3.None };
1015
+ }
1016
+ let waterLevel = WaterLevel3.Feet;
1017
+ const waist = state.origin.z + (mins.z + maxs.z) * 0.5;
1018
+ point.z = waist;
1019
+ const waistContents = pointContents2(point);
1020
+ if (waistContents & MASK_WATER2) {
1021
+ waterLevel = WaterLevel3.Waist;
1022
+ const head = state.origin.z + 22;
1023
+ point.z = head;
1024
+ const headContents = pointContents2(point);
1025
+ if (headContents & MASK_WATER2) {
1026
+ waterLevel = WaterLevel3.Under;
1027
+ }
1028
+ }
1029
+ return { ...state, waterLevel };
1007
1030
  };
1008
1031
  var applyPmove = (state, cmd, trace, pointContents2) => {
1009
1032
  let newState = { ...state };
@@ -1043,7 +1066,8 @@ var applyPmove = (state, cmd, trace, pointContents2) => {
1043
1066
  velocity: frictionedVelocity,
1044
1067
  wishdir: wish.wishdir,
1045
1068
  wishspeed: wish.wishspeed,
1046
- accel: onGround ? 10 : 1,
1069
+ // Water movement uses ground acceleration (10), not air acceleration (1)
1070
+ accel: onGround || waterLevel >= 2 ? 10 : 1,
1047
1071
  frametime: FRAMETIME
1048
1072
  });
1049
1073
  const traceResult = trace(origin, {
@@ -4434,6 +4458,131 @@ function useTargetBlaster(self, other, activator, context) {
4434
4458
  }
4435
4459
  context.entities.sound(self, 2, "weapons/laser2.wav", 1, ATTN_NORM, 0);
4436
4460
  }
4461
+ var TARGET_LASER_START_ON = 1;
4462
+ var TARGET_LASER_RED = 2;
4463
+ var TARGET_LASER_GREEN = 4;
4464
+ var TARGET_LASER_BLUE = 8;
4465
+ var TARGET_LASER_YELLOW = 16;
4466
+ var TARGET_LASER_ORANGE = 32;
4467
+ var TARGET_LASER_FAT = 64;
4468
+ function target_laser_think(self, context) {
4469
+ let count;
4470
+ if (self.spawnflags & 2147483648) {
4471
+ count = 8;
4472
+ } else {
4473
+ count = 4;
4474
+ }
4475
+ if (self.enemy) {
4476
+ const last_movedir = { ...self.movedir };
4477
+ const size = subtractVec3(self.enemy.maxs, self.enemy.mins);
4478
+ const centerOffset = scaleVec3(size, 0.5);
4479
+ const enemyCenter = addVec3(self.enemy.mins, centerOffset);
4480
+ const dir = subtractVec3(enemyCenter, self.origin);
4481
+ self.movedir = normalizeVec3(dir);
4482
+ 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) {
4483
+ self.spawnflags |= 2147483648;
4484
+ }
4485
+ }
4486
+ let ignore = self;
4487
+ let start = { ...self.origin };
4488
+ const end = addVec3(start, scaleVec3(self.movedir, 2048));
4489
+ let traceResult;
4490
+ while (true) {
4491
+ traceResult = context.entities.trace(start, end, ZERO_VEC3, ZERO_VEC3, ignore, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_DEADMONSTER);
4492
+ if (!traceResult.ent) {
4493
+ break;
4494
+ }
4495
+ const trEnt = traceResult.ent;
4496
+ if (trEnt.takedamage && !(trEnt.flags & 2)) {
4497
+ T_Damage(trEnt, self, self.activator, self.movedir, traceResult.endpos, ZERO_VEC3, self.dmg, 1, 4 /* ENERGY */, 31 /* TARGET_LASER */, context.entities.timeSeconds);
4498
+ }
4499
+ if (!(trEnt.svflags & 1) && !trEnt.client) {
4500
+ if (self.spawnflags & 2147483648) {
4501
+ self.spawnflags &= ~2147483648;
4502
+ context.entities.multicast(traceResult.endpos, 1 /* Pvs */, ServerCommand.temp_entity, TempEntity.LASER_SPARKS, count, traceResult.endpos, traceResult.plane?.normal || ZERO_VEC3, self.skin);
4503
+ }
4504
+ break;
4505
+ }
4506
+ ignore = trEnt;
4507
+ start = { ...traceResult.endpos };
4508
+ }
4509
+ self.old_origin = { ...traceResult.endpos };
4510
+ self.nextthink = context.entities.timeSeconds + 0.1;
4511
+ }
4512
+ function target_laser_on(self, context) {
4513
+ if (!self.activator) {
4514
+ self.activator = self;
4515
+ }
4516
+ self.spawnflags |= 2147483649;
4517
+ self.svflags &= ~1 /* NoClient */;
4518
+ target_laser_think(self, context);
4519
+ }
4520
+ function target_laser_off(self) {
4521
+ self.spawnflags &= ~1;
4522
+ self.svflags |= 1 /* NoClient */;
4523
+ self.nextthink = 0;
4524
+ }
4525
+ function target_laser_use(self, other, activator, context) {
4526
+ self.activator = activator;
4527
+ if (self.spawnflags & 1) {
4528
+ target_laser_off(self);
4529
+ } else {
4530
+ target_laser_on(self, context);
4531
+ }
4532
+ }
4533
+ function target_laser_start(self, context) {
4534
+ self.movetype = 0 /* None */;
4535
+ self.solid = 0 /* Not */;
4536
+ self.renderfx |= 8 | 64;
4537
+ self.modelindex = 1;
4538
+ if (self.spawnflags & TARGET_LASER_FAT) {
4539
+ self.frame = 16;
4540
+ } else {
4541
+ self.frame = 4;
4542
+ }
4543
+ if (self.spawnflags & TARGET_LASER_RED) {
4544
+ self.skin = 4076007664;
4545
+ } else if (self.spawnflags & TARGET_LASER_GREEN) {
4546
+ self.skin = 3503411923;
4547
+ } else if (self.spawnflags & TARGET_LASER_BLUE) {
4548
+ self.skin = 4092850673;
4549
+ } else if (self.spawnflags & TARGET_LASER_YELLOW) {
4550
+ self.skin = 3705528031;
4551
+ } else if (self.spawnflags & TARGET_LASER_ORANGE) {
4552
+ self.skin = 3772900067;
4553
+ }
4554
+ if (!self.enemy) {
4555
+ if (self.target) {
4556
+ let found = null;
4557
+ context.entities.forEachEntity((ent) => {
4558
+ if (ent.targetname === self.target) {
4559
+ found = ent;
4560
+ }
4561
+ });
4562
+ if (found) {
4563
+ self.enemy = found;
4564
+ } else {
4565
+ context.warn(`${self.classname} at ${self.origin}: ${self.target} is a bad target`);
4566
+ self.movedir = setMovedir(self.angles);
4567
+ }
4568
+ } else {
4569
+ self.movedir = setMovedir(self.angles);
4570
+ }
4571
+ }
4572
+ self.use = (s, o, a) => target_laser_use(s, o, a || null, context);
4573
+ self.think = (s) => target_laser_think(s, context);
4574
+ if (!self.dmg) {
4575
+ self.dmg = 1;
4576
+ }
4577
+ self.absmin = addVec3(self.origin, { x: -8, y: -8, z: -8 });
4578
+ self.absmax = addVec3(self.origin, { x: 8, y: 8, z: 8 });
4579
+ context.entities.linkentity(self);
4580
+ if (self.spawnflags & TARGET_LASER_START_ON) {
4581
+ target_laser_on(self, context);
4582
+ } else {
4583
+ target_laser_off(self);
4584
+ }
4585
+ }
4437
4586
  function registerTargetSpawns(registry) {
4438
4587
  registry.register("target_temp_entity", (entity, context) => {
4439
4588
  entity.style = context.keyValues.style ? parseInt(context.keyValues.style) : 0;
@@ -4516,6 +4665,10 @@ function registerTargetSpawns(registry) {
4516
4665
  if (!entity.speed) entity.speed = 1e3;
4517
4666
  entity.svflags |= 1 /* NoClient */;
4518
4667
  });
4668
+ registry.register("target_laser", (entity, context) => {
4669
+ entity.think = (self) => target_laser_start(self, context);
4670
+ entity.nextthink = context.entities.timeSeconds + 1;
4671
+ });
4519
4672
  }
4520
4673
 
4521
4674
  // src/entities/triggers.ts
@@ -9935,11 +10088,11 @@ function registerInfantrySpawns(registry) {
9935
10088
  registry.register("monster_infantry", SP_monster_infantry);
9936
10089
  }
9937
10090
 
9938
- // src/entities/monsters/jorg.ts
10091
+ // src/entities/monsters/makron.ts
9939
10092
  var MONSTER_TICK13 = 0.1;
9940
- var JORG_MACHINEGUN_R1_OFFSET = { x: 40, y: -20, z: 20 };
9941
- var JORG_MACHINEGUN_L1_OFFSET = { x: 40, y: 20, z: 20 };
9942
- var JORG_BFG_OFFSET = { x: 30, y: 0, z: 40 };
10093
+ var MAKRON_BFG_OFFSET = { x: 30, y: 28, z: 24 };
10094
+ var MAKRON_BLASTER_OFFSET_1 = { x: 26, y: 16, z: 24 };
10095
+ var MAKRON_RAILGUN_OFFSET = { x: 26, y: -14, z: 24 };
9943
10096
  function monster_ai_stand13(self, dist, context) {
9944
10097
  ai_stand(self, MONSTER_TICK13, context);
9945
10098
  }
@@ -9958,49 +10111,36 @@ function monster_ai_move13(self, dist, context) {
9958
10111
  var stand_move12;
9959
10112
  var walk_move11;
9960
10113
  var run_move11;
9961
- var attack1_move3;
9962
- var attack1_end_move;
9963
- var attack2_move2;
9964
- var pain1_move5;
9965
- var pain2_move5;
9966
- var pain3_move4;
10114
+ var attack_bfg_move;
10115
+ var attack_hyperblaster_move;
10116
+ var attack_railgun_move;
10117
+ var pain4_move;
10118
+ var pain5_move;
10119
+ var pain6_move;
9967
10120
  var death_move10;
9968
- function jorg_stand(self) {
10121
+ var sight_move;
10122
+ function makron_stand(self) {
9969
10123
  self.monsterinfo.current_move = stand_move12;
9970
10124
  }
9971
- function jorg_walk(self) {
10125
+ function makron_walk(self) {
9972
10126
  self.monsterinfo.current_move = walk_move11;
9973
10127
  }
9974
- function jorg_run(self) {
10128
+ function makron_run(self) {
9975
10129
  if (self.enemy && self.enemy.health > 0) {
9976
10130
  self.monsterinfo.current_move = run_move11;
9977
10131
  } else {
9978
10132
  self.monsterinfo.current_move = stand_move12;
9979
10133
  }
9980
10134
  }
9981
- function jorg_attack(self, context) {
10135
+ function makron_attack(self) {
9982
10136
  if (!self.enemy) return;
9983
- if (Math.random() <= 0.75) {
9984
- context.sound(self, 0, "boss3/bs3atck1.wav", 1, 1, 0);
9985
- self.monsterinfo.current_move = attack1_move3;
9986
- } else {
9987
- context.sound(self, 0, "boss3/bs3atck2.wav", 1, 1, 0);
9988
- self.monsterinfo.current_move = attack2_move2;
9989
- }
9990
- }
9991
- function jorg_reattack1(self, context) {
9992
- const traceFn = (start, mins, maxs, end, ignore, mask) => {
9993
- const tr = context.trace(start, mins, maxs, end, ignore, mask);
9994
- return { fraction: tr.fraction, ent: tr.ent };
9995
- };
9996
- if (self.enemy && visible(self, self.enemy, traceFn)) {
9997
- if (Math.random() < 0.9) {
9998
- self.monsterinfo.current_move = attack1_move3;
9999
- } else {
10000
- self.monsterinfo.current_move = attack1_end_move;
10001
- }
10137
+ const r = Math.random();
10138
+ if (r <= 0.3) {
10139
+ self.monsterinfo.current_move = attack_bfg_move;
10140
+ } else if (r <= 0.6) {
10141
+ self.monsterinfo.current_move = attack_hyperblaster_move;
10002
10142
  } else {
10003
- self.monsterinfo.current_move = attack1_end_move;
10143
+ self.monsterinfo.current_move = attack_railgun_move;
10004
10144
  }
10005
10145
  }
10006
10146
  function getProjectedOffset2(self, offset) {
@@ -10011,136 +10151,408 @@ function getProjectedOffset2(self, offset) {
10011
10151
  const z = scaleVec3(up, offset.z);
10012
10152
  return addVec3(addVec3(addVec3(start, x), y), z);
10013
10153
  }
10014
- function jorg_fire_bullet(self, context) {
10015
- if (!self.enemy) return;
10016
- const startL = getProjectedOffset2(self, JORG_MACHINEGUN_L1_OFFSET);
10017
- const dirL = normalizeVec3(subtractVec3(self.enemy.origin, startL));
10018
- monster_fire_bullet_v2(self, startL, dirL, 6, 4, 0.05, 0.05, 0, context, 4 /* MACHINEGUN */);
10019
- const startR = getProjectedOffset2(self, JORG_MACHINEGUN_R1_OFFSET);
10020
- const dirR = normalizeVec3(subtractVec3(self.enemy.origin, startR));
10021
- monster_fire_bullet_v2(self, startR, dirR, 6, 4, 0.05, 0.05, 0, context, 4 /* MACHINEGUN */);
10022
- }
10023
- function jorg_fire_bfg(self, context) {
10154
+ function makron_fire_bfg(self, context) {
10024
10155
  if (!self.enemy) return;
10025
- const start = getProjectedOffset2(self, JORG_BFG_OFFSET);
10156
+ context.engine.sound?.(self, 0, "makron/bfg_fire.wav", 1, 1, 0);
10157
+ const start = getProjectedOffset2(self, MAKRON_BFG_OFFSET);
10026
10158
  const target = { ...self.enemy.origin };
10027
10159
  target.z += self.enemy.viewheight || 0;
10028
10160
  const dir = normalizeVec3(subtractVec3(target, start));
10029
- monster_fire_bfg(self, start, dir, 50, 300, 100, 200, 0, context);
10161
+ monster_fire_bfg(self, start, dir, 50, 300, 100, 300, 0, context);
10030
10162
  }
10031
- function jorg_pain(self, other, kick, damage, context) {
10163
+ function makron_fire_railgun(self, context) {
10164
+ if (!self.pos1) return;
10165
+ context.engine.sound?.(self, 0, "makron/rail_fire.wav", 1, 1, 0);
10166
+ const start = getProjectedOffset2(self, MAKRON_RAILGUN_OFFSET);
10167
+ const dir = normalizeVec3(subtractVec3(self.pos1, start));
10168
+ monster_fire_railgun(self, start, dir, 50, 100, 0, context);
10169
+ }
10170
+ function makron_save_loc(self) {
10171
+ if (!self.enemy) return;
10172
+ self.pos1 = { ...self.enemy.origin };
10173
+ self.pos1 = { ...self.pos1, z: self.pos1.z + (self.enemy.viewheight || 0) };
10174
+ }
10175
+ function makron_fire_hyperblaster(self, context) {
10176
+ context.engine.sound?.(self, 0, "makron/blaster.wav", 1, 1, 0);
10177
+ const start = getProjectedOffset2(self, MAKRON_BLASTER_OFFSET_1);
10178
+ const relFrame = (self.monsterinfo.nextframe || 0) - attack_hyperblaster_move.firstframe;
10179
+ let yawDelta = 0;
10180
+ let dir;
10181
+ if (self.enemy) {
10182
+ const target = { ...self.enemy.origin };
10183
+ target.z += self.enemy.viewheight || 0;
10184
+ const vec = subtractVec3(target, start);
10185
+ const baseAngles = vectorToAngles(vec);
10186
+ const enemyAngles = { ...baseAngles };
10187
+ if (relFrame <= 12) {
10188
+ enemyAngles.y -= 5 * (relFrame - 4);
10189
+ } else {
10190
+ enemyAngles.y -= 40 - 5 * (relFrame - 12);
10191
+ }
10192
+ const forward = angleVectors(enemyAngles).forward;
10193
+ dir = forward;
10194
+ } else {
10195
+ const { forward } = angleVectors(self.angles);
10196
+ dir = forward;
10197
+ }
10198
+ monster_fire_blaster(self, start, dir, 15, 1e3, 0, 0, context, 1 /* BLASTER */);
10199
+ }
10200
+ function makron_pain(self, other, kick, damage, context) {
10032
10201
  if (self.health < self.max_health / 2) {
10033
10202
  self.skin = 1;
10034
10203
  }
10035
10204
  if (self.timestamp < (self.pain_finished_time || 0)) return;
10036
- if (damage <= 40 && Math.random() <= 0.6) return;
10037
- if (self.monsterinfo.current_move === attack1_move3 || self.monsterinfo.current_move === attack2_move2) {
10038
- if (Math.random() <= 5e-3) return;
10039
- }
10205
+ if (damage <= 25 && Math.random() < 0.2) return;
10040
10206
  self.pain_finished_time = self.timestamp + 3;
10041
- if (damage <= 50) {
10042
- context.engine.sound?.(self, 0, "boss3/bs3pain1.wav", 1, 1, 0);
10043
- self.monsterinfo.current_move = pain1_move5;
10044
- } else if (damage <= 100) {
10045
- context.engine.sound?.(self, 0, "boss3/bs3pain2.wav", 1, 1, 0);
10046
- self.monsterinfo.current_move = pain2_move5;
10207
+ if (damage <= 40) {
10208
+ context.engine.sound?.(self, 0, "makron/pain1.wav", 1, 1, 0);
10209
+ self.monsterinfo.current_move = pain4_move;
10210
+ } else if (damage <= 110) {
10211
+ context.engine.sound?.(self, 0, "makron/pain2.wav", 1, 1, 0);
10212
+ self.monsterinfo.current_move = pain5_move;
10047
10213
  } else {
10048
- if (Math.random() <= 0.3) {
10049
- context.engine.sound?.(self, 0, "boss3/bs3pain3.wav", 1, 1, 0);
10050
- self.monsterinfo.current_move = pain3_move4;
10214
+ if (Math.random() <= 0.45) {
10215
+ context.engine.sound?.(self, 0, "makron/pain3.wav", 1, 1, 0);
10216
+ self.monsterinfo.current_move = pain6_move;
10051
10217
  }
10052
10218
  }
10053
10219
  }
10054
- function jorg_die(self, context) {
10055
- context.engine.sound?.(self, 0, "boss3/bs3deth1.wav", 1, 1, 0);
10220
+ function makron_torso_think(self, context) {
10221
+ if (++self.frame >= 365)
10222
+ self.frame = 346;
10223
+ self.nextthink = context.timeSeconds + 0.1;
10224
+ if (self.angles.x > 0)
10225
+ self.angles = { ...self.angles, x: Math.max(0, self.angles.x - 15) };
10226
+ }
10227
+ function makron_torso(ent, context) {
10228
+ ent.frame = 346;
10229
+ ent.model = "models/monsters/boss3/rider/tris.md2";
10230
+ ent.skin = 1;
10231
+ ent.think = makron_torso_think;
10232
+ ent.nextthink = context.timeSeconds + 0.1;
10233
+ context.sound(ent, 0, "makron/spine.wav", 1, 1, 0);
10234
+ ent.movetype = 7 /* Toss */;
10235
+ const { forward, up } = angleVectors(ent.angles);
10236
+ const vUp = scaleVec3(up, 120);
10237
+ const vFwd = scaleVec3(forward, -120);
10238
+ ent.velocity = addVec3(addVec3(ent.velocity, vUp), vFwd);
10239
+ ent.origin = addVec3(ent.origin, scaleVec3(forward, -10));
10240
+ ent.angles = { ...ent.angles, x: 90 };
10241
+ ent.avelocity = ZERO_VEC3;
10242
+ context.linkentity(ent);
10243
+ }
10244
+ function makron_spawn_torso(self, context) {
10245
+ const tempent = context.spawn();
10246
+ tempent.classname = "makron_torso";
10247
+ tempent.origin = { ...self.origin };
10248
+ tempent.angles = { ...self.angles };
10249
+ tempent.origin.z += self.maxs.z - 15;
10250
+ makron_torso(tempent, context);
10251
+ }
10252
+ function makron_die(self, context) {
10253
+ context.engine.sound?.(self, 0, "makron/death.wav", 1, 1, 0);
10254
+ makron_spawn_torso(self, context);
10056
10255
  self.monsterinfo.current_move = death_move10;
10256
+ self.mins = { x: -60, y: -60, z: 0 };
10257
+ self.maxs = { x: 60, y: 60, z: 48 };
10057
10258
  }
10058
- function jorg_dead(self) {
10259
+ function makron_dead(self) {
10059
10260
  self.monsterinfo.nextframe = death_move10.lastframe;
10060
10261
  self.nextthink = -1;
10061
10262
  }
10062
- function makron_toss(self, context) {
10063
- const makron = context.spawn();
10064
- makron.classname = "monster_makron";
10065
- makron.origin = { ...self.origin };
10066
- makron.angles = { ...self.angles };
10067
- }
10068
- var stand_frames12 = Array.from({ length: 51 }, () => ({ ai: monster_ai_stand13, dist: 0 }));
10069
- stand_move12 = { firstframe: 0, lastframe: 50, frames: stand_frames12, endfunc: jorg_stand };
10070
- var walk_frames11 = Array.from({ length: 14 }, () => ({ ai: monster_ai_walk13, dist: 10 }));
10071
- walk_move11 = { firstframe: 51, lastframe: 64, frames: walk_frames11, endfunc: jorg_walk };
10072
- var run_frames10 = Array.from({ length: 14 }, () => ({ ai: monster_ai_run12, dist: 10 }));
10073
- run_move11 = { firstframe: 51, lastframe: 64, frames: run_frames10, endfunc: jorg_run };
10074
- var attack1_start_frames = Array.from({ length: 8 }, () => ({ ai: monster_ai_charge13, dist: 0 }));
10075
- var attack1_start_move = { firstframe: 65, lastframe: 72, frames: attack1_start_frames, endfunc: null };
10076
- var attack1_frames3 = Array.from({ length: 6 }, () => ({ ai: monster_ai_charge13, dist: 0, think: jorg_fire_bullet }));
10077
- attack1_move3 = { firstframe: 73, lastframe: 78, frames: attack1_frames3, endfunc: jorg_reattack1 };
10078
- attack1_start_move.endfunc = (self) => {
10079
- self.monsterinfo.current_move = attack1_move3;
10080
- };
10081
- var attack1_end_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10082
- attack1_end_move = { firstframe: 79, lastframe: 82, frames: attack1_end_frames, endfunc: jorg_run };
10083
- var attack2_frames2 = Array.from({ length: 13 }, (_, i) => ({
10263
+ var stand_frames12 = Array.from({ length: 60 }, () => ({ ai: monster_ai_stand13, dist: 0 }));
10264
+ stand_move12 = { firstframe: 0, lastframe: 59, frames: stand_frames12, endfunc: makron_stand };
10265
+ var walk_frames11 = Array.from({ length: 10 }, () => ({ ai: monster_ai_walk13, dist: 8 }));
10266
+ walk_move11 = { firstframe: 60, lastframe: 69, frames: walk_frames11, endfunc: makron_walk };
10267
+ var run_frames10 = Array.from({ length: 10 }, () => ({ ai: monster_ai_run12, dist: 8 }));
10268
+ run_move11 = { firstframe: 60, lastframe: 69, frames: run_frames10, endfunc: makron_run };
10269
+ var attack_bfg_frames = Array.from({ length: 8 }, (_, i) => ({
10084
10270
  ai: monster_ai_charge13,
10085
10271
  dist: 0,
10086
- think: i === 6 ? jorg_fire_bfg : null
10272
+ think: i === 3 ? makron_fire_bfg : null
10087
10273
  }));
10088
- attack2_move2 = { firstframe: 83, lastframe: 95, frames: attack2_frames2, endfunc: jorg_run };
10089
- var pain1_frames5 = Array.from({ length: 3 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10090
- pain1_move5 = { firstframe: 96, lastframe: 98, frames: pain1_frames5, endfunc: jorg_run };
10091
- var pain2_frames5 = Array.from({ length: 3 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10092
- pain2_move5 = { firstframe: 99, lastframe: 101, frames: pain2_frames5, endfunc: jorg_run };
10093
- var pain3_frames4 = Array.from({ length: 25 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10094
- pain3_move4 = { firstframe: 102, lastframe: 126, frames: pain3_frames4, endfunc: jorg_run };
10095
- var death_frames10 = Array.from({ length: 50 }, (_, i) => ({
10274
+ attack_bfg_move = { firstframe: 70, lastframe: 77, frames: attack_bfg_frames, endfunc: makron_run };
10275
+ var attack_hyperblaster_frames = Array.from({ length: 26 }, (_, i) => ({
10096
10276
  ai: monster_ai_move13,
10097
10277
  dist: 0,
10098
- think: i === 49 ? ((self, ctx) => {
10099
- }) : i === 48 ? makron_toss : null
10278
+ think: i >= 4 && i <= 20 ? makron_fire_hyperblaster : null
10100
10279
  }));
10101
- death_move10 = { firstframe: 127, lastframe: 176, frames: death_frames10, endfunc: jorg_dead };
10102
- function SP_monster_jorg(self, context) {
10103
- self.classname = "monster_jorg";
10104
- self.model = "models/monsters/boss3/jorg/tris.md2";
10105
- self.mins = { x: -80, y: -80, z: 0 };
10106
- self.maxs = { x: 80, y: 80, z: 140 };
10280
+ attack_hyperblaster_move = { firstframe: 78, lastframe: 103, frames: attack_hyperblaster_frames, endfunc: makron_run };
10281
+ var attack_railgun_frames = Array.from({ length: 16 }, (_, i) => ({
10282
+ ai: monster_ai_charge13,
10283
+ dist: 0,
10284
+ think: i === 7 ? makron_save_loc : i === 8 ? makron_fire_railgun : null
10285
+ }));
10286
+ attack_railgun_move = { firstframe: 104, lastframe: 119, frames: attack_railgun_frames, endfunc: makron_run };
10287
+ var pain4_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10288
+ pain4_move = { firstframe: 120, lastframe: 123, frames: pain4_frames, endfunc: makron_run };
10289
+ var pain5_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10290
+ pain5_move = { firstframe: 124, lastframe: 127, frames: pain5_frames, endfunc: makron_run };
10291
+ var pain6_frames = Array.from({ length: 27 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10292
+ pain6_move = { firstframe: 128, lastframe: 154, frames: pain6_frames, endfunc: makron_run };
10293
+ var death_frames10 = Array.from({ length: 95 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10294
+ death_move10 = { firstframe: 155, lastframe: 249, frames: death_frames10, endfunc: makron_dead };
10295
+ var sight_frames = Array.from({ length: 13 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10296
+ sight_move = { firstframe: 250, lastframe: 262, frames: sight_frames, endfunc: makron_run };
10297
+ function SP_monster_makron(self, context) {
10298
+ self.classname = "monster_makron";
10299
+ self.model = "models/monsters/boss3/rider/tris.md2";
10300
+ self.mins = { x: -30, y: -30, z: 0 };
10301
+ self.maxs = { x: 30, y: 30, z: 90 };
10107
10302
  self.movetype = 5 /* Step */;
10108
10303
  self.solid = 2 /* BoundingBox */;
10109
10304
  self.health = 3e3;
10110
10305
  self.max_health = 3e3;
10111
- self.mass = 1e3;
10306
+ self.mass = 500;
10112
10307
  self.takedamage = true;
10113
10308
  self.viewheight = 90;
10114
- self.pain = (ent, other, kick, dmg) => jorg_pain(ent, other, kick, dmg, context.entities);
10309
+ self.pain = (ent, other, kick, dmg) => makron_pain(ent, other, kick, dmg, context.entities);
10115
10310
  self.die = (self2, inflictor, attacker, damage, point) => {
10116
- self2.deadflag = 2 /* Dead */;
10117
- self2.solid = 0 /* Not */;
10118
- if (self2.health < -2e3) {
10311
+ if (self2.health <= -2e3) {
10119
10312
  throwGibs(context.entities, self2.origin, damage);
10120
10313
  context.entities.free(self2);
10121
10314
  return;
10122
10315
  }
10123
- jorg_die(self2, context.entities);
10316
+ self2.deadflag = 2 /* Dead */;
10317
+ self2.solid = 0 /* Not */;
10318
+ makron_die(self2, context.entities);
10124
10319
  };
10125
- self.monsterinfo.stand = jorg_stand;
10126
- self.monsterinfo.walk = jorg_walk;
10127
- self.monsterinfo.run = jorg_run;
10128
- self.monsterinfo.attack = (ent) => jorg_attack(ent, context.entities);
10320
+ self.monsterinfo.stand = makron_stand;
10321
+ self.monsterinfo.walk = makron_walk;
10322
+ self.monsterinfo.run = makron_run;
10323
+ self.monsterinfo.attack = makron_attack;
10129
10324
  self.monsterinfo.sight = (self2, other) => {
10130
- context.entities.sound?.(self2, 0, "boss3/sight1.wav", 1, 1, 0);
10325
+ context.entities.sound?.(self2, 0, "makron/sight.wav", 1, 1, 0);
10326
+ self2.monsterinfo.current_move = sight_move;
10131
10327
  };
10132
10328
  self.think = monster_think;
10133
- jorg_stand(self);
10329
+ self.monsterinfo.current_move = sight_move;
10134
10330
  self.nextthink = self.timestamp + MONSTER_TICK13;
10135
10331
  }
10136
- function registerJorgSpawns(registry) {
10137
- registry.register("monster_jorg", SP_monster_jorg);
10332
+ function registerMakronSpawns(registry) {
10333
+ registry.register("monster_makron", SP_monster_makron);
10138
10334
  }
10139
10335
 
10140
- // src/entities/monsters/insane.ts
10336
+ // src/entities/monsters/jorg.ts
10141
10337
  var MONSTER_TICK14 = 0.1;
10142
- var SPAWNFLAG_INSANE_CRAWL = 4;
10143
- var SPAWNFLAG_INSANE_CRUCIFIED = 8;
10338
+ var JORG_MACHINEGUN_R1_OFFSET = { x: 40, y: -20, z: 20 };
10339
+ var JORG_MACHINEGUN_L1_OFFSET = { x: 40, y: 20, z: 20 };
10340
+ var JORG_BFG_OFFSET = { x: 30, y: 0, z: 40 };
10341
+ function monster_ai_stand14(self, dist, context) {
10342
+ ai_stand(self, MONSTER_TICK14, context);
10343
+ }
10344
+ function monster_ai_walk14(self, dist, context) {
10345
+ ai_walk(self, dist, MONSTER_TICK14, context);
10346
+ }
10347
+ function monster_ai_run13(self, dist, context) {
10348
+ ai_run(self, dist, MONSTER_TICK14, context);
10349
+ }
10350
+ function monster_ai_charge14(self, dist, context) {
10351
+ ai_charge(self, dist, MONSTER_TICK14, context);
10352
+ }
10353
+ function monster_ai_move14(self, dist, context) {
10354
+ ai_move(self, dist);
10355
+ }
10356
+ var stand_move13;
10357
+ var walk_move12;
10358
+ var run_move12;
10359
+ var attack1_move3;
10360
+ var attack1_end_move;
10361
+ var attack2_move2;
10362
+ var pain1_move5;
10363
+ var pain2_move5;
10364
+ var pain3_move4;
10365
+ var death_move11;
10366
+ function jorg_stand(self) {
10367
+ self.monsterinfo.current_move = stand_move13;
10368
+ }
10369
+ function jorg_walk(self) {
10370
+ self.monsterinfo.current_move = walk_move12;
10371
+ }
10372
+ function jorg_run(self) {
10373
+ if (self.enemy && self.enemy.health > 0) {
10374
+ self.monsterinfo.current_move = run_move12;
10375
+ } else {
10376
+ self.monsterinfo.current_move = stand_move13;
10377
+ }
10378
+ }
10379
+ function jorg_attack(self, context) {
10380
+ if (!self.enemy) return;
10381
+ if (Math.random() <= 0.75) {
10382
+ context.sound(self, 0, "boss3/bs3atck1.wav", 1, 1, 0);
10383
+ self.monsterinfo.current_move = attack1_move3;
10384
+ } else {
10385
+ context.sound(self, 0, "boss3/bs3atck2.wav", 1, 1, 0);
10386
+ self.monsterinfo.current_move = attack2_move2;
10387
+ }
10388
+ }
10389
+ function jorg_reattack1(self, context) {
10390
+ const traceFn = (start, mins, maxs, end, ignore, mask) => {
10391
+ const tr = context.trace(start, mins, maxs, end, ignore, mask);
10392
+ return { fraction: tr.fraction, ent: tr.ent };
10393
+ };
10394
+ if (self.enemy && visible(self, self.enemy, traceFn)) {
10395
+ if (Math.random() < 0.9) {
10396
+ self.monsterinfo.current_move = attack1_move3;
10397
+ } else {
10398
+ self.monsterinfo.current_move = attack1_end_move;
10399
+ }
10400
+ } else {
10401
+ self.monsterinfo.current_move = attack1_end_move;
10402
+ }
10403
+ }
10404
+ function getProjectedOffset3(self, offset) {
10405
+ const { forward, right, up } = angleVectors(self.angles);
10406
+ const start = { ...self.origin };
10407
+ const x = scaleVec3(forward, offset.x);
10408
+ const y = scaleVec3(right, offset.y);
10409
+ const z = scaleVec3(up, offset.z);
10410
+ return addVec3(addVec3(addVec3(start, x), y), z);
10411
+ }
10412
+ function jorg_fire_bullet(self, context) {
10413
+ if (!self.enemy) return;
10414
+ const startL = getProjectedOffset3(self, JORG_MACHINEGUN_L1_OFFSET);
10415
+ const dirL = normalizeVec3(subtractVec3(self.enemy.origin, startL));
10416
+ monster_fire_bullet_v2(self, startL, dirL, 6, 4, 0.05, 0.05, 0, context, 4 /* MACHINEGUN */);
10417
+ const startR = getProjectedOffset3(self, JORG_MACHINEGUN_R1_OFFSET);
10418
+ const dirR = normalizeVec3(subtractVec3(self.enemy.origin, startR));
10419
+ monster_fire_bullet_v2(self, startR, dirR, 6, 4, 0.05, 0.05, 0, context, 4 /* MACHINEGUN */);
10420
+ }
10421
+ function jorg_fire_bfg(self, context) {
10422
+ if (!self.enemy) return;
10423
+ const start = getProjectedOffset3(self, JORG_BFG_OFFSET);
10424
+ const target = { ...self.enemy.origin };
10425
+ target.z += self.enemy.viewheight || 0;
10426
+ const dir = normalizeVec3(subtractVec3(target, start));
10427
+ monster_fire_bfg(self, start, dir, 50, 300, 100, 200, 0, context);
10428
+ }
10429
+ function jorg_pain(self, other, kick, damage, context) {
10430
+ if (self.health < self.max_health / 2) {
10431
+ self.skin = 1;
10432
+ }
10433
+ if (self.timestamp < (self.pain_finished_time || 0)) return;
10434
+ if (damage <= 40 && Math.random() <= 0.6) return;
10435
+ if (self.monsterinfo.current_move === attack1_move3 || self.monsterinfo.current_move === attack2_move2) {
10436
+ if (Math.random() <= 5e-3) return;
10437
+ }
10438
+ self.pain_finished_time = self.timestamp + 3;
10439
+ if (damage <= 50) {
10440
+ context.engine.sound?.(self, 0, "boss3/bs3pain1.wav", 1, 1, 0);
10441
+ self.monsterinfo.current_move = pain1_move5;
10442
+ } else if (damage <= 100) {
10443
+ context.engine.sound?.(self, 0, "boss3/bs3pain2.wav", 1, 1, 0);
10444
+ self.monsterinfo.current_move = pain2_move5;
10445
+ } else {
10446
+ if (Math.random() <= 0.3) {
10447
+ context.engine.sound?.(self, 0, "boss3/bs3pain3.wav", 1, 1, 0);
10448
+ self.monsterinfo.current_move = pain3_move4;
10449
+ }
10450
+ }
10451
+ }
10452
+ function jorg_die(self, context) {
10453
+ context.engine.sound?.(self, 0, "boss3/bs3deth1.wav", 1, 1, 0);
10454
+ self.monsterinfo.current_move = death_move11;
10455
+ }
10456
+ function jorg_dead(self) {
10457
+ self.monsterinfo.nextframe = death_move11.lastframe;
10458
+ self.nextthink = -1;
10459
+ }
10460
+ function makron_toss(self, context) {
10461
+ const makron = context.spawn();
10462
+ makron.classname = "monster_makron";
10463
+ makron.origin = { ...self.origin };
10464
+ makron.target = self.target;
10465
+ makron.enemy = self.enemy;
10466
+ const spawnContext = { entities: context };
10467
+ SP_monster_makron(makron, spawnContext);
10468
+ if (makron.enemy && makron.enemy.health > 0) {
10469
+ const vec = subtractVec3(makron.enemy.origin, makron.origin);
10470
+ makron.angles = { ...makron.angles, y: vectorToYaw(vec) };
10471
+ const dir = normalizeVec3(vec);
10472
+ const vel = scaleVec3(dir, 400);
10473
+ makron.velocity = { x: vel.x, y: vel.y, z: 200 };
10474
+ makron.groundentity = null;
10475
+ if (makron.monsterinfo.sight) {
10476
+ makron.monsterinfo.sight(makron, makron.enemy);
10477
+ }
10478
+ }
10479
+ }
10480
+ var stand_frames13 = Array.from({ length: 51 }, () => ({ ai: monster_ai_stand14, dist: 0 }));
10481
+ stand_move13 = { firstframe: 0, lastframe: 50, frames: stand_frames13, endfunc: jorg_stand };
10482
+ var walk_frames12 = Array.from({ length: 14 }, () => ({ ai: monster_ai_walk14, dist: 10 }));
10483
+ walk_move12 = { firstframe: 51, lastframe: 64, frames: walk_frames12, endfunc: jorg_walk };
10484
+ var run_frames11 = Array.from({ length: 14 }, () => ({ ai: monster_ai_run13, dist: 10 }));
10485
+ run_move12 = { firstframe: 51, lastframe: 64, frames: run_frames11, endfunc: jorg_run };
10486
+ var attack1_start_frames = Array.from({ length: 8 }, () => ({ ai: monster_ai_charge14, dist: 0 }));
10487
+ var attack1_start_move = { firstframe: 65, lastframe: 72, frames: attack1_start_frames, endfunc: null };
10488
+ var attack1_frames3 = Array.from({ length: 6 }, () => ({ ai: monster_ai_charge14, dist: 0, think: jorg_fire_bullet }));
10489
+ attack1_move3 = { firstframe: 73, lastframe: 78, frames: attack1_frames3, endfunc: jorg_reattack1 };
10490
+ attack1_start_move.endfunc = (self) => {
10491
+ self.monsterinfo.current_move = attack1_move3;
10492
+ };
10493
+ var attack1_end_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10494
+ attack1_end_move = { firstframe: 79, lastframe: 82, frames: attack1_end_frames, endfunc: jorg_run };
10495
+ var attack2_frames2 = Array.from({ length: 13 }, (_, i) => ({
10496
+ ai: monster_ai_charge14,
10497
+ dist: 0,
10498
+ think: i === 6 ? jorg_fire_bfg : null
10499
+ }));
10500
+ attack2_move2 = { firstframe: 83, lastframe: 95, frames: attack2_frames2, endfunc: jorg_run };
10501
+ var pain1_frames5 = Array.from({ length: 3 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10502
+ pain1_move5 = { firstframe: 96, lastframe: 98, frames: pain1_frames5, endfunc: jorg_run };
10503
+ var pain2_frames5 = Array.from({ length: 3 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10504
+ pain2_move5 = { firstframe: 99, lastframe: 101, frames: pain2_frames5, endfunc: jorg_run };
10505
+ var pain3_frames4 = Array.from({ length: 25 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10506
+ pain3_move4 = { firstframe: 102, lastframe: 126, frames: pain3_frames4, endfunc: jorg_run };
10507
+ var death_frames11 = Array.from({ length: 50 }, (_, i) => ({
10508
+ ai: monster_ai_move14,
10509
+ dist: 0,
10510
+ think: i === 49 ? ((self, ctx) => {
10511
+ }) : i === 48 ? makron_toss : null
10512
+ }));
10513
+ death_move11 = { firstframe: 127, lastframe: 176, frames: death_frames11, endfunc: jorg_dead };
10514
+ function SP_monster_jorg(self, context) {
10515
+ self.classname = "monster_jorg";
10516
+ self.model = "models/monsters/boss3/jorg/tris.md2";
10517
+ self.mins = { x: -80, y: -80, z: 0 };
10518
+ self.maxs = { x: 80, y: 80, z: 140 };
10519
+ self.movetype = 5 /* Step */;
10520
+ self.solid = 2 /* BoundingBox */;
10521
+ self.health = 3e3;
10522
+ self.max_health = 3e3;
10523
+ self.mass = 1e3;
10524
+ self.takedamage = true;
10525
+ self.viewheight = 90;
10526
+ self.pain = (ent, other, kick, dmg) => jorg_pain(ent, other, kick, dmg, context.entities);
10527
+ self.die = (self2, inflictor, attacker, damage, point) => {
10528
+ self2.deadflag = 2 /* Dead */;
10529
+ self2.solid = 0 /* Not */;
10530
+ if (self2.health < -2e3) {
10531
+ throwGibs(context.entities, self2.origin, damage);
10532
+ context.entities.free(self2);
10533
+ return;
10534
+ }
10535
+ jorg_die(self2, context.entities);
10536
+ };
10537
+ self.monsterinfo.stand = jorg_stand;
10538
+ self.monsterinfo.walk = jorg_walk;
10539
+ self.monsterinfo.run = jorg_run;
10540
+ self.monsterinfo.attack = (ent) => jorg_attack(ent, context.entities);
10541
+ self.monsterinfo.sight = (self2, other) => {
10542
+ context.entities.sound?.(self2, 0, "boss3/sight1.wav", 1, 1, 0);
10543
+ };
10544
+ self.think = monster_think;
10545
+ jorg_stand(self);
10546
+ self.nextthink = self.timestamp + MONSTER_TICK14;
10547
+ }
10548
+ function registerJorgSpawns(registry) {
10549
+ registry.register("monster_jorg", SP_monster_jorg);
10550
+ }
10551
+
10552
+ // src/entities/monsters/insane.ts
10553
+ var MONSTER_TICK15 = 0.1;
10554
+ var SPAWNFLAG_INSANE_CRAWL = 4;
10555
+ var SPAWNFLAG_INSANE_CRUCIFIED = 8;
10144
10556
  var SPAWNFLAG_INSANE_STAND_GROUND = 16;
10145
10557
  var SPAWNFLAG_INSANE_ALWAYS_STAND = 32;
10146
10558
  var SPAWNFLAG_INSANE_QUIET = 64;
@@ -10308,7 +10720,7 @@ function insane_dead(self, context) {
10308
10720
  function m(ai, dist = 0, think) {
10309
10721
  return { ai: (s, d, c) => {
10310
10722
  if (think) think(s, c);
10311
- ai(s, dist, MONSTER_TICK14, c);
10723
+ ai(s, dist, MONSTER_TICK15, c);
10312
10724
  }, dist };
10313
10725
  }
10314
10726
  var frames_stand_normal = [
@@ -10547,7 +10959,7 @@ insane_move_run_normal = {
10547
10959
  frames: frames_walk_normal.map((f) => ({
10548
10960
  ai: (s, d, c) => {
10549
10961
  if (f.ai === frames_walk_normal[0].ai) insane_scream(s, c);
10550
- ai_run(s, d, MONSTER_TICK14, c);
10962
+ ai_run(s, d, MONSTER_TICK15, c);
10551
10963
  },
10552
10964
  dist: f.dist
10553
10965
  })),
@@ -10593,7 +11005,7 @@ insane_move_run_insane = {
10593
11005
  frames: frames_walk_insane.map((f) => ({
10594
11006
  ai: (s, d, c) => {
10595
11007
  if (f.ai === frames_walk_insane[0].ai) insane_scream(s, c);
10596
- ai_run(s, d, MONSTER_TICK14, c);
11008
+ ai_run(s, d, MONSTER_TICK15, c);
10597
11009
  },
10598
11010
  dist: f.dist
10599
11011
  })),
@@ -10820,7 +11232,7 @@ function SP_misc_insane(self, context) {
10820
11232
  self.monsterinfo.current_move = insane_move_stand_normal;
10821
11233
  self.monsterinfo.scale = 1;
10822
11234
  self.think = monster_think;
10823
- self.nextthink = context.entities.timeSeconds + MONSTER_TICK14;
11235
+ self.nextthink = context.entities.timeSeconds + MONSTER_TICK15;
10824
11236
  if (self.spawnflags & SPAWNFLAG_INSANE_CRUCIFIED) {
10825
11237
  self.mass = 1e5;
10826
11238
  }
@@ -10830,218 +11242,548 @@ function registerInsaneSpawns(registry) {
10830
11242
  registry.register("misc_insane", SP_misc_insane);
10831
11243
  }
10832
11244
 
10833
- // src/entities/monsters/makron.ts
10834
- var MONSTER_TICK15 = 0.1;
10835
- var MAKRON_BFG_OFFSET = { x: 30, y: 28, z: 24 };
10836
- var MAKRON_BLASTER_OFFSET_1 = { x: 26, y: 16, z: 24 };
10837
- var MAKRON_RAILGUN_OFFSET = { x: 26, y: -14, z: 24 };
10838
- function monster_ai_stand14(self, dist, context) {
10839
- ai_stand(self, MONSTER_TICK15, context);
10840
- }
10841
- function monster_ai_walk14(self, dist, context) {
10842
- ai_walk(self, dist, MONSTER_TICK15, context);
10843
- }
10844
- function monster_ai_run13(self, dist, context) {
10845
- ai_run(self, dist, MONSTER_TICK15, context);
10846
- }
10847
- function monster_ai_charge14(self, dist, context) {
10848
- ai_charge(self, dist, MONSTER_TICK15, context);
10849
- }
10850
- function monster_ai_move14(self, dist, context) {
10851
- ai_move(self, dist);
11245
+ // src/entities/monsters/actor.ts
11246
+ var MONSTER_TICK16 = 0.1;
11247
+ var MZ2_ACTOR_MACHINEGUN_1 = 0;
11248
+ var actor_names = [
11249
+ "Hellrot",
11250
+ "Tokay",
11251
+ "Killme",
11252
+ "Disruptor",
11253
+ "Adrianator",
11254
+ "Rambear",
11255
+ "Titus",
11256
+ "Bitterman"
11257
+ ];
11258
+ var FRAME_stand101 = 0;
11259
+ var FRAME_stand140 = 39;
11260
+ var FRAME_walk01 = 40;
11261
+ var FRAME_walk08 = 47;
11262
+ var FRAME_run02 = 48;
11263
+ var FRAME_run07 = 53;
11264
+ var FRAME_pain101 = 54;
11265
+ var FRAME_pain103 = 56;
11266
+ var FRAME_pain201 = 57;
11267
+ var FRAME_pain203 = 59;
11268
+ var FRAME_pain301 = 60;
11269
+ var FRAME_pain303 = 62;
11270
+ var FRAME_flip01 = 63;
11271
+ var FRAME_flip14 = 76;
11272
+ var FRAME_taunt01 = 77;
11273
+ var FRAME_taunt17 = 93;
11274
+ var FRAME_death101 = 94;
11275
+ var FRAME_death107 = 100;
11276
+ var FRAME_death201 = 101;
11277
+ var FRAME_death213 = 113;
11278
+ var FRAME_attak01 = 114;
11279
+ var FRAME_attak04 = 117;
11280
+ var actor_move_stand;
11281
+ var actor_move_walk;
11282
+ var actor_move_run;
11283
+ var actor_move_pain1;
11284
+ var actor_move_pain2;
11285
+ var actor_move_pain3;
11286
+ var actor_move_flipoff;
11287
+ var actor_move_taunt;
11288
+ var actor_move_death1;
11289
+ var actor_move_death2;
11290
+ var actor_move_attack;
11291
+ function m2(ai, dist = 0, think) {
11292
+ return { ai: (s, d, c) => {
11293
+ if (think) think(s, c);
11294
+ ai(s, dist, MONSTER_TICK16, c);
11295
+ }, dist };
10852
11296
  }
10853
- var stand_move13;
10854
- var walk_move12;
10855
- var run_move12;
10856
- var attack_bfg_move;
10857
- var attack_hyperblaster_move;
10858
- var attack_railgun_move;
10859
- var pain4_move;
10860
- var pain5_move;
10861
- var pain6_move;
10862
- var death_move11;
10863
- var sight_move;
10864
- function makron_stand(self) {
10865
- self.monsterinfo.current_move = stand_move13;
11297
+ function actor_stand(self, context) {
11298
+ self.monsterinfo.current_move = actor_move_stand;
11299
+ if (context.timeSeconds < 1) {
11300
+ self.frame = FRAME_stand101 + Math.floor(Math.random() * (FRAME_stand140 - FRAME_stand101 + 1));
11301
+ }
10866
11302
  }
10867
- function makron_walk(self) {
10868
- self.monsterinfo.current_move = walk_move12;
11303
+ function actor_walk(self, context) {
11304
+ self.monsterinfo.current_move = actor_move_walk;
10869
11305
  }
10870
- function makron_run(self) {
10871
- if (self.enemy && self.enemy.health > 0) {
10872
- self.monsterinfo.current_move = run_move12;
10873
- } else {
10874
- self.monsterinfo.current_move = stand_move13;
11306
+ function actor_run(self, context) {
11307
+ if (context.timeSeconds < self.pain_debounce_time && !self.enemy) {
11308
+ if (self.movetarget)
11309
+ actor_walk(self, context);
11310
+ else
11311
+ actor_stand(self, context);
11312
+ return;
10875
11313
  }
10876
- }
10877
- function makron_attack(self) {
10878
- if (!self.enemy) return;
10879
- const r = Math.random();
10880
- if (r <= 0.3) {
10881
- self.monsterinfo.current_move = attack_bfg_move;
10882
- } else if (r <= 0.6) {
10883
- self.monsterinfo.current_move = attack_hyperblaster_move;
10884
- } else {
10885
- self.monsterinfo.current_move = attack_railgun_move;
11314
+ if (self.monsterinfo.aiflags & 1 /* StandGround */) {
11315
+ actor_stand(self, context);
11316
+ return;
10886
11317
  }
11318
+ self.monsterinfo.current_move = actor_move_run;
10887
11319
  }
10888
- function getProjectedOffset3(self, offset) {
10889
- const { forward, right, up } = angleVectors(self.angles);
10890
- const start = { ...self.origin };
10891
- const x = scaleVec3(forward, offset.x);
10892
- const y = scaleVec3(right, offset.y);
10893
- const z = scaleVec3(up, offset.z);
10894
- return addVec3(addVec3(addVec3(start, x), y), z);
10895
- }
10896
- function makron_fire_bfg(self, context) {
10897
- if (!self.enemy) return;
10898
- context.engine.sound?.(self, 0, "makron/bfg_fire.wav", 1, 1, 0);
10899
- const start = getProjectedOffset3(self, MAKRON_BFG_OFFSET);
10900
- const target = { ...self.enemy.origin };
10901
- target.z += self.enemy.viewheight || 0;
10902
- const dir = normalizeVec3(subtractVec3(target, start));
10903
- monster_fire_bfg(self, start, dir, 50, 300, 100, 300, 0, context);
10904
- }
10905
- function makron_fire_railgun(self, context) {
10906
- if (!self.pos1) return;
10907
- context.engine.sound?.(self, 0, "makron/rail_fire.wav", 1, 1, 0);
10908
- const start = getProjectedOffset3(self, MAKRON_RAILGUN_OFFSET);
10909
- const dir = normalizeVec3(subtractVec3(self.pos1, start));
10910
- monster_fire_railgun(self, start, dir, 50, 100, 0, context);
11320
+ var messages = [
11321
+ "Watch it",
11322
+ "#$@*&",
11323
+ "Idiot",
11324
+ "Check your targets"
11325
+ ];
11326
+ function actor_pain(self, other, kick, damage) {
11327
+ const context = self.monsterinfo.context;
11328
+ if (!context) return;
11329
+ if (context.timeSeconds < self.pain_debounce_time)
11330
+ return;
11331
+ self.pain_debounce_time = context.timeSeconds + 3;
11332
+ const random10 = Math.random();
11333
+ if (other && other.client && random10 < 0.4) {
11334
+ const v = subtractVec3(other.origin, self.origin);
11335
+ self.ideal_yaw = vectorToYaw(v);
11336
+ if (Math.random() < 0.5)
11337
+ self.monsterinfo.current_move = actor_move_flipoff;
11338
+ else
11339
+ self.monsterinfo.current_move = actor_move_taunt;
11340
+ const name = actor_names[Math.floor(Math.random() * actor_names.length)];
11341
+ const message = messages[Math.floor(Math.random() * messages.length)];
11342
+ context.centerprintf(other, `${name}: ${message}!
11343
+ `);
11344
+ return;
11345
+ }
11346
+ const n = Math.floor(Math.random() * 3);
11347
+ if (n === 0)
11348
+ self.monsterinfo.current_move = actor_move_pain1;
11349
+ else if (n === 1)
11350
+ self.monsterinfo.current_move = actor_move_pain2;
11351
+ else
11352
+ self.monsterinfo.current_move = actor_move_pain3;
10911
11353
  }
10912
- function makron_save_loc(self) {
10913
- if (!self.enemy) return;
10914
- self.pos1 = { ...self.enemy.origin };
10915
- self.pos1 = { ...self.pos1, z: self.pos1.z + (self.enemy.viewheight || 0) };
11354
+ function actor_setskin(self, context) {
11355
+ if (self.health < self.max_health / 2)
11356
+ self.skin = 1;
11357
+ else
11358
+ self.skin = 0;
10916
11359
  }
10917
- function makron_fire_hyperblaster(self, context) {
10918
- context.engine.sound?.(self, 0, "makron/blaster.wav", 1, 1, 0);
10919
- const start = getProjectedOffset3(self, MAKRON_BLASTER_OFFSET_1);
10920
- const relFrame = (self.monsterinfo.nextframe || 0) - attack_hyperblaster_move.firstframe;
10921
- let yawDelta = 0;
11360
+ function actorMachineGun(self, context) {
11361
+ const flashOffset = { x: 0, y: 0, z: 0 };
11362
+ const vectors = angleVectors(self.angles);
11363
+ const forward = vectors.forward;
11364
+ const start = copyVec3(self.origin);
11365
+ start.z += self.viewheight;
10922
11366
  let dir;
10923
11367
  if (self.enemy) {
10924
- const target = { ...self.enemy.origin };
10925
- target.z += self.enemy.viewheight || 0;
10926
- const vec = subtractVec3(target, start);
10927
- const baseAngles = vectorToAngles(vec);
10928
- const enemyAngles = { ...baseAngles };
10929
- if (relFrame <= 12) {
10930
- enemyAngles.y -= 5 * (relFrame - 4);
11368
+ let target;
11369
+ if (self.enemy.health > 0) {
11370
+ target = subtractVec3(self.enemy.origin, scaleVec3(self.enemy.velocity, 0.2));
11371
+ target.z += self.enemy.viewheight;
10931
11372
  } else {
10932
- enemyAngles.y -= 40 - 5 * (relFrame - 12);
11373
+ target = copyVec3(self.enemy.absmin);
11374
+ target.z += self.enemy.size.z / 2 + 1;
10933
11375
  }
10934
- const forward = angleVectors(enemyAngles).forward;
10935
- dir = forward;
11376
+ dir = subtractVec3(target, start);
11377
+ dir = normalizeVec3(dir);
10936
11378
  } else {
10937
- const { forward } = angleVectors(self.angles);
10938
11379
  dir = forward;
10939
11380
  }
10940
- monster_fire_blaster(self, start, dir, 15, 1e3, 0, 0, context, 1 /* BLASTER */);
11381
+ monster_fire_bullet(self, start, dir, 3, 4, 0, 0, MZ2_ACTOR_MACHINEGUN_1, context);
10941
11382
  }
10942
- function makron_pain(self, other, kick, damage, context) {
10943
- if (self.health < self.max_health / 2) {
10944
- self.skin = 1;
10945
- }
10946
- if (self.timestamp < (self.pain_finished_time || 0)) return;
10947
- if (damage <= 25 && Math.random() < 0.2) return;
10948
- self.pain_finished_time = self.timestamp + 3;
10949
- if (damage <= 40) {
10950
- context.engine.sound?.(self, 0, "makron/pain1.wav", 1, 1, 0);
10951
- self.monsterinfo.current_move = pain4_move;
10952
- } else if (damage <= 110) {
10953
- context.engine.sound?.(self, 0, "makron/pain2.wav", 1, 1, 0);
10954
- self.monsterinfo.current_move = pain5_move;
10955
- } else {
10956
- if (Math.random() <= 0.45) {
10957
- context.engine.sound?.(self, 0, "makron/pain3.wav", 1, 1, 0);
10958
- self.monsterinfo.current_move = pain6_move;
10959
- }
10960
- }
11383
+ function actor_dead(self, context) {
11384
+ self.mins = { x: -16, y: -16, z: -24 };
11385
+ self.maxs = { x: 16, y: 16, z: -8 };
11386
+ self.movetype = 7 /* Toss */;
11387
+ self.svflags |= 1;
11388
+ self.nextthink = -1;
11389
+ context.linkentity(self);
10961
11390
  }
10962
- function makron_die(self, context) {
10963
- context.engine.sound?.(self, 0, "makron/death.wav", 1, 1, 0);
10964
- self.monsterinfo.current_move = death_move11;
11391
+ function actor_die(self, inflictor, attacker, damage, point, mod) {
11392
+ const context = self.monsterinfo.context;
11393
+ if (!context) return;
11394
+ if (self.health <= -80) {
11395
+ throwGibs(context, self.origin, damage);
11396
+ self.deadflag = 2 /* Dead */;
11397
+ return;
11398
+ }
11399
+ if (self.deadflag === 2 /* Dead */)
11400
+ return;
11401
+ self.deadflag = 2 /* Dead */;
11402
+ self.takedamage = true;
11403
+ if (Math.random() < 0.5)
11404
+ self.monsterinfo.current_move = actor_move_death1;
11405
+ else
11406
+ self.monsterinfo.current_move = actor_move_death2;
11407
+ }
11408
+ function actor_fire(self, context) {
11409
+ actorMachineGun(self, context);
11410
+ const fire_wait = self.monsterinfo.fire_wait ?? 0;
11411
+ if (context.timeSeconds >= fire_wait)
11412
+ self.monsterinfo.aiflags &= ~128 /* HoldFrame */;
11413
+ else
11414
+ self.monsterinfo.aiflags |= 128 /* HoldFrame */;
10965
11415
  }
10966
- function makron_dead(self) {
10967
- self.monsterinfo.nextframe = death_move11.lastframe;
10968
- self.nextthink = -1;
11416
+ function actor_attack(self, context) {
11417
+ self.monsterinfo.current_move = actor_move_attack;
11418
+ self.monsterinfo.fire_wait = context.timeSeconds + 1 + Math.random() * 1.6;
10969
11419
  }
10970
- var stand_frames13 = Array.from({ length: 60 }, () => ({ ai: monster_ai_stand14, dist: 0 }));
10971
- stand_move13 = { firstframe: 0, lastframe: 59, frames: stand_frames13, endfunc: makron_stand };
10972
- var walk_frames12 = Array.from({ length: 10 }, () => ({ ai: monster_ai_walk14, dist: 8 }));
10973
- walk_move12 = { firstframe: 60, lastframe: 69, frames: walk_frames12, endfunc: makron_walk };
10974
- var run_frames11 = Array.from({ length: 10 }, () => ({ ai: monster_ai_run13, dist: 8 }));
10975
- run_move12 = { firstframe: 60, lastframe: 69, frames: run_frames11, endfunc: makron_run };
10976
- var attack_bfg_frames = Array.from({ length: 8 }, (_, i) => ({
10977
- ai: monster_ai_charge14,
10978
- dist: 0,
10979
- think: i === 3 ? makron_fire_bfg : null
10980
- }));
10981
- attack_bfg_move = { firstframe: 70, lastframe: 77, frames: attack_bfg_frames, endfunc: makron_run };
10982
- var attack_hyperblaster_frames = Array.from({ length: 26 }, (_, i) => ({
10983
- ai: monster_ai_move14,
10984
- dist: 0,
10985
- think: i >= 4 && i <= 20 ? makron_fire_hyperblaster : null
10986
- }));
10987
- attack_hyperblaster_move = { firstframe: 78, lastframe: 103, frames: attack_hyperblaster_frames, endfunc: makron_run };
10988
- var attack_railgun_frames = Array.from({ length: 16 }, (_, i) => ({
10989
- ai: monster_ai_charge14,
10990
- dist: 0,
10991
- think: i === 7 ? makron_save_loc : i === 8 ? makron_fire_railgun : null
10992
- }));
10993
- attack_railgun_move = { firstframe: 104, lastframe: 119, frames: attack_railgun_frames, endfunc: makron_run };
10994
- var pain4_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10995
- pain4_move = { firstframe: 120, lastframe: 123, frames: pain4_frames, endfunc: makron_run };
10996
- var pain5_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10997
- pain5_move = { firstframe: 124, lastframe: 127, frames: pain5_frames, endfunc: makron_run };
10998
- var pain6_frames = Array.from({ length: 27 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10999
- pain6_move = { firstframe: 128, lastframe: 154, frames: pain6_frames, endfunc: makron_run };
11000
- var death_frames11 = Array.from({ length: 95 }, () => ({ ai: monster_ai_move14, dist: 0 }));
11001
- death_move11 = { firstframe: 155, lastframe: 249, frames: death_frames11, endfunc: makron_dead };
11002
- var sight_frames = Array.from({ length: 13 }, () => ({ ai: monster_ai_move14, dist: 0 }));
11003
- sight_move = { firstframe: 250, lastframe: 262, frames: sight_frames, endfunc: makron_run };
11004
- function SP_monster_makron(self, context) {
11005
- self.classname = "monster_makron";
11006
- self.model = "models/monsters/boss3/rider/tris.md2";
11007
- self.mins = { x: -30, y: -30, z: 0 };
11008
- self.maxs = { x: 30, y: 30, z: 90 };
11420
+ function actor_use(self, other, activator) {
11421
+ const context = self.monsterinfo.context;
11422
+ const target = context.pickTarget(self.target);
11423
+ self.goalentity = target;
11424
+ self.movetarget = target;
11425
+ if (!self.movetarget || self.movetarget.classname !== "target_actor") {
11426
+ console.log(`${self.classname}: bad target ${self.target}`);
11427
+ self.target = void 0;
11428
+ self.monsterinfo.pausetime = 1e8;
11429
+ if (self.monsterinfo.stand) self.monsterinfo.stand(self, context);
11430
+ return;
11431
+ }
11432
+ const goalPos = self.goalentity ? self.goalentity.origin : self.movetarget ? self.movetarget.origin : self.origin;
11433
+ const v = subtractVec3(goalPos, self.origin);
11434
+ self.ideal_yaw = vectorToYaw(v);
11435
+ self.angles.y = self.ideal_yaw;
11436
+ if (self.monsterinfo.walk) self.monsterinfo.walk(self, context);
11437
+ self.target = void 0;
11438
+ }
11439
+ function actor_stand_wrapper(self, context) {
11440
+ actor_stand(self, context);
11441
+ }
11442
+ var frames_stand = [
11443
+ m2(ai_stand),
11444
+ m2(ai_stand),
11445
+ m2(ai_stand),
11446
+ m2(ai_stand),
11447
+ m2(ai_stand),
11448
+ m2(ai_stand),
11449
+ m2(ai_stand),
11450
+ m2(ai_stand),
11451
+ m2(ai_stand),
11452
+ m2(ai_stand),
11453
+ m2(ai_stand),
11454
+ m2(ai_stand),
11455
+ m2(ai_stand),
11456
+ m2(ai_stand),
11457
+ m2(ai_stand),
11458
+ m2(ai_stand),
11459
+ m2(ai_stand),
11460
+ m2(ai_stand),
11461
+ m2(ai_stand),
11462
+ m2(ai_stand),
11463
+ m2(ai_stand),
11464
+ m2(ai_stand),
11465
+ m2(ai_stand),
11466
+ m2(ai_stand),
11467
+ m2(ai_stand),
11468
+ m2(ai_stand),
11469
+ m2(ai_stand),
11470
+ m2(ai_stand),
11471
+ m2(ai_stand),
11472
+ m2(ai_stand),
11473
+ m2(ai_stand),
11474
+ m2(ai_stand),
11475
+ m2(ai_stand),
11476
+ m2(ai_stand),
11477
+ m2(ai_stand),
11478
+ m2(ai_stand),
11479
+ m2(ai_stand),
11480
+ m2(ai_stand),
11481
+ m2(ai_stand),
11482
+ m2(ai_stand)
11483
+ ];
11484
+ actor_move_stand = {
11485
+ firstframe: FRAME_stand101,
11486
+ lastframe: FRAME_stand140,
11487
+ frames: frames_stand,
11488
+ endfunc: null
11489
+ };
11490
+ var frames_walk = [
11491
+ m2(ai_walk),
11492
+ m2(ai_walk, 6),
11493
+ m2(ai_walk, 10),
11494
+ m2(ai_walk, 3),
11495
+ m2(ai_walk, 2),
11496
+ m2(ai_walk, 7),
11497
+ m2(ai_walk, 10),
11498
+ m2(ai_walk, 1)
11499
+ ];
11500
+ actor_move_walk = {
11501
+ firstframe: FRAME_walk01,
11502
+ lastframe: FRAME_walk08,
11503
+ frames: frames_walk,
11504
+ endfunc: null
11505
+ };
11506
+ var frames_run = [
11507
+ m2(ai_run, 4),
11508
+ m2(ai_run, 15),
11509
+ m2(ai_run, 15),
11510
+ m2(ai_run, 8),
11511
+ m2(ai_run, 20),
11512
+ m2(ai_run, 15)
11513
+ ];
11514
+ actor_move_run = {
11515
+ firstframe: FRAME_run02,
11516
+ lastframe: FRAME_run07,
11517
+ frames: frames_run,
11518
+ endfunc: null
11519
+ };
11520
+ var frames_pain1 = [
11521
+ m2(ai_move, -5),
11522
+ m2(ai_move, 4),
11523
+ m2(ai_move, 1)
11524
+ ];
11525
+ actor_move_pain1 = {
11526
+ firstframe: FRAME_pain101,
11527
+ lastframe: FRAME_pain103,
11528
+ frames: frames_pain1,
11529
+ endfunc: actor_run
11530
+ };
11531
+ var frames_pain2 = [
11532
+ m2(ai_move, -4),
11533
+ m2(ai_move, 4),
11534
+ m2(ai_move)
11535
+ ];
11536
+ actor_move_pain2 = {
11537
+ firstframe: FRAME_pain201,
11538
+ lastframe: FRAME_pain203,
11539
+ frames: frames_pain2,
11540
+ endfunc: actor_run
11541
+ };
11542
+ var frames_pain3 = [
11543
+ m2(ai_move, -1),
11544
+ m2(ai_move, 1),
11545
+ m2(ai_move, 0)
11546
+ ];
11547
+ actor_move_pain3 = {
11548
+ firstframe: FRAME_pain301,
11549
+ lastframe: FRAME_pain303,
11550
+ frames: frames_pain3,
11551
+ endfunc: actor_run
11552
+ };
11553
+ var frames_flipoff = [
11554
+ m2(ai_turn),
11555
+ m2(ai_turn),
11556
+ m2(ai_turn),
11557
+ m2(ai_turn),
11558
+ m2(ai_turn),
11559
+ m2(ai_turn),
11560
+ m2(ai_turn),
11561
+ m2(ai_turn),
11562
+ m2(ai_turn),
11563
+ m2(ai_turn),
11564
+ m2(ai_turn),
11565
+ m2(ai_turn),
11566
+ m2(ai_turn),
11567
+ m2(ai_turn)
11568
+ ];
11569
+ actor_move_flipoff = {
11570
+ firstframe: FRAME_flip01,
11571
+ lastframe: FRAME_flip14,
11572
+ frames: frames_flipoff,
11573
+ endfunc: actor_run
11574
+ };
11575
+ var frames_taunt = [
11576
+ m2(ai_turn),
11577
+ m2(ai_turn),
11578
+ m2(ai_turn),
11579
+ m2(ai_turn),
11580
+ m2(ai_turn),
11581
+ m2(ai_turn),
11582
+ m2(ai_turn),
11583
+ m2(ai_turn),
11584
+ m2(ai_turn),
11585
+ m2(ai_turn),
11586
+ m2(ai_turn),
11587
+ m2(ai_turn),
11588
+ m2(ai_turn),
11589
+ m2(ai_turn),
11590
+ m2(ai_turn),
11591
+ m2(ai_turn),
11592
+ m2(ai_turn)
11593
+ ];
11594
+ actor_move_taunt = {
11595
+ firstframe: FRAME_taunt01,
11596
+ lastframe: FRAME_taunt17,
11597
+ frames: frames_taunt,
11598
+ endfunc: actor_run
11599
+ };
11600
+ var frames_death1 = [
11601
+ m2(ai_move),
11602
+ m2(ai_move),
11603
+ m2(ai_move, -13),
11604
+ m2(ai_move, 14),
11605
+ m2(ai_move, 3),
11606
+ m2(ai_move, -2),
11607
+ m2(ai_move, 1)
11608
+ ];
11609
+ actor_move_death1 = {
11610
+ firstframe: FRAME_death101,
11611
+ lastframe: FRAME_death107,
11612
+ frames: frames_death1,
11613
+ endfunc: actor_dead
11614
+ };
11615
+ var frames_death2 = [
11616
+ m2(ai_move),
11617
+ m2(ai_move, 7),
11618
+ m2(ai_move, -6),
11619
+ m2(ai_move, -5),
11620
+ m2(ai_move, 1),
11621
+ m2(ai_move),
11622
+ m2(ai_move, -1),
11623
+ m2(ai_move, -2),
11624
+ m2(ai_move, -1),
11625
+ m2(ai_move, -9),
11626
+ m2(ai_move, -13),
11627
+ m2(ai_move, -13),
11628
+ m2(ai_move)
11629
+ ];
11630
+ actor_move_death2 = {
11631
+ firstframe: FRAME_death201,
11632
+ lastframe: FRAME_death213,
11633
+ frames: frames_death2,
11634
+ endfunc: actor_dead
11635
+ };
11636
+ var frames_attack = [
11637
+ m2(ai_charge, -2, actor_fire),
11638
+ m2(ai_charge, -2),
11639
+ m2(ai_charge, 3),
11640
+ m2(ai_charge, 2)
11641
+ ];
11642
+ actor_move_attack = {
11643
+ firstframe: FRAME_attak01,
11644
+ lastframe: FRAME_attak04,
11645
+ frames: frames_attack,
11646
+ endfunc: actor_run
11647
+ };
11648
+ function SP_misc_actor(self, context) {
11649
+ if (!self.targetname) {
11650
+ console.log(`${self.classname}: no targetname`);
11651
+ context.entities.free(self);
11652
+ return;
11653
+ }
11654
+ if (!self.target) {
11655
+ console.log(`${self.classname}: no target`);
11656
+ context.entities.free(self);
11657
+ return;
11658
+ }
11659
+ self.movetarget = null;
11009
11660
  self.movetype = 5 /* Step */;
11010
11661
  self.solid = 2 /* BoundingBox */;
11011
- self.health = 3e3;
11012
- self.max_health = 3e3;
11013
- self.mass = 500;
11014
- self.takedamage = true;
11015
- self.viewheight = 90;
11016
- self.pain = (ent, other, kick, dmg) => makron_pain(ent, other, kick, dmg, context.entities);
11017
- self.die = (self2, inflictor, attacker, damage, point) => {
11018
- if (self2.health <= -2e3) {
11019
- throwGibs(context.entities, self2.origin, damage);
11020
- context.entities.free(self2);
11021
- return;
11022
- }
11023
- self2.deadflag = 2 /* Dead */;
11024
- self2.solid = 0 /* Not */;
11025
- makron_die(self2, context.entities);
11662
+ self.model = "players/male/tris.md2";
11663
+ self.mins = { x: -16, y: -16, z: -24 };
11664
+ self.maxs = { x: 16, y: 16, z: 32 };
11665
+ if (!self.health)
11666
+ self.health = 100;
11667
+ self.max_health = self.health;
11668
+ self.mass = 200;
11669
+ self.pain = actor_pain;
11670
+ self.die = actor_die;
11671
+ self.monsterinfo = {
11672
+ ...self.monsterinfo,
11673
+ // Preserve default properties like last_sighting, trail_time, pausetime
11674
+ stand: (s) => actor_stand_wrapper(s, context.entities),
11675
+ // Wrap to match signature
11676
+ walk: actor_walk,
11677
+ run: actor_run,
11678
+ attack: actor_attack,
11679
+ melee: void 0,
11680
+ sight: void 0,
11681
+ setskin: (s) => actor_setskin(s, context.entities),
11682
+ // Wrap to match signature
11683
+ aiflags: 256 /* GoodGuy */,
11684
+ scale: 1
11685
+ // MODEL_SCALE
11026
11686
  };
11027
- self.monsterinfo.stand = makron_stand;
11028
- self.monsterinfo.walk = makron_walk;
11029
- self.monsterinfo.run = makron_run;
11030
- self.monsterinfo.attack = makron_attack;
11031
- self.monsterinfo.sight = (self2, other) => {
11032
- context.entities.sound?.(self2, 0, "makron/sight.wav", 1, 1, 0);
11033
- self2.monsterinfo.current_move = sight_move;
11687
+ self.monsterinfo.context = context.entities;
11688
+ context.entities.linkentity(self);
11689
+ self.monsterinfo.current_move = actor_move_stand;
11690
+ self.think = (s) => {
11691
+ const c = s.monsterinfo.context;
11692
+ if (c) monster_think(s, c);
11034
11693
  };
11035
- self.think = monster_think;
11036
- self.monsterinfo.current_move = sight_move;
11037
- self.nextthink = self.timestamp + MONSTER_TICK15;
11694
+ self.nextthink = context.entities.timeSeconds + MONSTER_TICK16;
11695
+ self.use = (self2, other, activator = null) => actor_use(self2, other, activator);
11696
+ }
11697
+ var SPAWNFLAG_TARGET_ACTOR_JUMP = 1;
11698
+ var SPAWNFLAG_TARGET_ACTOR_SHOOT = 2;
11699
+ var SPAWNFLAG_TARGET_ACTOR_ATTACK = 4;
11700
+ var SPAWNFLAG_TARGET_ACTOR_HOLD = 16;
11701
+ var SPAWNFLAG_TARGET_ACTOR_BRUTAL = 32;
11702
+ function target_actor_touch(self, other, plane, surf) {
11703
+ if (!other) return;
11704
+ const context = self.monsterinfo.context;
11705
+ if (other.movetarget !== self)
11706
+ return;
11707
+ if (other.enemy)
11708
+ return;
11709
+ other.goalentity = null;
11710
+ other.movetarget = null;
11711
+ if (self.message) {
11712
+ const name = actor_names[Math.floor(Math.random() * actor_names.length)];
11713
+ }
11714
+ if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_JUMP) {
11715
+ const v = other.velocity;
11716
+ v.x = self.movedir.x * self.speed;
11717
+ v.y = self.movedir.y * self.speed;
11718
+ if (other.groundentity) {
11719
+ other.groundentity = null;
11720
+ v.z = self.movedir.z;
11721
+ context.sound(other, 2, "player/male/jump1.wav", 1, 1, 0);
11722
+ }
11723
+ }
11724
+ if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_SHOOT) {
11725
+ } else if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_ATTACK) {
11726
+ other.enemy = context.pickTarget(self.pathtarget);
11727
+ if (other.enemy) {
11728
+ other.goalentity = other.enemy;
11729
+ if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_BRUTAL)
11730
+ other.monsterinfo.aiflags |= 512 /* Brutal */;
11731
+ if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_HOLD) {
11732
+ other.monsterinfo.aiflags |= 1 /* StandGround */;
11733
+ actor_stand(other, context);
11734
+ } else {
11735
+ actor_run(other, context);
11736
+ }
11737
+ }
11738
+ }
11739
+ if (!(self.spawnflags & (SPAWNFLAG_TARGET_ACTOR_ATTACK | SPAWNFLAG_TARGET_ACTOR_SHOOT)) && self.pathtarget) {
11740
+ const savetarget = self.target;
11741
+ self.target = self.pathtarget;
11742
+ context.useTargets(self, other);
11743
+ self.target = savetarget;
11744
+ }
11745
+ other.movetarget = context.pickTarget(self.target);
11746
+ if (!other.goalentity)
11747
+ other.goalentity = other.movetarget;
11748
+ if (!other.movetarget && !other.enemy) {
11749
+ other.monsterinfo.pausetime = 1e8;
11750
+ if (other.monsterinfo.stand) other.monsterinfo.stand(other, context);
11751
+ } else if (other.movetarget === other.goalentity && other.movetarget) {
11752
+ const v = subtractVec3(other.movetarget.origin, other.origin);
11753
+ other.ideal_yaw = vectorToYaw(v);
11754
+ }
11038
11755
  }
11039
- function registerMakronSpawns(registry) {
11040
- registry.register("monster_makron", SP_monster_makron);
11756
+ function SP_target_actor(self, context) {
11757
+ if (!self.targetname)
11758
+ console.log(`${self.classname}: no targetname`);
11759
+ self.solid = 1 /* Trigger */;
11760
+ self.touch = target_actor_touch;
11761
+ self.mins = { x: -8, y: -8, z: -8 };
11762
+ self.maxs = { x: 8, y: 8, z: 8 };
11763
+ self.svflags = 1 << 6;
11764
+ self.monsterinfo = {
11765
+ ...self.monsterinfo
11766
+ };
11767
+ self.monsterinfo.context = context.entities;
11768
+ if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_JUMP) {
11769
+ if (!self.speed)
11770
+ self.speed = 200;
11771
+ const height = self.height || 200;
11772
+ if (self.angles.y === 0)
11773
+ self.angles.y = 360;
11774
+ const dir = setMovedir(self.angles);
11775
+ dir.z = height;
11776
+ self.movedir = dir;
11777
+ }
11778
+ context.entities.linkentity(self);
11779
+ }
11780
+ function registerActorSpawns(registry) {
11781
+ registry.register("misc_actor", SP_misc_actor);
11782
+ registry.register("target_actor", SP_target_actor);
11041
11783
  }
11042
11784
 
11043
11785
  // src/entities/monsters/medic.ts
11044
- var MONSTER_TICK16 = 0.1;
11786
+ var MONSTER_TICK17 = 0.1;
11045
11787
  function monster_ai_stand15(self, dist, context) {
11046
11788
  if (self.classname === "monster_medic") {
11047
11789
  if (medic_find_dead(self, context)) {
@@ -11049,24 +11791,24 @@ function monster_ai_stand15(self, dist, context) {
11049
11791
  return;
11050
11792
  }
11051
11793
  }
11052
- ai_stand(self, MONSTER_TICK16, context);
11794
+ ai_stand(self, MONSTER_TICK17, context);
11053
11795
  }
11054
11796
  function monster_ai_walk15(self, dist, context) {
11055
- ai_walk(self, dist, MONSTER_TICK16, context);
11797
+ ai_walk(self, dist, MONSTER_TICK17, context);
11056
11798
  }
11057
11799
  function monster_ai_run14(self, dist, context) {
11058
11800
  if (self.classname === "monster_medic") {
11059
11801
  if (medic_find_dead(self, context)) {
11060
11802
  self.monsterinfo.current_move = run_move13;
11061
11803
  } else {
11062
- ai_run(self, dist, MONSTER_TICK16, context);
11804
+ ai_run(self, dist, MONSTER_TICK17, context);
11063
11805
  }
11064
11806
  } else {
11065
- ai_run(self, dist, MONSTER_TICK16, context);
11807
+ ai_run(self, dist, MONSTER_TICK17, context);
11066
11808
  }
11067
11809
  }
11068
11810
  function monster_ai_charge15(self, dist, context) {
11069
- ai_charge(self, dist, MONSTER_TICK16, context);
11811
+ ai_charge(self, dist, MONSTER_TICK17, context);
11070
11812
  }
11071
11813
  function monster_ai_move15(self, dist, context) {
11072
11814
  ai_move(self, dist);
@@ -11402,7 +12144,7 @@ function SP_monster_medic(self, context) {
11402
12144
  self.monsterinfo.attack = medic_attack;
11403
12145
  self.think = monster_think;
11404
12146
  medic_stand(self);
11405
- self.nextthink = self.timestamp + MONSTER_TICK16;
12147
+ self.nextthink = self.timestamp + MONSTER_TICK17;
11406
12148
  }
11407
12149
  function SP_monster_medic_commander(self, context) {
11408
12150
  SP_monster_medic(self, context);
@@ -11417,25 +12159,25 @@ function registerMedicSpawns(registry) {
11417
12159
  }
11418
12160
 
11419
12161
  // src/entities/monsters/mutant.ts
11420
- var MONSTER_TICK17 = 0.1;
12162
+ var MONSTER_TICK18 = 0.1;
11421
12163
  var random6 = () => Math.random();
11422
12164
  function monster_ai_stand16(self, dist, context) {
11423
- ai_stand(self, MONSTER_TICK17, context);
12165
+ ai_stand(self, MONSTER_TICK18, context);
11424
12166
  }
11425
12167
  function monster_ai_walk16(self, dist, context) {
11426
- ai_walk(self, dist, MONSTER_TICK17, context);
12168
+ ai_walk(self, dist, MONSTER_TICK18, context);
11427
12169
  }
11428
12170
  function monster_ai_run15(self, dist, context) {
11429
- ai_run(self, dist, MONSTER_TICK17, context);
12171
+ ai_run(self, dist, MONSTER_TICK18, context);
11430
12172
  }
11431
12173
  function monster_ai_charge16(self, dist, context) {
11432
- ai_charge(self, dist, MONSTER_TICK17, context);
12174
+ ai_charge(self, dist, MONSTER_TICK18, context);
11433
12175
  }
11434
12176
  function monster_ai_move16(self, dist, context) {
11435
12177
  ai_move(self, dist);
11436
12178
  }
11437
12179
  function monster_ai_face(self, dist, context) {
11438
- ai_face(self, null, dist, MONSTER_TICK17);
12180
+ ai_face(self, null, dist, MONSTER_TICK18);
11439
12181
  }
11440
12182
  var stand_move15;
11441
12183
  var walk_move14;
@@ -11799,26 +12541,26 @@ function SP_monster_mutant(self, context) {
11799
12541
  self.monsterinfo.idle = mutant_stand;
11800
12542
  self.think = monster_think;
11801
12543
  mutant_stand(self);
11802
- self.nextthink = self.timestamp + MONSTER_TICK17;
12544
+ self.nextthink = self.timestamp + MONSTER_TICK18;
11803
12545
  }
11804
12546
  function registerMutantSpawns(registry) {
11805
12547
  registry.register("monster_mutant", SP_monster_mutant);
11806
12548
  }
11807
12549
 
11808
12550
  // src/entities/monsters/parasite.ts
11809
- var MONSTER_TICK18 = 0.1;
12551
+ var MONSTER_TICK19 = 0.1;
11810
12552
  var random7 = () => Math.random();
11811
12553
  function monster_ai_stand17(self, dist, context) {
11812
- ai_stand(self, MONSTER_TICK18, context);
12554
+ ai_stand(self, MONSTER_TICK19, context);
11813
12555
  }
11814
12556
  function monster_ai_walk17(self, dist, context) {
11815
- ai_walk(self, dist, MONSTER_TICK18, context);
12557
+ ai_walk(self, dist, MONSTER_TICK19, context);
11816
12558
  }
11817
12559
  function monster_ai_run16(self, dist, context) {
11818
- ai_run(self, dist, MONSTER_TICK18, context);
12560
+ ai_run(self, dist, MONSTER_TICK19, context);
11819
12561
  }
11820
12562
  function monster_ai_charge17(self, dist, context) {
11821
- ai_charge(self, dist, MONSTER_TICK18, context);
12563
+ ai_charge(self, dist, MONSTER_TICK19, context);
11822
12564
  }
11823
12565
  function monster_ai_move17(self, dist, context) {
11824
12566
  ai_move(self, dist);
@@ -12195,28 +12937,28 @@ function SP_monster_parasite(self, context) {
12195
12937
  self.monsterinfo.idle = parasite_idle;
12196
12938
  self.think = monster_think;
12197
12939
  parasite_stand(self);
12198
- self.nextthink = self.timestamp + MONSTER_TICK18;
12940
+ self.nextthink = self.timestamp + MONSTER_TICK19;
12199
12941
  }
12200
12942
  function registerParasiteSpawns(registry) {
12201
12943
  registry.register("monster_parasite", SP_monster_parasite);
12202
12944
  }
12203
12945
 
12204
12946
  // src/entities/monsters/soldier.ts
12205
- var MONSTER_TICK19 = 0.1;
12947
+ var MONSTER_TICK20 = 0.1;
12206
12948
  var SOLDIER_LIGHT = 1;
12207
12949
  var SOLDIER_SSG = 2;
12208
12950
  var SOLDIER_MACHINEGUN = 4;
12209
12951
  function monster_ai_stand18(self, dist, context) {
12210
- ai_stand(self, MONSTER_TICK19, context);
12952
+ ai_stand(self, MONSTER_TICK20, context);
12211
12953
  }
12212
12954
  function monster_ai_walk18(self, dist, context) {
12213
- ai_walk(self, dist, MONSTER_TICK19, context);
12955
+ ai_walk(self, dist, MONSTER_TICK20, context);
12214
12956
  }
12215
12957
  function monster_ai_run17(self, dist, context) {
12216
- ai_run(self, dist, MONSTER_TICK19, context);
12958
+ ai_run(self, dist, MONSTER_TICK20, context);
12217
12959
  }
12218
12960
  function monster_ai_charge18(self, dist, context) {
12219
- ai_charge(self, dist, MONSTER_TICK19, context);
12961
+ ai_charge(self, dist, MONSTER_TICK20, context);
12220
12962
  }
12221
12963
  function monster_ai_move18(self, dist, context) {
12222
12964
  ai_move(self, dist);
@@ -12500,7 +13242,7 @@ function SP_monster_soldier(self, context) {
12500
13242
  };
12501
13243
  self.think = monster_think;
12502
13244
  soldier_stand(self);
12503
- self.nextthink = self.timestamp + MONSTER_TICK19;
13245
+ self.nextthink = self.timestamp + MONSTER_TICK20;
12504
13246
  }
12505
13247
  function SP_monster_soldier_light(self, context) {
12506
13248
  self.spawnflags |= SOLDIER_LIGHT;
@@ -12540,12 +13282,12 @@ function registerMonsterSpawns(registry) {
12540
13282
  }
12541
13283
 
12542
13284
  // src/entities/monsters/supertank.ts
12543
- var MONSTER_TICK20 = 0.1;
13285
+ var MONSTER_TICK21 = 0.1;
12544
13286
  var SUPERTANK_MACHINEGUN_OFFSET = { x: 30, y: 30, z: 40 };
12545
13287
  var SUPERTANK_ROCKET_OFFSET = { x: 30, y: -30, z: 40 };
12546
13288
  var SUPERTANK_GRENADE_OFFSET = { x: 20, y: 0, z: 70 };
12547
13289
  function monster_ai_stand19(self, dist, context) {
12548
- ai_stand(self, MONSTER_TICK20, context);
13290
+ ai_stand(self, MONSTER_TICK21, context);
12549
13291
  }
12550
13292
  function monster_ai_run18(self, dist, context) {
12551
13293
  if (self.enemy && self.enemy.health > 0) {
@@ -12555,7 +13297,7 @@ function monster_ai_run18(self, dist, context) {
12555
13297
  }
12556
13298
  }
12557
13299
  function monster_ai_charge19(self, dist, context) {
12558
- ai_charge(self, dist, MONSTER_TICK20, context);
13300
+ ai_charge(self, dist, MONSTER_TICK21, context);
12559
13301
  }
12560
13302
  function monster_ai_move19(self, dist, context) {
12561
13303
  ai_move(self, dist);
@@ -12751,7 +13493,7 @@ function SP_monster_supertank(self, context) {
12751
13493
  };
12752
13494
  self.think = monster_think;
12753
13495
  supertank_stand(self);
12754
- self.nextthink = self.timestamp + MONSTER_TICK20;
13496
+ self.nextthink = self.timestamp + MONSTER_TICK21;
12755
13497
  }
12756
13498
  function registerSupertankSpawns(registry) {
12757
13499
  registry.register("monster_supertank", SP_monster_supertank);
@@ -12764,7 +13506,7 @@ function registerSupertankSpawns(registry) {
12764
13506
  }
12765
13507
 
12766
13508
  // src/entities/monsters/tank.ts
12767
- var MONSTER_TICK21 = 0.1;
13509
+ var MONSTER_TICK22 = 0.1;
12768
13510
  function M_AdjustBlindfireTarget(self, start, target, right, context) {
12769
13511
  const tr = context.trace(start, target, ZERO_VEC3, ZERO_VEC3, self, MASK_SHOT);
12770
13512
  if (!tr.startsolid && !tr.allsolid && tr.fraction >= 0.5) {
@@ -12791,10 +13533,10 @@ function tank_blind_check(self, context) {
12791
13533
  }
12792
13534
  }
12793
13535
  function monster_ai_stand20(self, dist, context) {
12794
- ai_stand(self, MONSTER_TICK21, context);
13536
+ ai_stand(self, MONSTER_TICK22, context);
12795
13537
  }
12796
13538
  function monster_ai_walk19(self, dist, context) {
12797
- ai_walk(self, dist, MONSTER_TICK21, context);
13539
+ ai_walk(self, dist, MONSTER_TICK22, context);
12798
13540
  }
12799
13541
  function monster_ai_run19(self, dist, context) {
12800
13542
  if (self.enemy && self.enemy.health > 0) {
@@ -12804,7 +13546,7 @@ function monster_ai_run19(self, dist, context) {
12804
13546
  }
12805
13547
  }
12806
13548
  function monster_ai_charge20(self, dist, context) {
12807
- ai_charge(self, dist, MONSTER_TICK21, context);
13549
+ ai_charge(self, dist, MONSTER_TICK22, context);
12808
13550
  }
12809
13551
  function monster_ai_move20(self, dist, context) {
12810
13552
  ai_move(self, dist);
@@ -13115,7 +13857,7 @@ function SP_monster_tank(self, context) {
13115
13857
  self.monsterinfo.blindfire = true;
13116
13858
  self.think = monster_think;
13117
13859
  tank_stand(self);
13118
- self.nextthink = self.timestamp + MONSTER_TICK21;
13860
+ self.nextthink = self.timestamp + MONSTER_TICK22;
13119
13861
  }
13120
13862
  function registerTankSpawns(registry) {
13121
13863
  registry.register("monster_tank", SP_monster_tank);
@@ -13134,15 +13876,15 @@ function registerTankCommanderSpawns(registry) {
13134
13876
  }
13135
13877
 
13136
13878
  // src/entities/monsters/turret.ts
13137
- var MONSTER_TICK22 = 0.1;
13879
+ var MONSTER_TICK23 = 0.1;
13138
13880
  function monster_ai_stand21(self, dist, context) {
13139
- ai_stand(self, MONSTER_TICK22, context);
13881
+ ai_stand(self, MONSTER_TICK23, context);
13140
13882
  }
13141
13883
  function monster_ai_run20(self, dist, context) {
13142
- ai_run(self, dist, MONSTER_TICK22, context);
13884
+ ai_run(self, dist, MONSTER_TICK23, context);
13143
13885
  }
13144
13886
  function monster_ai_charge21(self, dist, context) {
13145
- ai_charge(self, dist, MONSTER_TICK22, context);
13887
+ ai_charge(self, dist, MONSTER_TICK23, context);
13146
13888
  }
13147
13889
  var stand_move20;
13148
13890
  var run_move19;
@@ -13278,7 +14020,7 @@ function SP_monster_turret(self, context) {
13278
14020
  };
13279
14021
  self.think = monster_think;
13280
14022
  turret_stand(self);
13281
- self.nextthink = self.timestamp + MONSTER_TICK22;
14023
+ self.nextthink = self.timestamp + MONSTER_TICK23;
13282
14024
  }
13283
14025
  function registerTurretSpawns(registry) {
13284
14026
  registry.register("monster_turret", SP_monster_turret);
@@ -13309,6 +14051,7 @@ function registerMonsterSpawns2(registry) {
13309
14051
  registerJorgSpawns(registry);
13310
14052
  registerMakronSpawns(registry);
13311
14053
  registerInsaneSpawns(registry);
14054
+ registerActorSpawns(registry);
13312
14055
  }
13313
14056
 
13314
14057
  // src/entities/worldspawn.ts
@@ -14756,7 +15499,97 @@ function ClientObituary(self, inflictor, attacker, mod, sys) {
14756
15499
  }
14757
15500
  }
14758
15501
 
15502
+ // src/entities/player_anim.ts
15503
+ var FRAME_stand01 = 0;
15504
+ var FRAME_stand402 = 39;
15505
+ var FRAME_run1 = 40;
15506
+ var FRAME_run6 = 45;
15507
+ var FRAME_pain1012 = 54;
15508
+ var FRAME_pain104 = 57;
15509
+ var FRAME_pain2012 = 58;
15510
+ var FRAME_pain204 = 61;
15511
+ var FRAME_pain3012 = 62;
15512
+ var FRAME_pain304 = 65;
15513
+ var FRAME_death1012 = 66;
15514
+ var FRAME_death106 = 71;
15515
+ var FRAME_death2012 = 72;
15516
+ var FRAME_death206 = 77;
15517
+ var FRAME_death301 = 78;
15518
+ var FRAME_death306 = 83;
15519
+ var ANIM_BASIC = 0;
15520
+ var ANIM_PAIN = 2;
15521
+ var ANIM_DEATH = 3;
15522
+
15523
+ // src/combat/weapons/firing.ts
15524
+ var random9 = createRandomGenerator();
15525
+
14759
15526
  // src/entities/player.ts
15527
+ function P_PlayerThink(ent, sys) {
15528
+ if (!ent.client) return;
15529
+ const client = ent.client;
15530
+ let animChanged = false;
15531
+ if (ent.deadflag) {
15532
+ } else {
15533
+ const speed = Math.sqrt(ent.velocity.x * ent.velocity.x + ent.velocity.y * ent.velocity.y);
15534
+ const moving = speed > 10;
15535
+ if (client.anim_priority === ANIM_BASIC || client.anim_priority === void 0) {
15536
+ if (moving) {
15537
+ if (ent.frame < FRAME_run1 || ent.frame > FRAME_run6) {
15538
+ ent.frame = FRAME_run1;
15539
+ client.anim_end = FRAME_run6;
15540
+ client.anim_priority = ANIM_BASIC;
15541
+ animChanged = true;
15542
+ }
15543
+ } else {
15544
+ if (ent.frame >= FRAME_run1 && ent.frame <= FRAME_run6 || client.anim_priority === ANIM_BASIC && client.anim_end !== FRAME_stand402 || client.anim_priority === void 0) {
15545
+ ent.frame = FRAME_stand01;
15546
+ client.anim_end = FRAME_stand402;
15547
+ client.anim_priority = ANIM_BASIC;
15548
+ animChanged = true;
15549
+ }
15550
+ }
15551
+ }
15552
+ }
15553
+ if (animChanged) {
15554
+ return;
15555
+ }
15556
+ if (client.anim_end !== void 0 && client.anim_end !== ent.frame) {
15557
+ if (ent.frame < client.anim_end) {
15558
+ ent.frame++;
15559
+ } else if (ent.frame > client.anim_end) {
15560
+ ent.frame--;
15561
+ }
15562
+ } else if (client.anim_end === ent.frame) {
15563
+ if (client.anim_priority === ANIM_BASIC) {
15564
+ if (ent.frame === FRAME_run6) ent.frame = FRAME_run1;
15565
+ else if (ent.frame === FRAME_stand402) ent.frame = FRAME_stand01;
15566
+ } else {
15567
+ if (client.anim_priority !== ANIM_DEATH) {
15568
+ client.anim_priority = ANIM_BASIC;
15569
+ }
15570
+ }
15571
+ }
15572
+ }
15573
+ function player_pain(self, damage) {
15574
+ if (!self.client) return;
15575
+ if (self.health < 40) {
15576
+ }
15577
+ if (self.client.anim_priority && self.client.anim_priority >= ANIM_PAIN) {
15578
+ return;
15579
+ }
15580
+ self.client.anim_priority = ANIM_PAIN;
15581
+ const r = random9.frandom();
15582
+ if (r < 0.33) {
15583
+ self.frame = FRAME_pain1012;
15584
+ self.client.anim_end = FRAME_pain104;
15585
+ } else if (r < 0.66) {
15586
+ self.frame = FRAME_pain2012;
15587
+ self.client.anim_end = FRAME_pain204;
15588
+ } else {
15589
+ self.frame = FRAME_pain3012;
15590
+ self.client.anim_end = FRAME_pain304;
15591
+ }
15592
+ }
14760
15593
  function player_die(self, inflictor, attacker, damage, point, mod, sys) {
14761
15594
  self.deadflag = 2 /* Dead */;
14762
15595
  self.solid = 0 /* Not */;
@@ -14764,8 +15597,24 @@ function player_die(self, inflictor, attacker, damage, point, mod, sys) {
14764
15597
  self.takedamage = false;
14765
15598
  if (self.health < -40 && sys) {
14766
15599
  throwGibs(sys, self.origin, damage);
15600
+ return;
15601
+ }
15602
+ if (self.client) {
15603
+ self.client.anim_priority = ANIM_DEATH;
15604
+ const r = random9.frandom();
15605
+ if (r < 0.33) {
15606
+ self.frame = FRAME_death1012;
15607
+ self.client.anim_end = FRAME_death106;
15608
+ } else if (r < 0.66) {
15609
+ self.frame = FRAME_death2012;
15610
+ self.client.anim_end = FRAME_death206;
15611
+ } else {
15612
+ self.frame = FRAME_death301;
15613
+ self.client.anim_end = FRAME_death306;
15614
+ }
15615
+ } else {
15616
+ self.frame = 0;
14767
15617
  }
14768
- self.frame = 0;
14769
15618
  if (sys) {
14770
15619
  ClientObituary(self, inflictor, attacker, mod, sys);
14771
15620
  }
@@ -14799,6 +15648,7 @@ function player_think(self, sys) {
14799
15648
  weaponItem.think(self, sys);
14800
15649
  }
14801
15650
  }
15651
+ P_PlayerThink(self, sys);
14802
15652
  self.nextthink = sys.timeSeconds + 0.1;
14803
15653
  sys.scheduleThink(self, self.nextthink);
14804
15654
  }
@@ -15145,7 +15995,7 @@ var WEAPONS = {
15145
15995
  };
15146
15996
 
15147
15997
  // src/index.ts
15148
- var ZERO_VEC37 = { x: 0, y: 0, z: 0 };
15998
+ var ZERO_VEC36 = { x: 0, y: 0, z: 0 };
15149
15999
  function createGame(imports, engine, options) {
15150
16000
  const gravity = options.gravity;
15151
16001
  const deathmatch = options.deathmatch ?? false;
@@ -15214,8 +16064,8 @@ function createGame(imports, engine, options) {
15214
16064
  };
15215
16065
  entities.runFrame();
15216
16066
  });
15217
- let origin = { ...ZERO_VEC37 };
15218
- let velocity = { ...ZERO_VEC37 };
16067
+ let origin = { ...ZERO_VEC36 };
16068
+ let velocity = { ...ZERO_VEC36 };
15219
16069
  const calculateBlend = (player, time) => {
15220
16070
  const blend = [0, 0, 0, 0];
15221
16071
  if (!player || !player.client) return blend;
@@ -15297,10 +16147,10 @@ function createGame(imports, engine, options) {
15297
16147
  // TODO
15298
16148
  damageIndicators: [],
15299
16149
  stats: player ? populatePlayerStats(player, levelClock.current.timeSeconds) : [],
15300
- kick_angles: player?.client?.kick_angles ?? ZERO_VEC37,
15301
- kick_origin: player?.client?.kick_origin ?? ZERO_VEC37,
15302
- gunoffset: ZERO_VEC37,
15303
- gunangles: ZERO_VEC37,
16150
+ kick_angles: player?.client?.kick_angles ?? ZERO_VEC36,
16151
+ kick_origin: player?.client?.kick_origin ?? ZERO_VEC36,
16152
+ gunoffset: ZERO_VEC36,
16153
+ gunangles: ZERO_VEC36,
15304
16154
  gunindex: 0,
15305
16155
  gun_frame: player?.client?.gun_frame ?? 0,
15306
16156
  rdflags: player?.client?.rdflags ?? 0,
@@ -15314,8 +16164,8 @@ function createGame(imports, engine, options) {
15314
16164
  const resetState = (startTimeMs) => {
15315
16165
  frameLoop.reset(startTimeMs);
15316
16166
  levelClock.start(startTimeMs);
15317
- origin = { ...ZERO_VEC37 };
15318
- velocity = { ...ZERO_VEC37 };
16167
+ origin = { ...ZERO_VEC36 };
16168
+ velocity = { ...ZERO_VEC36 };
15319
16169
  entities.beginFrame(startTimeMs / 1e3);
15320
16170
  entities.runFrame();
15321
16171
  };
@@ -15343,10 +16193,10 @@ function createGame(imports, engine, options) {
15343
16193
  blend: [0, 0, 0, 0],
15344
16194
  // Stubs
15345
16195
  stats: populatePlayerStats(player, levelClock.current.timeSeconds),
15346
- kick_angles: ZERO_VEC37,
15347
- kick_origin: ZERO_VEC37,
15348
- gunoffset: ZERO_VEC37,
15349
- gunangles: ZERO_VEC37,
16196
+ kick_angles: ZERO_VEC36,
16197
+ kick_origin: ZERO_VEC36,
16198
+ gunoffset: ZERO_VEC36,
16199
+ gunangles: ZERO_VEC36,
15350
16200
  gunindex: 0,
15351
16201
  pm_type: 0,
15352
16202
  pm_time: 0,
@@ -15404,6 +16254,9 @@ function createGame(imports, engine, options) {
15404
16254
  player.die = (self, inflictor, attacker, damage, point, mod) => {
15405
16255
  player_die(self, inflictor, attacker, damage, point, mod, entities);
15406
16256
  };
16257
+ player.pain = (self, other, kick, damage) => {
16258
+ player_pain(self, damage);
16259
+ };
15407
16260
  player.think = (self) => {
15408
16261
  player_think(self, entities);
15409
16262
  };
@@ -15473,8 +16326,8 @@ function createGame(imports, engine, options) {
15473
16326
  rng,
15474
16327
  player: player?.client?.inventory
15475
16328
  });
15476
- origin = player ? { ...player.origin } : { ...ZERO_VEC37 };
15477
- velocity = player ? { ...player.velocity } : { ...ZERO_VEC37 };
16329
+ origin = player ? { ...player.origin } : { ...ZERO_VEC36 };
16330
+ velocity = player ? { ...player.velocity } : { ...ZERO_VEC36 };
15478
16331
  frameLoop.reset(save.level.timeSeconds * 1e3);
15479
16332
  }
15480
16333
  };