quake2ts 0.0.262 → 0.0.266

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 (51) 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 +25 -12
  5. package/packages/client/dist/cjs/index.cjs.map +1 -1
  6. package/packages/client/dist/esm/index.js +25 -12
  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 +998 -291
  23. package/packages/game/dist/cjs/index.cjs.map +1 -1
  24. package/packages/game/dist/esm/index.js +999 -292
  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/index.d.ts.map +1 -1
  44. package/packages/shared/dist/browser/index.global.js +1 -1
  45. package/packages/shared/dist/browser/index.global.js.map +1 -1
  46. package/packages/shared/dist/cjs/index.cjs +12 -5
  47. package/packages/shared/dist/cjs/index.cjs.map +1 -1
  48. package/packages/shared/dist/esm/index.js +12 -5
  49. package/packages/shared/dist/esm/index.js.map +1 -1
  50. package/packages/shared/dist/tsconfig.tsbuildinfo +1 -1
  51. package/packages/shared/dist/types/pmove/apply.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,
@@ -1009,7 +1009,14 @@ var applyPmove = (state, cmd, trace, pointContents2) => {
1009
1009
  let newState = { ...state };
1010
1010
  newState = categorizePosition2(newState, trace);
1011
1011
  newState = checkWater(newState, pointContents2);
1012
- const { origin, velocity, onGround, waterLevel } = newState;
1012
+ const { origin, velocity, onGround, waterLevel, viewAngles } = newState;
1013
+ const adjustedAngles = waterLevel >= 2 ? viewAngles : {
1014
+ // For ground/air movement, reduce pitch influence (rerelease/p_move.cpp:1689)
1015
+ x: viewAngles.x > 180 ? (viewAngles.x - 360) / 3 : viewAngles.x / 3,
1016
+ y: viewAngles.y,
1017
+ z: viewAngles.z
1018
+ };
1019
+ const { forward, right } = angleVectors(adjustedAngles);
1013
1020
  const frictionedVelocity = applyPmoveFriction({
1014
1021
  velocity,
1015
1022
  frametime: FRAMETIME,
@@ -1022,13 +1029,13 @@ var applyPmove = (state, cmd, trace, pointContents2) => {
1022
1029
  pmWaterFriction: 1
1023
1030
  });
1024
1031
  const wish = waterLevel >= 2 ? buildWaterWish({
1025
- forward: { x: 1, y: 0, z: 0 },
1026
- right: { x: 0, y: 1, z: 0 },
1032
+ forward,
1033
+ right,
1027
1034
  cmd,
1028
1035
  maxSpeed: 320
1029
1036
  }) : buildAirGroundWish({
1030
- forward: { x: 1, y: 0, z: 0 },
1031
- right: { x: 0, y: 1, z: 0 },
1037
+ forward,
1038
+ right,
1032
1039
  cmd,
1033
1040
  maxSpeed: 320
1034
1041
  });
@@ -9928,11 +9935,11 @@ function registerInfantrySpawns(registry) {
9928
9935
  registry.register("monster_infantry", SP_monster_infantry);
9929
9936
  }
9930
9937
 
9931
- // src/entities/monsters/jorg.ts
9938
+ // src/entities/monsters/makron.ts
9932
9939
  var MONSTER_TICK13 = 0.1;
9933
- var JORG_MACHINEGUN_R1_OFFSET = { x: 40, y: -20, z: 20 };
9934
- var JORG_MACHINEGUN_L1_OFFSET = { x: 40, y: 20, z: 20 };
9935
- var JORG_BFG_OFFSET = { x: 30, y: 0, z: 40 };
9940
+ var MAKRON_BFG_OFFSET = { x: 30, y: 28, z: 24 };
9941
+ var MAKRON_BLASTER_OFFSET_1 = { x: 26, y: 16, z: 24 };
9942
+ var MAKRON_RAILGUN_OFFSET = { x: 26, y: -14, z: 24 };
9936
9943
  function monster_ai_stand13(self, dist, context) {
9937
9944
  ai_stand(self, MONSTER_TICK13, context);
9938
9945
  }
@@ -9951,24 +9958,269 @@ function monster_ai_move13(self, dist, context) {
9951
9958
  var stand_move12;
9952
9959
  var walk_move11;
9953
9960
  var run_move11;
9961
+ var attack_bfg_move;
9962
+ var attack_hyperblaster_move;
9963
+ var attack_railgun_move;
9964
+ var pain4_move;
9965
+ var pain5_move;
9966
+ var pain6_move;
9967
+ var death_move10;
9968
+ var sight_move;
9969
+ function makron_stand(self) {
9970
+ self.monsterinfo.current_move = stand_move12;
9971
+ }
9972
+ function makron_walk(self) {
9973
+ self.monsterinfo.current_move = walk_move11;
9974
+ }
9975
+ function makron_run(self) {
9976
+ if (self.enemy && self.enemy.health > 0) {
9977
+ self.monsterinfo.current_move = run_move11;
9978
+ } else {
9979
+ self.monsterinfo.current_move = stand_move12;
9980
+ }
9981
+ }
9982
+ function makron_attack(self) {
9983
+ if (!self.enemy) return;
9984
+ const r = Math.random();
9985
+ if (r <= 0.3) {
9986
+ self.monsterinfo.current_move = attack_bfg_move;
9987
+ } else if (r <= 0.6) {
9988
+ self.monsterinfo.current_move = attack_hyperblaster_move;
9989
+ } else {
9990
+ self.monsterinfo.current_move = attack_railgun_move;
9991
+ }
9992
+ }
9993
+ function getProjectedOffset2(self, offset) {
9994
+ const { forward, right, up } = angleVectors(self.angles);
9995
+ const start = { ...self.origin };
9996
+ const x = scaleVec3(forward, offset.x);
9997
+ const y = scaleVec3(right, offset.y);
9998
+ const z = scaleVec3(up, offset.z);
9999
+ return addVec3(addVec3(addVec3(start, x), y), z);
10000
+ }
10001
+ function makron_fire_bfg(self, context) {
10002
+ if (!self.enemy) return;
10003
+ context.engine.sound?.(self, 0, "makron/bfg_fire.wav", 1, 1, 0);
10004
+ const start = getProjectedOffset2(self, MAKRON_BFG_OFFSET);
10005
+ const target = { ...self.enemy.origin };
10006
+ target.z += self.enemy.viewheight || 0;
10007
+ const dir = normalizeVec3(subtractVec3(target, start));
10008
+ monster_fire_bfg(self, start, dir, 50, 300, 100, 300, 0, context);
10009
+ }
10010
+ function makron_fire_railgun(self, context) {
10011
+ if (!self.pos1) return;
10012
+ context.engine.sound?.(self, 0, "makron/rail_fire.wav", 1, 1, 0);
10013
+ const start = getProjectedOffset2(self, MAKRON_RAILGUN_OFFSET);
10014
+ const dir = normalizeVec3(subtractVec3(self.pos1, start));
10015
+ monster_fire_railgun(self, start, dir, 50, 100, 0, context);
10016
+ }
10017
+ function makron_save_loc(self) {
10018
+ if (!self.enemy) return;
10019
+ self.pos1 = { ...self.enemy.origin };
10020
+ self.pos1 = { ...self.pos1, z: self.pos1.z + (self.enemy.viewheight || 0) };
10021
+ }
10022
+ function makron_fire_hyperblaster(self, context) {
10023
+ context.engine.sound?.(self, 0, "makron/blaster.wav", 1, 1, 0);
10024
+ const start = getProjectedOffset2(self, MAKRON_BLASTER_OFFSET_1);
10025
+ const relFrame = (self.monsterinfo.nextframe || 0) - attack_hyperblaster_move.firstframe;
10026
+ let yawDelta = 0;
10027
+ let dir;
10028
+ if (self.enemy) {
10029
+ const target = { ...self.enemy.origin };
10030
+ target.z += self.enemy.viewheight || 0;
10031
+ const vec = subtractVec3(target, start);
10032
+ const baseAngles = vectorToAngles(vec);
10033
+ const enemyAngles = { ...baseAngles };
10034
+ if (relFrame <= 12) {
10035
+ enemyAngles.y -= 5 * (relFrame - 4);
10036
+ } else {
10037
+ enemyAngles.y -= 40 - 5 * (relFrame - 12);
10038
+ }
10039
+ const forward = angleVectors(enemyAngles).forward;
10040
+ dir = forward;
10041
+ } else {
10042
+ const { forward } = angleVectors(self.angles);
10043
+ dir = forward;
10044
+ }
10045
+ monster_fire_blaster(self, start, dir, 15, 1e3, 0, 0, context, 1 /* BLASTER */);
10046
+ }
10047
+ function makron_pain(self, other, kick, damage, context) {
10048
+ if (self.health < self.max_health / 2) {
10049
+ self.skin = 1;
10050
+ }
10051
+ if (self.timestamp < (self.pain_finished_time || 0)) return;
10052
+ if (damage <= 25 && Math.random() < 0.2) return;
10053
+ self.pain_finished_time = self.timestamp + 3;
10054
+ if (damage <= 40) {
10055
+ context.engine.sound?.(self, 0, "makron/pain1.wav", 1, 1, 0);
10056
+ self.monsterinfo.current_move = pain4_move;
10057
+ } else if (damage <= 110) {
10058
+ context.engine.sound?.(self, 0, "makron/pain2.wav", 1, 1, 0);
10059
+ self.monsterinfo.current_move = pain5_move;
10060
+ } else {
10061
+ if (Math.random() <= 0.45) {
10062
+ context.engine.sound?.(self, 0, "makron/pain3.wav", 1, 1, 0);
10063
+ self.monsterinfo.current_move = pain6_move;
10064
+ }
10065
+ }
10066
+ }
10067
+ function makron_torso_think(self, context) {
10068
+ if (++self.frame >= 365)
10069
+ self.frame = 346;
10070
+ self.nextthink = context.timeSeconds + 0.1;
10071
+ if (self.angles.x > 0)
10072
+ self.angles = { ...self.angles, x: Math.max(0, self.angles.x - 15) };
10073
+ }
10074
+ function makron_torso(ent, context) {
10075
+ ent.frame = 346;
10076
+ ent.model = "models/monsters/boss3/rider/tris.md2";
10077
+ ent.skin = 1;
10078
+ ent.think = makron_torso_think;
10079
+ ent.nextthink = context.timeSeconds + 0.1;
10080
+ context.sound(ent, 0, "makron/spine.wav", 1, 1, 0);
10081
+ ent.movetype = 7 /* Toss */;
10082
+ const { forward, up } = angleVectors(ent.angles);
10083
+ const vUp = scaleVec3(up, 120);
10084
+ const vFwd = scaleVec3(forward, -120);
10085
+ ent.velocity = addVec3(addVec3(ent.velocity, vUp), vFwd);
10086
+ ent.origin = addVec3(ent.origin, scaleVec3(forward, -10));
10087
+ ent.angles = { ...ent.angles, x: 90 };
10088
+ ent.avelocity = ZERO_VEC3;
10089
+ context.linkentity(ent);
10090
+ }
10091
+ function makron_spawn_torso(self, context) {
10092
+ const tempent = context.spawn();
10093
+ tempent.classname = "makron_torso";
10094
+ tempent.origin = { ...self.origin };
10095
+ tempent.angles = { ...self.angles };
10096
+ tempent.origin.z += self.maxs.z - 15;
10097
+ makron_torso(tempent, context);
10098
+ }
10099
+ function makron_die(self, context) {
10100
+ context.engine.sound?.(self, 0, "makron/death.wav", 1, 1, 0);
10101
+ makron_spawn_torso(self, context);
10102
+ self.monsterinfo.current_move = death_move10;
10103
+ self.mins = { x: -60, y: -60, z: 0 };
10104
+ self.maxs = { x: 60, y: 60, z: 48 };
10105
+ }
10106
+ function makron_dead(self) {
10107
+ self.monsterinfo.nextframe = death_move10.lastframe;
10108
+ self.nextthink = -1;
10109
+ }
10110
+ var stand_frames12 = Array.from({ length: 60 }, () => ({ ai: monster_ai_stand13, dist: 0 }));
10111
+ stand_move12 = { firstframe: 0, lastframe: 59, frames: stand_frames12, endfunc: makron_stand };
10112
+ var walk_frames11 = Array.from({ length: 10 }, () => ({ ai: monster_ai_walk13, dist: 8 }));
10113
+ walk_move11 = { firstframe: 60, lastframe: 69, frames: walk_frames11, endfunc: makron_walk };
10114
+ var run_frames10 = Array.from({ length: 10 }, () => ({ ai: monster_ai_run12, dist: 8 }));
10115
+ run_move11 = { firstframe: 60, lastframe: 69, frames: run_frames10, endfunc: makron_run };
10116
+ var attack_bfg_frames = Array.from({ length: 8 }, (_, i) => ({
10117
+ ai: monster_ai_charge13,
10118
+ dist: 0,
10119
+ think: i === 3 ? makron_fire_bfg : null
10120
+ }));
10121
+ attack_bfg_move = { firstframe: 70, lastframe: 77, frames: attack_bfg_frames, endfunc: makron_run };
10122
+ var attack_hyperblaster_frames = Array.from({ length: 26 }, (_, i) => ({
10123
+ ai: monster_ai_move13,
10124
+ dist: 0,
10125
+ think: i >= 4 && i <= 20 ? makron_fire_hyperblaster : null
10126
+ }));
10127
+ attack_hyperblaster_move = { firstframe: 78, lastframe: 103, frames: attack_hyperblaster_frames, endfunc: makron_run };
10128
+ var attack_railgun_frames = Array.from({ length: 16 }, (_, i) => ({
10129
+ ai: monster_ai_charge13,
10130
+ dist: 0,
10131
+ think: i === 7 ? makron_save_loc : i === 8 ? makron_fire_railgun : null
10132
+ }));
10133
+ attack_railgun_move = { firstframe: 104, lastframe: 119, frames: attack_railgun_frames, endfunc: makron_run };
10134
+ var pain4_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10135
+ pain4_move = { firstframe: 120, lastframe: 123, frames: pain4_frames, endfunc: makron_run };
10136
+ var pain5_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10137
+ pain5_move = { firstframe: 124, lastframe: 127, frames: pain5_frames, endfunc: makron_run };
10138
+ var pain6_frames = Array.from({ length: 27 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10139
+ pain6_move = { firstframe: 128, lastframe: 154, frames: pain6_frames, endfunc: makron_run };
10140
+ var death_frames10 = Array.from({ length: 95 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10141
+ death_move10 = { firstframe: 155, lastframe: 249, frames: death_frames10, endfunc: makron_dead };
10142
+ var sight_frames = Array.from({ length: 13 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10143
+ sight_move = { firstframe: 250, lastframe: 262, frames: sight_frames, endfunc: makron_run };
10144
+ function SP_monster_makron(self, context) {
10145
+ self.classname = "monster_makron";
10146
+ self.model = "models/monsters/boss3/rider/tris.md2";
10147
+ self.mins = { x: -30, y: -30, z: 0 };
10148
+ self.maxs = { x: 30, y: 30, z: 90 };
10149
+ self.movetype = 5 /* Step */;
10150
+ self.solid = 2 /* BoundingBox */;
10151
+ self.health = 3e3;
10152
+ self.max_health = 3e3;
10153
+ self.mass = 500;
10154
+ self.takedamage = true;
10155
+ self.viewheight = 90;
10156
+ self.pain = (ent, other, kick, dmg) => makron_pain(ent, other, kick, dmg, context.entities);
10157
+ self.die = (self2, inflictor, attacker, damage, point) => {
10158
+ if (self2.health <= -2e3) {
10159
+ throwGibs(context.entities, self2.origin, damage);
10160
+ context.entities.free(self2);
10161
+ return;
10162
+ }
10163
+ self2.deadflag = 2 /* Dead */;
10164
+ self2.solid = 0 /* Not */;
10165
+ makron_die(self2, context.entities);
10166
+ };
10167
+ self.monsterinfo.stand = makron_stand;
10168
+ self.monsterinfo.walk = makron_walk;
10169
+ self.monsterinfo.run = makron_run;
10170
+ self.monsterinfo.attack = makron_attack;
10171
+ self.monsterinfo.sight = (self2, other) => {
10172
+ context.entities.sound?.(self2, 0, "makron/sight.wav", 1, 1, 0);
10173
+ self2.monsterinfo.current_move = sight_move;
10174
+ };
10175
+ self.think = monster_think;
10176
+ self.monsterinfo.current_move = sight_move;
10177
+ self.nextthink = self.timestamp + MONSTER_TICK13;
10178
+ }
10179
+ function registerMakronSpawns(registry) {
10180
+ registry.register("monster_makron", SP_monster_makron);
10181
+ }
10182
+
10183
+ // src/entities/monsters/jorg.ts
10184
+ var MONSTER_TICK14 = 0.1;
10185
+ var JORG_MACHINEGUN_R1_OFFSET = { x: 40, y: -20, z: 20 };
10186
+ var JORG_MACHINEGUN_L1_OFFSET = { x: 40, y: 20, z: 20 };
10187
+ var JORG_BFG_OFFSET = { x: 30, y: 0, z: 40 };
10188
+ function monster_ai_stand14(self, dist, context) {
10189
+ ai_stand(self, MONSTER_TICK14, context);
10190
+ }
10191
+ function monster_ai_walk14(self, dist, context) {
10192
+ ai_walk(self, dist, MONSTER_TICK14, context);
10193
+ }
10194
+ function monster_ai_run13(self, dist, context) {
10195
+ ai_run(self, dist, MONSTER_TICK14, context);
10196
+ }
10197
+ function monster_ai_charge14(self, dist, context) {
10198
+ ai_charge(self, dist, MONSTER_TICK14, context);
10199
+ }
10200
+ function monster_ai_move14(self, dist, context) {
10201
+ ai_move(self, dist);
10202
+ }
10203
+ var stand_move13;
10204
+ var walk_move12;
10205
+ var run_move12;
9954
10206
  var attack1_move3;
9955
10207
  var attack1_end_move;
9956
10208
  var attack2_move2;
9957
10209
  var pain1_move5;
9958
10210
  var pain2_move5;
9959
10211
  var pain3_move4;
9960
- var death_move10;
10212
+ var death_move11;
9961
10213
  function jorg_stand(self) {
9962
- self.monsterinfo.current_move = stand_move12;
10214
+ self.monsterinfo.current_move = stand_move13;
9963
10215
  }
9964
10216
  function jorg_walk(self) {
9965
- self.monsterinfo.current_move = walk_move11;
10217
+ self.monsterinfo.current_move = walk_move12;
9966
10218
  }
9967
10219
  function jorg_run(self) {
9968
10220
  if (self.enemy && self.enemy.health > 0) {
9969
- self.monsterinfo.current_move = run_move11;
10221
+ self.monsterinfo.current_move = run_move12;
9970
10222
  } else {
9971
- self.monsterinfo.current_move = stand_move12;
10223
+ self.monsterinfo.current_move = stand_move13;
9972
10224
  }
9973
10225
  }
9974
10226
  function jorg_attack(self, context) {
@@ -9996,7 +10248,7 @@ function jorg_reattack1(self, context) {
9996
10248
  self.monsterinfo.current_move = attack1_end_move;
9997
10249
  }
9998
10250
  }
9999
- function getProjectedOffset2(self, offset) {
10251
+ function getProjectedOffset3(self, offset) {
10000
10252
  const { forward, right, up } = angleVectors(self.angles);
10001
10253
  const start = { ...self.origin };
10002
10254
  const x = scaleVec3(forward, offset.x);
@@ -10006,16 +10258,16 @@ function getProjectedOffset2(self, offset) {
10006
10258
  }
10007
10259
  function jorg_fire_bullet(self, context) {
10008
10260
  if (!self.enemy) return;
10009
- const startL = getProjectedOffset2(self, JORG_MACHINEGUN_L1_OFFSET);
10261
+ const startL = getProjectedOffset3(self, JORG_MACHINEGUN_L1_OFFSET);
10010
10262
  const dirL = normalizeVec3(subtractVec3(self.enemy.origin, startL));
10011
10263
  monster_fire_bullet_v2(self, startL, dirL, 6, 4, 0.05, 0.05, 0, context, 4 /* MACHINEGUN */);
10012
- const startR = getProjectedOffset2(self, JORG_MACHINEGUN_R1_OFFSET);
10264
+ const startR = getProjectedOffset3(self, JORG_MACHINEGUN_R1_OFFSET);
10013
10265
  const dirR = normalizeVec3(subtractVec3(self.enemy.origin, startR));
10014
10266
  monster_fire_bullet_v2(self, startR, dirR, 6, 4, 0.05, 0.05, 0, context, 4 /* MACHINEGUN */);
10015
10267
  }
10016
10268
  function jorg_fire_bfg(self, context) {
10017
10269
  if (!self.enemy) return;
10018
- const start = getProjectedOffset2(self, JORG_BFG_OFFSET);
10270
+ const start = getProjectedOffset3(self, JORG_BFG_OFFSET);
10019
10271
  const target = { ...self.enemy.origin };
10020
10272
  target.z += self.enemy.viewheight || 0;
10021
10273
  const dir = normalizeVec3(subtractVec3(target, start));
@@ -10046,52 +10298,66 @@ function jorg_pain(self, other, kick, damage, context) {
10046
10298
  }
10047
10299
  function jorg_die(self, context) {
10048
10300
  context.engine.sound?.(self, 0, "boss3/bs3deth1.wav", 1, 1, 0);
10049
- self.monsterinfo.current_move = death_move10;
10301
+ self.monsterinfo.current_move = death_move11;
10050
10302
  }
10051
10303
  function jorg_dead(self) {
10052
- self.monsterinfo.nextframe = death_move10.lastframe;
10304
+ self.monsterinfo.nextframe = death_move11.lastframe;
10053
10305
  self.nextthink = -1;
10054
10306
  }
10055
10307
  function makron_toss(self, context) {
10056
10308
  const makron = context.spawn();
10057
10309
  makron.classname = "monster_makron";
10058
10310
  makron.origin = { ...self.origin };
10059
- makron.angles = { ...self.angles };
10060
- }
10061
- var stand_frames12 = Array.from({ length: 51 }, () => ({ ai: monster_ai_stand13, dist: 0 }));
10062
- stand_move12 = { firstframe: 0, lastframe: 50, frames: stand_frames12, endfunc: jorg_stand };
10063
- var walk_frames11 = Array.from({ length: 14 }, () => ({ ai: monster_ai_walk13, dist: 10 }));
10064
- walk_move11 = { firstframe: 51, lastframe: 64, frames: walk_frames11, endfunc: jorg_walk };
10065
- var run_frames10 = Array.from({ length: 14 }, () => ({ ai: monster_ai_run12, dist: 10 }));
10066
- run_move11 = { firstframe: 51, lastframe: 64, frames: run_frames10, endfunc: jorg_run };
10067
- var attack1_start_frames = Array.from({ length: 8 }, () => ({ ai: monster_ai_charge13, dist: 0 }));
10311
+ makron.target = self.target;
10312
+ makron.enemy = self.enemy;
10313
+ const spawnContext = { entities: context };
10314
+ SP_monster_makron(makron, spawnContext);
10315
+ if (makron.enemy && makron.enemy.health > 0) {
10316
+ const vec = subtractVec3(makron.enemy.origin, makron.origin);
10317
+ makron.angles = { ...makron.angles, y: vectorToYaw(vec) };
10318
+ const dir = normalizeVec3(vec);
10319
+ const vel = scaleVec3(dir, 400);
10320
+ makron.velocity = { x: vel.x, y: vel.y, z: 200 };
10321
+ makron.groundentity = null;
10322
+ if (makron.monsterinfo.sight) {
10323
+ makron.monsterinfo.sight(makron, makron.enemy);
10324
+ }
10325
+ }
10326
+ }
10327
+ var stand_frames13 = Array.from({ length: 51 }, () => ({ ai: monster_ai_stand14, dist: 0 }));
10328
+ stand_move13 = { firstframe: 0, lastframe: 50, frames: stand_frames13, endfunc: jorg_stand };
10329
+ var walk_frames12 = Array.from({ length: 14 }, () => ({ ai: monster_ai_walk14, dist: 10 }));
10330
+ walk_move12 = { firstframe: 51, lastframe: 64, frames: walk_frames12, endfunc: jorg_walk };
10331
+ var run_frames11 = Array.from({ length: 14 }, () => ({ ai: monster_ai_run13, dist: 10 }));
10332
+ run_move12 = { firstframe: 51, lastframe: 64, frames: run_frames11, endfunc: jorg_run };
10333
+ var attack1_start_frames = Array.from({ length: 8 }, () => ({ ai: monster_ai_charge14, dist: 0 }));
10068
10334
  var attack1_start_move = { firstframe: 65, lastframe: 72, frames: attack1_start_frames, endfunc: null };
10069
- var attack1_frames3 = Array.from({ length: 6 }, () => ({ ai: monster_ai_charge13, dist: 0, think: jorg_fire_bullet }));
10335
+ var attack1_frames3 = Array.from({ length: 6 }, () => ({ ai: monster_ai_charge14, dist: 0, think: jorg_fire_bullet }));
10070
10336
  attack1_move3 = { firstframe: 73, lastframe: 78, frames: attack1_frames3, endfunc: jorg_reattack1 };
10071
10337
  attack1_start_move.endfunc = (self) => {
10072
10338
  self.monsterinfo.current_move = attack1_move3;
10073
10339
  };
10074
- var attack1_end_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10340
+ var attack1_end_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10075
10341
  attack1_end_move = { firstframe: 79, lastframe: 82, frames: attack1_end_frames, endfunc: jorg_run };
10076
10342
  var attack2_frames2 = Array.from({ length: 13 }, (_, i) => ({
10077
- ai: monster_ai_charge13,
10343
+ ai: monster_ai_charge14,
10078
10344
  dist: 0,
10079
10345
  think: i === 6 ? jorg_fire_bfg : null
10080
10346
  }));
10081
10347
  attack2_move2 = { firstframe: 83, lastframe: 95, frames: attack2_frames2, endfunc: jorg_run };
10082
- var pain1_frames5 = Array.from({ length: 3 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10348
+ var pain1_frames5 = Array.from({ length: 3 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10083
10349
  pain1_move5 = { firstframe: 96, lastframe: 98, frames: pain1_frames5, endfunc: jorg_run };
10084
- var pain2_frames5 = Array.from({ length: 3 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10350
+ var pain2_frames5 = Array.from({ length: 3 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10085
10351
  pain2_move5 = { firstframe: 99, lastframe: 101, frames: pain2_frames5, endfunc: jorg_run };
10086
- var pain3_frames4 = Array.from({ length: 25 }, () => ({ ai: monster_ai_move13, dist: 0 }));
10352
+ var pain3_frames4 = Array.from({ length: 25 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10087
10353
  pain3_move4 = { firstframe: 102, lastframe: 126, frames: pain3_frames4, endfunc: jorg_run };
10088
- var death_frames10 = Array.from({ length: 50 }, (_, i) => ({
10089
- ai: monster_ai_move13,
10354
+ var death_frames11 = Array.from({ length: 50 }, (_, i) => ({
10355
+ ai: monster_ai_move14,
10090
10356
  dist: 0,
10091
10357
  think: i === 49 ? ((self, ctx) => {
10092
10358
  }) : i === 48 ? makron_toss : null
10093
10359
  }));
10094
- death_move10 = { firstframe: 127, lastframe: 176, frames: death_frames10, endfunc: jorg_dead };
10360
+ death_move11 = { firstframe: 127, lastframe: 176, frames: death_frames11, endfunc: jorg_dead };
10095
10361
  function SP_monster_jorg(self, context) {
10096
10362
  self.classname = "monster_jorg";
10097
10363
  self.model = "models/monsters/boss3/jorg/tris.md2";
@@ -10124,14 +10390,14 @@ function SP_monster_jorg(self, context) {
10124
10390
  };
10125
10391
  self.think = monster_think;
10126
10392
  jorg_stand(self);
10127
- self.nextthink = self.timestamp + MONSTER_TICK13;
10393
+ self.nextthink = self.timestamp + MONSTER_TICK14;
10128
10394
  }
10129
10395
  function registerJorgSpawns(registry) {
10130
10396
  registry.register("monster_jorg", SP_monster_jorg);
10131
10397
  }
10132
10398
 
10133
10399
  // src/entities/monsters/insane.ts
10134
- var MONSTER_TICK14 = 0.1;
10400
+ var MONSTER_TICK15 = 0.1;
10135
10401
  var SPAWNFLAG_INSANE_CRAWL = 4;
10136
10402
  var SPAWNFLAG_INSANE_CRUCIFIED = 8;
10137
10403
  var SPAWNFLAG_INSANE_STAND_GROUND = 16;
@@ -10301,7 +10567,7 @@ function insane_dead(self, context) {
10301
10567
  function m(ai, dist = 0, think) {
10302
10568
  return { ai: (s, d, c) => {
10303
10569
  if (think) think(s, c);
10304
- ai(s, dist, MONSTER_TICK14, c);
10570
+ ai(s, dist, MONSTER_TICK15, c);
10305
10571
  }, dist };
10306
10572
  }
10307
10573
  var frames_stand_normal = [
@@ -10540,7 +10806,7 @@ insane_move_run_normal = {
10540
10806
  frames: frames_walk_normal.map((f) => ({
10541
10807
  ai: (s, d, c) => {
10542
10808
  if (f.ai === frames_walk_normal[0].ai) insane_scream(s, c);
10543
- ai_run(s, d, MONSTER_TICK14, c);
10809
+ ai_run(s, d, MONSTER_TICK15, c);
10544
10810
  },
10545
10811
  dist: f.dist
10546
10812
  })),
@@ -10586,7 +10852,7 @@ insane_move_run_insane = {
10586
10852
  frames: frames_walk_insane.map((f) => ({
10587
10853
  ai: (s, d, c) => {
10588
10854
  if (f.ai === frames_walk_insane[0].ai) insane_scream(s, c);
10589
- ai_run(s, d, MONSTER_TICK14, c);
10855
+ ai_run(s, d, MONSTER_TICK15, c);
10590
10856
  },
10591
10857
  dist: f.dist
10592
10858
  })),
@@ -10813,7 +11079,7 @@ function SP_misc_insane(self, context) {
10813
11079
  self.monsterinfo.current_move = insane_move_stand_normal;
10814
11080
  self.monsterinfo.scale = 1;
10815
11081
  self.think = monster_think;
10816
- self.nextthink = context.entities.timeSeconds + MONSTER_TICK14;
11082
+ self.nextthink = context.entities.timeSeconds + MONSTER_TICK15;
10817
11083
  if (self.spawnflags & SPAWNFLAG_INSANE_CRUCIFIED) {
10818
11084
  self.mass = 1e5;
10819
11085
  }
@@ -10823,218 +11089,548 @@ function registerInsaneSpawns(registry) {
10823
11089
  registry.register("misc_insane", SP_misc_insane);
10824
11090
  }
10825
11091
 
10826
- // src/entities/monsters/makron.ts
10827
- var MONSTER_TICK15 = 0.1;
10828
- var MAKRON_BFG_OFFSET = { x: 30, y: 28, z: 24 };
10829
- var MAKRON_BLASTER_OFFSET_1 = { x: 26, y: 16, z: 24 };
10830
- var MAKRON_RAILGUN_OFFSET = { x: 26, y: -14, z: 24 };
10831
- function monster_ai_stand14(self, dist, context) {
10832
- ai_stand(self, MONSTER_TICK15, context);
11092
+ // src/entities/monsters/actor.ts
11093
+ var MONSTER_TICK16 = 0.1;
11094
+ var MZ2_ACTOR_MACHINEGUN_1 = 0;
11095
+ var actor_names = [
11096
+ "Hellrot",
11097
+ "Tokay",
11098
+ "Killme",
11099
+ "Disruptor",
11100
+ "Adrianator",
11101
+ "Rambear",
11102
+ "Titus",
11103
+ "Bitterman"
11104
+ ];
11105
+ var FRAME_stand101 = 0;
11106
+ var FRAME_stand140 = 39;
11107
+ var FRAME_walk01 = 40;
11108
+ var FRAME_walk08 = 47;
11109
+ var FRAME_run02 = 48;
11110
+ var FRAME_run07 = 53;
11111
+ var FRAME_pain101 = 54;
11112
+ var FRAME_pain103 = 56;
11113
+ var FRAME_pain201 = 57;
11114
+ var FRAME_pain203 = 59;
11115
+ var FRAME_pain301 = 60;
11116
+ var FRAME_pain303 = 62;
11117
+ var FRAME_flip01 = 63;
11118
+ var FRAME_flip14 = 76;
11119
+ var FRAME_taunt01 = 77;
11120
+ var FRAME_taunt17 = 93;
11121
+ var FRAME_death101 = 94;
11122
+ var FRAME_death107 = 100;
11123
+ var FRAME_death201 = 101;
11124
+ var FRAME_death213 = 113;
11125
+ var FRAME_attak01 = 114;
11126
+ var FRAME_attak04 = 117;
11127
+ var actor_move_stand;
11128
+ var actor_move_walk;
11129
+ var actor_move_run;
11130
+ var actor_move_pain1;
11131
+ var actor_move_pain2;
11132
+ var actor_move_pain3;
11133
+ var actor_move_flipoff;
11134
+ var actor_move_taunt;
11135
+ var actor_move_death1;
11136
+ var actor_move_death2;
11137
+ var actor_move_attack;
11138
+ function m2(ai, dist = 0, think) {
11139
+ return { ai: (s, d, c) => {
11140
+ if (think) think(s, c);
11141
+ ai(s, dist, MONSTER_TICK16, c);
11142
+ }, dist };
10833
11143
  }
10834
- function monster_ai_walk14(self, dist, context) {
10835
- ai_walk(self, dist, MONSTER_TICK15, context);
11144
+ function actor_stand(self, context) {
11145
+ self.monsterinfo.current_move = actor_move_stand;
11146
+ if (context.timeSeconds < 1) {
11147
+ self.frame = FRAME_stand101 + Math.floor(Math.random() * (FRAME_stand140 - FRAME_stand101 + 1));
11148
+ }
10836
11149
  }
10837
- function monster_ai_run13(self, dist, context) {
10838
- ai_run(self, dist, MONSTER_TICK15, context);
11150
+ function actor_walk(self, context) {
11151
+ self.monsterinfo.current_move = actor_move_walk;
10839
11152
  }
10840
- function monster_ai_charge14(self, dist, context) {
10841
- ai_charge(self, dist, MONSTER_TICK15, context);
11153
+ function actor_run(self, context) {
11154
+ if (context.timeSeconds < self.pain_debounce_time && !self.enemy) {
11155
+ if (self.movetarget)
11156
+ actor_walk(self, context);
11157
+ else
11158
+ actor_stand(self, context);
11159
+ return;
11160
+ }
11161
+ if (self.monsterinfo.aiflags & 1 /* StandGround */) {
11162
+ actor_stand(self, context);
11163
+ return;
11164
+ }
11165
+ self.monsterinfo.current_move = actor_move_run;
10842
11166
  }
10843
- function monster_ai_move14(self, dist, context) {
10844
- ai_move(self, dist);
11167
+ var messages = [
11168
+ "Watch it",
11169
+ "#$@*&",
11170
+ "Idiot",
11171
+ "Check your targets"
11172
+ ];
11173
+ function actor_pain(self, other, kick, damage) {
11174
+ const context = self.monsterinfo.context;
11175
+ if (!context) return;
11176
+ if (context.timeSeconds < self.pain_debounce_time)
11177
+ return;
11178
+ self.pain_debounce_time = context.timeSeconds + 3;
11179
+ const random10 = Math.random();
11180
+ if (other && other.client && random10 < 0.4) {
11181
+ const v = subtractVec3(other.origin, self.origin);
11182
+ self.ideal_yaw = vectorToYaw(v);
11183
+ if (Math.random() < 0.5)
11184
+ self.monsterinfo.current_move = actor_move_flipoff;
11185
+ else
11186
+ self.monsterinfo.current_move = actor_move_taunt;
11187
+ const name = actor_names[Math.floor(Math.random() * actor_names.length)];
11188
+ const message = messages[Math.floor(Math.random() * messages.length)];
11189
+ context.centerprintf(other, `${name}: ${message}!
11190
+ `);
11191
+ return;
11192
+ }
11193
+ const n = Math.floor(Math.random() * 3);
11194
+ if (n === 0)
11195
+ self.monsterinfo.current_move = actor_move_pain1;
11196
+ else if (n === 1)
11197
+ self.monsterinfo.current_move = actor_move_pain2;
11198
+ else
11199
+ self.monsterinfo.current_move = actor_move_pain3;
10845
11200
  }
10846
- var stand_move13;
10847
- var walk_move12;
10848
- var run_move12;
10849
- var attack_bfg_move;
10850
- var attack_hyperblaster_move;
10851
- var attack_railgun_move;
10852
- var pain4_move;
10853
- var pain5_move;
10854
- var pain6_move;
10855
- var death_move11;
10856
- var sight_move;
10857
- function makron_stand(self) {
10858
- self.monsterinfo.current_move = stand_move13;
10859
- }
10860
- function makron_walk(self) {
10861
- self.monsterinfo.current_move = walk_move12;
10862
- }
10863
- function makron_run(self) {
10864
- if (self.enemy && self.enemy.health > 0) {
10865
- self.monsterinfo.current_move = run_move12;
10866
- } else {
10867
- self.monsterinfo.current_move = stand_move13;
10868
- }
10869
- }
10870
- function makron_attack(self) {
10871
- if (!self.enemy) return;
10872
- const r = Math.random();
10873
- if (r <= 0.3) {
10874
- self.monsterinfo.current_move = attack_bfg_move;
10875
- } else if (r <= 0.6) {
10876
- self.monsterinfo.current_move = attack_hyperblaster_move;
10877
- } else {
10878
- self.monsterinfo.current_move = attack_railgun_move;
10879
- }
10880
- }
10881
- function getProjectedOffset3(self, offset) {
10882
- const { forward, right, up } = angleVectors(self.angles);
10883
- const start = { ...self.origin };
10884
- const x = scaleVec3(forward, offset.x);
10885
- const y = scaleVec3(right, offset.y);
10886
- const z = scaleVec3(up, offset.z);
10887
- return addVec3(addVec3(addVec3(start, x), y), z);
10888
- }
10889
- function makron_fire_bfg(self, context) {
10890
- if (!self.enemy) return;
10891
- context.engine.sound?.(self, 0, "makron/bfg_fire.wav", 1, 1, 0);
10892
- const start = getProjectedOffset3(self, MAKRON_BFG_OFFSET);
10893
- const target = { ...self.enemy.origin };
10894
- target.z += self.enemy.viewheight || 0;
10895
- const dir = normalizeVec3(subtractVec3(target, start));
10896
- monster_fire_bfg(self, start, dir, 50, 300, 100, 300, 0, context);
10897
- }
10898
- function makron_fire_railgun(self, context) {
10899
- if (!self.pos1) return;
10900
- context.engine.sound?.(self, 0, "makron/rail_fire.wav", 1, 1, 0);
10901
- const start = getProjectedOffset3(self, MAKRON_RAILGUN_OFFSET);
10902
- const dir = normalizeVec3(subtractVec3(self.pos1, start));
10903
- monster_fire_railgun(self, start, dir, 50, 100, 0, context);
10904
- }
10905
- function makron_save_loc(self) {
10906
- if (!self.enemy) return;
10907
- self.pos1 = { ...self.enemy.origin };
10908
- self.pos1 = { ...self.pos1, z: self.pos1.z + (self.enemy.viewheight || 0) };
11201
+ function actor_setskin(self, context) {
11202
+ if (self.health < self.max_health / 2)
11203
+ self.skin = 1;
11204
+ else
11205
+ self.skin = 0;
10909
11206
  }
10910
- function makron_fire_hyperblaster(self, context) {
10911
- context.engine.sound?.(self, 0, "makron/blaster.wav", 1, 1, 0);
10912
- const start = getProjectedOffset3(self, MAKRON_BLASTER_OFFSET_1);
10913
- const relFrame = (self.monsterinfo.nextframe || 0) - attack_hyperblaster_move.firstframe;
10914
- let yawDelta = 0;
11207
+ function actorMachineGun(self, context) {
11208
+ const flashOffset = { x: 0, y: 0, z: 0 };
11209
+ const vectors = angleVectors(self.angles);
11210
+ const forward = vectors.forward;
11211
+ const start = copyVec3(self.origin);
11212
+ start.z += self.viewheight;
10915
11213
  let dir;
10916
11214
  if (self.enemy) {
10917
- const target = { ...self.enemy.origin };
10918
- target.z += self.enemy.viewheight || 0;
10919
- const vec = subtractVec3(target, start);
10920
- const baseAngles = vectorToAngles(vec);
10921
- const enemyAngles = { ...baseAngles };
10922
- if (relFrame <= 12) {
10923
- enemyAngles.y -= 5 * (relFrame - 4);
11215
+ let target;
11216
+ if (self.enemy.health > 0) {
11217
+ target = subtractVec3(self.enemy.origin, scaleVec3(self.enemy.velocity, 0.2));
11218
+ target.z += self.enemy.viewheight;
10924
11219
  } else {
10925
- enemyAngles.y -= 40 - 5 * (relFrame - 12);
11220
+ target = copyVec3(self.enemy.absmin);
11221
+ target.z += self.enemy.size.z / 2 + 1;
10926
11222
  }
10927
- const forward = angleVectors(enemyAngles).forward;
10928
- dir = forward;
11223
+ dir = subtractVec3(target, start);
11224
+ dir = normalizeVec3(dir);
10929
11225
  } else {
10930
- const { forward } = angleVectors(self.angles);
10931
11226
  dir = forward;
10932
11227
  }
10933
- monster_fire_blaster(self, start, dir, 15, 1e3, 0, 0, context, 1 /* BLASTER */);
11228
+ monster_fire_bullet(self, start, dir, 3, 4, 0, 0, MZ2_ACTOR_MACHINEGUN_1, context);
10934
11229
  }
10935
- function makron_pain(self, other, kick, damage, context) {
10936
- if (self.health < self.max_health / 2) {
10937
- self.skin = 1;
10938
- }
10939
- if (self.timestamp < (self.pain_finished_time || 0)) return;
10940
- if (damage <= 25 && Math.random() < 0.2) return;
10941
- self.pain_finished_time = self.timestamp + 3;
10942
- if (damage <= 40) {
10943
- context.engine.sound?.(self, 0, "makron/pain1.wav", 1, 1, 0);
10944
- self.monsterinfo.current_move = pain4_move;
10945
- } else if (damage <= 110) {
10946
- context.engine.sound?.(self, 0, "makron/pain2.wav", 1, 1, 0);
10947
- self.monsterinfo.current_move = pain5_move;
10948
- } else {
10949
- if (Math.random() <= 0.45) {
10950
- context.engine.sound?.(self, 0, "makron/pain3.wav", 1, 1, 0);
10951
- self.monsterinfo.current_move = pain6_move;
10952
- }
10953
- }
11230
+ function actor_dead(self, context) {
11231
+ self.mins = { x: -16, y: -16, z: -24 };
11232
+ self.maxs = { x: 16, y: 16, z: -8 };
11233
+ self.movetype = 7 /* Toss */;
11234
+ self.svflags |= 1;
11235
+ self.nextthink = -1;
11236
+ context.linkentity(self);
10954
11237
  }
10955
- function makron_die(self, context) {
10956
- context.engine.sound?.(self, 0, "makron/death.wav", 1, 1, 0);
10957
- self.monsterinfo.current_move = death_move11;
11238
+ function actor_die(self, inflictor, attacker, damage, point, mod) {
11239
+ const context = self.monsterinfo.context;
11240
+ if (!context) return;
11241
+ if (self.health <= -80) {
11242
+ throwGibs(context, self.origin, damage);
11243
+ self.deadflag = 2 /* Dead */;
11244
+ return;
11245
+ }
11246
+ if (self.deadflag === 2 /* Dead */)
11247
+ return;
11248
+ self.deadflag = 2 /* Dead */;
11249
+ self.takedamage = true;
11250
+ if (Math.random() < 0.5)
11251
+ self.monsterinfo.current_move = actor_move_death1;
11252
+ else
11253
+ self.monsterinfo.current_move = actor_move_death2;
11254
+ }
11255
+ function actor_fire(self, context) {
11256
+ actorMachineGun(self, context);
11257
+ const fire_wait = self.monsterinfo.fire_wait ?? 0;
11258
+ if (context.timeSeconds >= fire_wait)
11259
+ self.monsterinfo.aiflags &= ~128 /* HoldFrame */;
11260
+ else
11261
+ self.monsterinfo.aiflags |= 128 /* HoldFrame */;
10958
11262
  }
10959
- function makron_dead(self) {
10960
- self.monsterinfo.nextframe = death_move11.lastframe;
10961
- self.nextthink = -1;
11263
+ function actor_attack(self, context) {
11264
+ self.monsterinfo.current_move = actor_move_attack;
11265
+ self.monsterinfo.fire_wait = context.timeSeconds + 1 + Math.random() * 1.6;
10962
11266
  }
10963
- var stand_frames13 = Array.from({ length: 60 }, () => ({ ai: monster_ai_stand14, dist: 0 }));
10964
- stand_move13 = { firstframe: 0, lastframe: 59, frames: stand_frames13, endfunc: makron_stand };
10965
- var walk_frames12 = Array.from({ length: 10 }, () => ({ ai: monster_ai_walk14, dist: 8 }));
10966
- walk_move12 = { firstframe: 60, lastframe: 69, frames: walk_frames12, endfunc: makron_walk };
10967
- var run_frames11 = Array.from({ length: 10 }, () => ({ ai: monster_ai_run13, dist: 8 }));
10968
- run_move12 = { firstframe: 60, lastframe: 69, frames: run_frames11, endfunc: makron_run };
10969
- var attack_bfg_frames = Array.from({ length: 8 }, (_, i) => ({
10970
- ai: monster_ai_charge14,
10971
- dist: 0,
10972
- think: i === 3 ? makron_fire_bfg : null
10973
- }));
10974
- attack_bfg_move = { firstframe: 70, lastframe: 77, frames: attack_bfg_frames, endfunc: makron_run };
10975
- var attack_hyperblaster_frames = Array.from({ length: 26 }, (_, i) => ({
10976
- ai: monster_ai_move14,
10977
- dist: 0,
10978
- think: i >= 4 && i <= 20 ? makron_fire_hyperblaster : null
10979
- }));
10980
- attack_hyperblaster_move = { firstframe: 78, lastframe: 103, frames: attack_hyperblaster_frames, endfunc: makron_run };
10981
- var attack_railgun_frames = Array.from({ length: 16 }, (_, i) => ({
10982
- ai: monster_ai_charge14,
10983
- dist: 0,
10984
- think: i === 7 ? makron_save_loc : i === 8 ? makron_fire_railgun : null
10985
- }));
10986
- attack_railgun_move = { firstframe: 104, lastframe: 119, frames: attack_railgun_frames, endfunc: makron_run };
10987
- var pain4_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10988
- pain4_move = { firstframe: 120, lastframe: 123, frames: pain4_frames, endfunc: makron_run };
10989
- var pain5_frames = Array.from({ length: 4 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10990
- pain5_move = { firstframe: 124, lastframe: 127, frames: pain5_frames, endfunc: makron_run };
10991
- var pain6_frames = Array.from({ length: 27 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10992
- pain6_move = { firstframe: 128, lastframe: 154, frames: pain6_frames, endfunc: makron_run };
10993
- var death_frames11 = Array.from({ length: 95 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10994
- death_move11 = { firstframe: 155, lastframe: 249, frames: death_frames11, endfunc: makron_dead };
10995
- var sight_frames = Array.from({ length: 13 }, () => ({ ai: monster_ai_move14, dist: 0 }));
10996
- sight_move = { firstframe: 250, lastframe: 262, frames: sight_frames, endfunc: makron_run };
10997
- function SP_monster_makron(self, context) {
10998
- self.classname = "monster_makron";
10999
- self.model = "models/monsters/boss3/rider/tris.md2";
11000
- self.mins = { x: -30, y: -30, z: 0 };
11001
- self.maxs = { x: 30, y: 30, z: 90 };
11267
+ function actor_use(self, other, activator) {
11268
+ const context = self.monsterinfo.context;
11269
+ const target = context.pickTarget(self.target);
11270
+ self.goalentity = target;
11271
+ self.movetarget = target;
11272
+ if (!self.movetarget || self.movetarget.classname !== "target_actor") {
11273
+ console.log(`${self.classname}: bad target ${self.target}`);
11274
+ self.target = void 0;
11275
+ self.monsterinfo.pausetime = 1e8;
11276
+ if (self.monsterinfo.stand) self.monsterinfo.stand(self, context);
11277
+ return;
11278
+ }
11279
+ const goalPos = self.goalentity ? self.goalentity.origin : self.movetarget ? self.movetarget.origin : self.origin;
11280
+ const v = subtractVec3(goalPos, self.origin);
11281
+ self.ideal_yaw = vectorToYaw(v);
11282
+ self.angles.y = self.ideal_yaw;
11283
+ if (self.monsterinfo.walk) self.monsterinfo.walk(self, context);
11284
+ self.target = void 0;
11285
+ }
11286
+ function actor_stand_wrapper(self, context) {
11287
+ actor_stand(self, context);
11288
+ }
11289
+ var frames_stand = [
11290
+ m2(ai_stand),
11291
+ m2(ai_stand),
11292
+ m2(ai_stand),
11293
+ m2(ai_stand),
11294
+ m2(ai_stand),
11295
+ m2(ai_stand),
11296
+ m2(ai_stand),
11297
+ m2(ai_stand),
11298
+ m2(ai_stand),
11299
+ m2(ai_stand),
11300
+ m2(ai_stand),
11301
+ m2(ai_stand),
11302
+ m2(ai_stand),
11303
+ m2(ai_stand),
11304
+ m2(ai_stand),
11305
+ m2(ai_stand),
11306
+ m2(ai_stand),
11307
+ m2(ai_stand),
11308
+ m2(ai_stand),
11309
+ m2(ai_stand),
11310
+ m2(ai_stand),
11311
+ m2(ai_stand),
11312
+ m2(ai_stand),
11313
+ m2(ai_stand),
11314
+ m2(ai_stand),
11315
+ m2(ai_stand),
11316
+ m2(ai_stand),
11317
+ m2(ai_stand),
11318
+ m2(ai_stand),
11319
+ m2(ai_stand),
11320
+ m2(ai_stand),
11321
+ m2(ai_stand),
11322
+ m2(ai_stand),
11323
+ m2(ai_stand),
11324
+ m2(ai_stand),
11325
+ m2(ai_stand),
11326
+ m2(ai_stand),
11327
+ m2(ai_stand),
11328
+ m2(ai_stand),
11329
+ m2(ai_stand)
11330
+ ];
11331
+ actor_move_stand = {
11332
+ firstframe: FRAME_stand101,
11333
+ lastframe: FRAME_stand140,
11334
+ frames: frames_stand,
11335
+ endfunc: null
11336
+ };
11337
+ var frames_walk = [
11338
+ m2(ai_walk),
11339
+ m2(ai_walk, 6),
11340
+ m2(ai_walk, 10),
11341
+ m2(ai_walk, 3),
11342
+ m2(ai_walk, 2),
11343
+ m2(ai_walk, 7),
11344
+ m2(ai_walk, 10),
11345
+ m2(ai_walk, 1)
11346
+ ];
11347
+ actor_move_walk = {
11348
+ firstframe: FRAME_walk01,
11349
+ lastframe: FRAME_walk08,
11350
+ frames: frames_walk,
11351
+ endfunc: null
11352
+ };
11353
+ var frames_run = [
11354
+ m2(ai_run, 4),
11355
+ m2(ai_run, 15),
11356
+ m2(ai_run, 15),
11357
+ m2(ai_run, 8),
11358
+ m2(ai_run, 20),
11359
+ m2(ai_run, 15)
11360
+ ];
11361
+ actor_move_run = {
11362
+ firstframe: FRAME_run02,
11363
+ lastframe: FRAME_run07,
11364
+ frames: frames_run,
11365
+ endfunc: null
11366
+ };
11367
+ var frames_pain1 = [
11368
+ m2(ai_move, -5),
11369
+ m2(ai_move, 4),
11370
+ m2(ai_move, 1)
11371
+ ];
11372
+ actor_move_pain1 = {
11373
+ firstframe: FRAME_pain101,
11374
+ lastframe: FRAME_pain103,
11375
+ frames: frames_pain1,
11376
+ endfunc: actor_run
11377
+ };
11378
+ var frames_pain2 = [
11379
+ m2(ai_move, -4),
11380
+ m2(ai_move, 4),
11381
+ m2(ai_move)
11382
+ ];
11383
+ actor_move_pain2 = {
11384
+ firstframe: FRAME_pain201,
11385
+ lastframe: FRAME_pain203,
11386
+ frames: frames_pain2,
11387
+ endfunc: actor_run
11388
+ };
11389
+ var frames_pain3 = [
11390
+ m2(ai_move, -1),
11391
+ m2(ai_move, 1),
11392
+ m2(ai_move, 0)
11393
+ ];
11394
+ actor_move_pain3 = {
11395
+ firstframe: FRAME_pain301,
11396
+ lastframe: FRAME_pain303,
11397
+ frames: frames_pain3,
11398
+ endfunc: actor_run
11399
+ };
11400
+ var frames_flipoff = [
11401
+ m2(ai_turn),
11402
+ m2(ai_turn),
11403
+ m2(ai_turn),
11404
+ m2(ai_turn),
11405
+ m2(ai_turn),
11406
+ m2(ai_turn),
11407
+ m2(ai_turn),
11408
+ m2(ai_turn),
11409
+ m2(ai_turn),
11410
+ m2(ai_turn),
11411
+ m2(ai_turn),
11412
+ m2(ai_turn),
11413
+ m2(ai_turn),
11414
+ m2(ai_turn)
11415
+ ];
11416
+ actor_move_flipoff = {
11417
+ firstframe: FRAME_flip01,
11418
+ lastframe: FRAME_flip14,
11419
+ frames: frames_flipoff,
11420
+ endfunc: actor_run
11421
+ };
11422
+ var frames_taunt = [
11423
+ m2(ai_turn),
11424
+ m2(ai_turn),
11425
+ m2(ai_turn),
11426
+ m2(ai_turn),
11427
+ m2(ai_turn),
11428
+ m2(ai_turn),
11429
+ m2(ai_turn),
11430
+ m2(ai_turn),
11431
+ m2(ai_turn),
11432
+ m2(ai_turn),
11433
+ m2(ai_turn),
11434
+ m2(ai_turn),
11435
+ m2(ai_turn),
11436
+ m2(ai_turn),
11437
+ m2(ai_turn),
11438
+ m2(ai_turn),
11439
+ m2(ai_turn)
11440
+ ];
11441
+ actor_move_taunt = {
11442
+ firstframe: FRAME_taunt01,
11443
+ lastframe: FRAME_taunt17,
11444
+ frames: frames_taunt,
11445
+ endfunc: actor_run
11446
+ };
11447
+ var frames_death1 = [
11448
+ m2(ai_move),
11449
+ m2(ai_move),
11450
+ m2(ai_move, -13),
11451
+ m2(ai_move, 14),
11452
+ m2(ai_move, 3),
11453
+ m2(ai_move, -2),
11454
+ m2(ai_move, 1)
11455
+ ];
11456
+ actor_move_death1 = {
11457
+ firstframe: FRAME_death101,
11458
+ lastframe: FRAME_death107,
11459
+ frames: frames_death1,
11460
+ endfunc: actor_dead
11461
+ };
11462
+ var frames_death2 = [
11463
+ m2(ai_move),
11464
+ m2(ai_move, 7),
11465
+ m2(ai_move, -6),
11466
+ m2(ai_move, -5),
11467
+ m2(ai_move, 1),
11468
+ m2(ai_move),
11469
+ m2(ai_move, -1),
11470
+ m2(ai_move, -2),
11471
+ m2(ai_move, -1),
11472
+ m2(ai_move, -9),
11473
+ m2(ai_move, -13),
11474
+ m2(ai_move, -13),
11475
+ m2(ai_move)
11476
+ ];
11477
+ actor_move_death2 = {
11478
+ firstframe: FRAME_death201,
11479
+ lastframe: FRAME_death213,
11480
+ frames: frames_death2,
11481
+ endfunc: actor_dead
11482
+ };
11483
+ var frames_attack = [
11484
+ m2(ai_charge, -2, actor_fire),
11485
+ m2(ai_charge, -2),
11486
+ m2(ai_charge, 3),
11487
+ m2(ai_charge, 2)
11488
+ ];
11489
+ actor_move_attack = {
11490
+ firstframe: FRAME_attak01,
11491
+ lastframe: FRAME_attak04,
11492
+ frames: frames_attack,
11493
+ endfunc: actor_run
11494
+ };
11495
+ function SP_misc_actor(self, context) {
11496
+ if (!self.targetname) {
11497
+ console.log(`${self.classname}: no targetname`);
11498
+ context.entities.free(self);
11499
+ return;
11500
+ }
11501
+ if (!self.target) {
11502
+ console.log(`${self.classname}: no target`);
11503
+ context.entities.free(self);
11504
+ return;
11505
+ }
11506
+ self.movetarget = null;
11002
11507
  self.movetype = 5 /* Step */;
11003
11508
  self.solid = 2 /* BoundingBox */;
11004
- self.health = 3e3;
11005
- self.max_health = 3e3;
11006
- self.mass = 500;
11007
- self.takedamage = true;
11008
- self.viewheight = 90;
11009
- self.pain = (ent, other, kick, dmg) => makron_pain(ent, other, kick, dmg, context.entities);
11010
- self.die = (self2, inflictor, attacker, damage, point) => {
11011
- if (self2.health <= -2e3) {
11012
- throwGibs(context.entities, self2.origin, damage);
11013
- context.entities.free(self2);
11014
- return;
11015
- }
11016
- self2.deadflag = 2 /* Dead */;
11017
- self2.solid = 0 /* Not */;
11018
- makron_die(self2, context.entities);
11019
- };
11020
- self.monsterinfo.stand = makron_stand;
11021
- self.monsterinfo.walk = makron_walk;
11022
- self.monsterinfo.run = makron_run;
11023
- self.monsterinfo.attack = makron_attack;
11024
- self.monsterinfo.sight = (self2, other) => {
11025
- context.entities.sound?.(self2, 0, "makron/sight.wav", 1, 1, 0);
11026
- self2.monsterinfo.current_move = sight_move;
11509
+ self.model = "players/male/tris.md2";
11510
+ self.mins = { x: -16, y: -16, z: -24 };
11511
+ self.maxs = { x: 16, y: 16, z: 32 };
11512
+ if (!self.health)
11513
+ self.health = 100;
11514
+ self.max_health = self.health;
11515
+ self.mass = 200;
11516
+ self.pain = actor_pain;
11517
+ self.die = actor_die;
11518
+ self.monsterinfo = {
11519
+ ...self.monsterinfo,
11520
+ // Preserve default properties like last_sighting, trail_time, pausetime
11521
+ stand: (s) => actor_stand_wrapper(s, context.entities),
11522
+ // Wrap to match signature
11523
+ walk: actor_walk,
11524
+ run: actor_run,
11525
+ attack: actor_attack,
11526
+ melee: void 0,
11527
+ sight: void 0,
11528
+ setskin: (s) => actor_setskin(s, context.entities),
11529
+ // Wrap to match signature
11530
+ aiflags: 256 /* GoodGuy */,
11531
+ scale: 1
11532
+ // MODEL_SCALE
11027
11533
  };
11028
- self.think = monster_think;
11029
- self.monsterinfo.current_move = sight_move;
11030
- self.nextthink = self.timestamp + MONSTER_TICK15;
11534
+ self.monsterinfo.context = context.entities;
11535
+ context.entities.linkentity(self);
11536
+ self.monsterinfo.current_move = actor_move_stand;
11537
+ self.think = (s) => {
11538
+ const c = s.monsterinfo.context;
11539
+ if (c) monster_think(s, c);
11540
+ };
11541
+ self.nextthink = context.entities.timeSeconds + MONSTER_TICK16;
11542
+ self.use = (self2, other, activator = null) => actor_use(self2, other, activator);
11543
+ }
11544
+ var SPAWNFLAG_TARGET_ACTOR_JUMP = 1;
11545
+ var SPAWNFLAG_TARGET_ACTOR_SHOOT = 2;
11546
+ var SPAWNFLAG_TARGET_ACTOR_ATTACK = 4;
11547
+ var SPAWNFLAG_TARGET_ACTOR_HOLD = 16;
11548
+ var SPAWNFLAG_TARGET_ACTOR_BRUTAL = 32;
11549
+ function target_actor_touch(self, other, plane, surf) {
11550
+ if (!other) return;
11551
+ const context = self.monsterinfo.context;
11552
+ if (other.movetarget !== self)
11553
+ return;
11554
+ if (other.enemy)
11555
+ return;
11556
+ other.goalentity = null;
11557
+ other.movetarget = null;
11558
+ if (self.message) {
11559
+ const name = actor_names[Math.floor(Math.random() * actor_names.length)];
11560
+ }
11561
+ if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_JUMP) {
11562
+ const v = other.velocity;
11563
+ v.x = self.movedir.x * self.speed;
11564
+ v.y = self.movedir.y * self.speed;
11565
+ if (other.groundentity) {
11566
+ other.groundentity = null;
11567
+ v.z = self.movedir.z;
11568
+ context.sound(other, 2, "player/male/jump1.wav", 1, 1, 0);
11569
+ }
11570
+ }
11571
+ if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_SHOOT) {
11572
+ } else if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_ATTACK) {
11573
+ other.enemy = context.pickTarget(self.pathtarget);
11574
+ if (other.enemy) {
11575
+ other.goalentity = other.enemy;
11576
+ if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_BRUTAL)
11577
+ other.monsterinfo.aiflags |= 512 /* Brutal */;
11578
+ if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_HOLD) {
11579
+ other.monsterinfo.aiflags |= 1 /* StandGround */;
11580
+ actor_stand(other, context);
11581
+ } else {
11582
+ actor_run(other, context);
11583
+ }
11584
+ }
11585
+ }
11586
+ if (!(self.spawnflags & (SPAWNFLAG_TARGET_ACTOR_ATTACK | SPAWNFLAG_TARGET_ACTOR_SHOOT)) && self.pathtarget) {
11587
+ const savetarget = self.target;
11588
+ self.target = self.pathtarget;
11589
+ context.useTargets(self, other);
11590
+ self.target = savetarget;
11591
+ }
11592
+ other.movetarget = context.pickTarget(self.target);
11593
+ if (!other.goalentity)
11594
+ other.goalentity = other.movetarget;
11595
+ if (!other.movetarget && !other.enemy) {
11596
+ other.monsterinfo.pausetime = 1e8;
11597
+ if (other.monsterinfo.stand) other.monsterinfo.stand(other, context);
11598
+ } else if (other.movetarget === other.goalentity && other.movetarget) {
11599
+ const v = subtractVec3(other.movetarget.origin, other.origin);
11600
+ other.ideal_yaw = vectorToYaw(v);
11601
+ }
11031
11602
  }
11032
- function registerMakronSpawns(registry) {
11033
- registry.register("monster_makron", SP_monster_makron);
11603
+ function SP_target_actor(self, context) {
11604
+ if (!self.targetname)
11605
+ console.log(`${self.classname}: no targetname`);
11606
+ self.solid = 1 /* Trigger */;
11607
+ self.touch = target_actor_touch;
11608
+ self.mins = { x: -8, y: -8, z: -8 };
11609
+ self.maxs = { x: 8, y: 8, z: 8 };
11610
+ self.svflags = 1 << 6;
11611
+ self.monsterinfo = {
11612
+ ...self.monsterinfo
11613
+ };
11614
+ self.monsterinfo.context = context.entities;
11615
+ if (self.spawnflags & SPAWNFLAG_TARGET_ACTOR_JUMP) {
11616
+ if (!self.speed)
11617
+ self.speed = 200;
11618
+ const height = self.height || 200;
11619
+ if (self.angles.y === 0)
11620
+ self.angles.y = 360;
11621
+ const dir = setMovedir(self.angles);
11622
+ dir.z = height;
11623
+ self.movedir = dir;
11624
+ }
11625
+ context.entities.linkentity(self);
11626
+ }
11627
+ function registerActorSpawns(registry) {
11628
+ registry.register("misc_actor", SP_misc_actor);
11629
+ registry.register("target_actor", SP_target_actor);
11034
11630
  }
11035
11631
 
11036
11632
  // src/entities/monsters/medic.ts
11037
- var MONSTER_TICK16 = 0.1;
11633
+ var MONSTER_TICK17 = 0.1;
11038
11634
  function monster_ai_stand15(self, dist, context) {
11039
11635
  if (self.classname === "monster_medic") {
11040
11636
  if (medic_find_dead(self, context)) {
@@ -11042,24 +11638,24 @@ function monster_ai_stand15(self, dist, context) {
11042
11638
  return;
11043
11639
  }
11044
11640
  }
11045
- ai_stand(self, MONSTER_TICK16, context);
11641
+ ai_stand(self, MONSTER_TICK17, context);
11046
11642
  }
11047
11643
  function monster_ai_walk15(self, dist, context) {
11048
- ai_walk(self, dist, MONSTER_TICK16, context);
11644
+ ai_walk(self, dist, MONSTER_TICK17, context);
11049
11645
  }
11050
11646
  function monster_ai_run14(self, dist, context) {
11051
11647
  if (self.classname === "monster_medic") {
11052
11648
  if (medic_find_dead(self, context)) {
11053
11649
  self.monsterinfo.current_move = run_move13;
11054
11650
  } else {
11055
- ai_run(self, dist, MONSTER_TICK16, context);
11651
+ ai_run(self, dist, MONSTER_TICK17, context);
11056
11652
  }
11057
11653
  } else {
11058
- ai_run(self, dist, MONSTER_TICK16, context);
11654
+ ai_run(self, dist, MONSTER_TICK17, context);
11059
11655
  }
11060
11656
  }
11061
11657
  function monster_ai_charge15(self, dist, context) {
11062
- ai_charge(self, dist, MONSTER_TICK16, context);
11658
+ ai_charge(self, dist, MONSTER_TICK17, context);
11063
11659
  }
11064
11660
  function monster_ai_move15(self, dist, context) {
11065
11661
  ai_move(self, dist);
@@ -11395,7 +11991,7 @@ function SP_monster_medic(self, context) {
11395
11991
  self.monsterinfo.attack = medic_attack;
11396
11992
  self.think = monster_think;
11397
11993
  medic_stand(self);
11398
- self.nextthink = self.timestamp + MONSTER_TICK16;
11994
+ self.nextthink = self.timestamp + MONSTER_TICK17;
11399
11995
  }
11400
11996
  function SP_monster_medic_commander(self, context) {
11401
11997
  SP_monster_medic(self, context);
@@ -11410,25 +12006,25 @@ function registerMedicSpawns(registry) {
11410
12006
  }
11411
12007
 
11412
12008
  // src/entities/monsters/mutant.ts
11413
- var MONSTER_TICK17 = 0.1;
12009
+ var MONSTER_TICK18 = 0.1;
11414
12010
  var random6 = () => Math.random();
11415
12011
  function monster_ai_stand16(self, dist, context) {
11416
- ai_stand(self, MONSTER_TICK17, context);
12012
+ ai_stand(self, MONSTER_TICK18, context);
11417
12013
  }
11418
12014
  function monster_ai_walk16(self, dist, context) {
11419
- ai_walk(self, dist, MONSTER_TICK17, context);
12015
+ ai_walk(self, dist, MONSTER_TICK18, context);
11420
12016
  }
11421
12017
  function monster_ai_run15(self, dist, context) {
11422
- ai_run(self, dist, MONSTER_TICK17, context);
12018
+ ai_run(self, dist, MONSTER_TICK18, context);
11423
12019
  }
11424
12020
  function monster_ai_charge16(self, dist, context) {
11425
- ai_charge(self, dist, MONSTER_TICK17, context);
12021
+ ai_charge(self, dist, MONSTER_TICK18, context);
11426
12022
  }
11427
12023
  function monster_ai_move16(self, dist, context) {
11428
12024
  ai_move(self, dist);
11429
12025
  }
11430
12026
  function monster_ai_face(self, dist, context) {
11431
- ai_face(self, null, dist, MONSTER_TICK17);
12027
+ ai_face(self, null, dist, MONSTER_TICK18);
11432
12028
  }
11433
12029
  var stand_move15;
11434
12030
  var walk_move14;
@@ -11792,26 +12388,26 @@ function SP_monster_mutant(self, context) {
11792
12388
  self.monsterinfo.idle = mutant_stand;
11793
12389
  self.think = monster_think;
11794
12390
  mutant_stand(self);
11795
- self.nextthink = self.timestamp + MONSTER_TICK17;
12391
+ self.nextthink = self.timestamp + MONSTER_TICK18;
11796
12392
  }
11797
12393
  function registerMutantSpawns(registry) {
11798
12394
  registry.register("monster_mutant", SP_monster_mutant);
11799
12395
  }
11800
12396
 
11801
12397
  // src/entities/monsters/parasite.ts
11802
- var MONSTER_TICK18 = 0.1;
12398
+ var MONSTER_TICK19 = 0.1;
11803
12399
  var random7 = () => Math.random();
11804
12400
  function monster_ai_stand17(self, dist, context) {
11805
- ai_stand(self, MONSTER_TICK18, context);
12401
+ ai_stand(self, MONSTER_TICK19, context);
11806
12402
  }
11807
12403
  function monster_ai_walk17(self, dist, context) {
11808
- ai_walk(self, dist, MONSTER_TICK18, context);
12404
+ ai_walk(self, dist, MONSTER_TICK19, context);
11809
12405
  }
11810
12406
  function monster_ai_run16(self, dist, context) {
11811
- ai_run(self, dist, MONSTER_TICK18, context);
12407
+ ai_run(self, dist, MONSTER_TICK19, context);
11812
12408
  }
11813
12409
  function monster_ai_charge17(self, dist, context) {
11814
- ai_charge(self, dist, MONSTER_TICK18, context);
12410
+ ai_charge(self, dist, MONSTER_TICK19, context);
11815
12411
  }
11816
12412
  function monster_ai_move17(self, dist, context) {
11817
12413
  ai_move(self, dist);
@@ -12188,28 +12784,28 @@ function SP_monster_parasite(self, context) {
12188
12784
  self.monsterinfo.idle = parasite_idle;
12189
12785
  self.think = monster_think;
12190
12786
  parasite_stand(self);
12191
- self.nextthink = self.timestamp + MONSTER_TICK18;
12787
+ self.nextthink = self.timestamp + MONSTER_TICK19;
12192
12788
  }
12193
12789
  function registerParasiteSpawns(registry) {
12194
12790
  registry.register("monster_parasite", SP_monster_parasite);
12195
12791
  }
12196
12792
 
12197
12793
  // src/entities/monsters/soldier.ts
12198
- var MONSTER_TICK19 = 0.1;
12794
+ var MONSTER_TICK20 = 0.1;
12199
12795
  var SOLDIER_LIGHT = 1;
12200
12796
  var SOLDIER_SSG = 2;
12201
12797
  var SOLDIER_MACHINEGUN = 4;
12202
12798
  function monster_ai_stand18(self, dist, context) {
12203
- ai_stand(self, MONSTER_TICK19, context);
12799
+ ai_stand(self, MONSTER_TICK20, context);
12204
12800
  }
12205
12801
  function monster_ai_walk18(self, dist, context) {
12206
- ai_walk(self, dist, MONSTER_TICK19, context);
12802
+ ai_walk(self, dist, MONSTER_TICK20, context);
12207
12803
  }
12208
12804
  function monster_ai_run17(self, dist, context) {
12209
- ai_run(self, dist, MONSTER_TICK19, context);
12805
+ ai_run(self, dist, MONSTER_TICK20, context);
12210
12806
  }
12211
12807
  function monster_ai_charge18(self, dist, context) {
12212
- ai_charge(self, dist, MONSTER_TICK19, context);
12808
+ ai_charge(self, dist, MONSTER_TICK20, context);
12213
12809
  }
12214
12810
  function monster_ai_move18(self, dist, context) {
12215
12811
  ai_move(self, dist);
@@ -12493,7 +13089,7 @@ function SP_monster_soldier(self, context) {
12493
13089
  };
12494
13090
  self.think = monster_think;
12495
13091
  soldier_stand(self);
12496
- self.nextthink = self.timestamp + MONSTER_TICK19;
13092
+ self.nextthink = self.timestamp + MONSTER_TICK20;
12497
13093
  }
12498
13094
  function SP_monster_soldier_light(self, context) {
12499
13095
  self.spawnflags |= SOLDIER_LIGHT;
@@ -12533,12 +13129,12 @@ function registerMonsterSpawns(registry) {
12533
13129
  }
12534
13130
 
12535
13131
  // src/entities/monsters/supertank.ts
12536
- var MONSTER_TICK20 = 0.1;
13132
+ var MONSTER_TICK21 = 0.1;
12537
13133
  var SUPERTANK_MACHINEGUN_OFFSET = { x: 30, y: 30, z: 40 };
12538
13134
  var SUPERTANK_ROCKET_OFFSET = { x: 30, y: -30, z: 40 };
12539
13135
  var SUPERTANK_GRENADE_OFFSET = { x: 20, y: 0, z: 70 };
12540
13136
  function monster_ai_stand19(self, dist, context) {
12541
- ai_stand(self, MONSTER_TICK20, context);
13137
+ ai_stand(self, MONSTER_TICK21, context);
12542
13138
  }
12543
13139
  function monster_ai_run18(self, dist, context) {
12544
13140
  if (self.enemy && self.enemy.health > 0) {
@@ -12548,7 +13144,7 @@ function monster_ai_run18(self, dist, context) {
12548
13144
  }
12549
13145
  }
12550
13146
  function monster_ai_charge19(self, dist, context) {
12551
- ai_charge(self, dist, MONSTER_TICK20, context);
13147
+ ai_charge(self, dist, MONSTER_TICK21, context);
12552
13148
  }
12553
13149
  function monster_ai_move19(self, dist, context) {
12554
13150
  ai_move(self, dist);
@@ -12744,7 +13340,7 @@ function SP_monster_supertank(self, context) {
12744
13340
  };
12745
13341
  self.think = monster_think;
12746
13342
  supertank_stand(self);
12747
- self.nextthink = self.timestamp + MONSTER_TICK20;
13343
+ self.nextthink = self.timestamp + MONSTER_TICK21;
12748
13344
  }
12749
13345
  function registerSupertankSpawns(registry) {
12750
13346
  registry.register("monster_supertank", SP_monster_supertank);
@@ -12757,7 +13353,7 @@ function registerSupertankSpawns(registry) {
12757
13353
  }
12758
13354
 
12759
13355
  // src/entities/monsters/tank.ts
12760
- var MONSTER_TICK21 = 0.1;
13356
+ var MONSTER_TICK22 = 0.1;
12761
13357
  function M_AdjustBlindfireTarget(self, start, target, right, context) {
12762
13358
  const tr = context.trace(start, target, ZERO_VEC3, ZERO_VEC3, self, MASK_SHOT);
12763
13359
  if (!tr.startsolid && !tr.allsolid && tr.fraction >= 0.5) {
@@ -12784,10 +13380,10 @@ function tank_blind_check(self, context) {
12784
13380
  }
12785
13381
  }
12786
13382
  function monster_ai_stand20(self, dist, context) {
12787
- ai_stand(self, MONSTER_TICK21, context);
13383
+ ai_stand(self, MONSTER_TICK22, context);
12788
13384
  }
12789
13385
  function monster_ai_walk19(self, dist, context) {
12790
- ai_walk(self, dist, MONSTER_TICK21, context);
13386
+ ai_walk(self, dist, MONSTER_TICK22, context);
12791
13387
  }
12792
13388
  function monster_ai_run19(self, dist, context) {
12793
13389
  if (self.enemy && self.enemy.health > 0) {
@@ -12797,7 +13393,7 @@ function monster_ai_run19(self, dist, context) {
12797
13393
  }
12798
13394
  }
12799
13395
  function monster_ai_charge20(self, dist, context) {
12800
- ai_charge(self, dist, MONSTER_TICK21, context);
13396
+ ai_charge(self, dist, MONSTER_TICK22, context);
12801
13397
  }
12802
13398
  function monster_ai_move20(self, dist, context) {
12803
13399
  ai_move(self, dist);
@@ -13108,7 +13704,7 @@ function SP_monster_tank(self, context) {
13108
13704
  self.monsterinfo.blindfire = true;
13109
13705
  self.think = monster_think;
13110
13706
  tank_stand(self);
13111
- self.nextthink = self.timestamp + MONSTER_TICK21;
13707
+ self.nextthink = self.timestamp + MONSTER_TICK22;
13112
13708
  }
13113
13709
  function registerTankSpawns(registry) {
13114
13710
  registry.register("monster_tank", SP_monster_tank);
@@ -13127,15 +13723,15 @@ function registerTankCommanderSpawns(registry) {
13127
13723
  }
13128
13724
 
13129
13725
  // src/entities/monsters/turret.ts
13130
- var MONSTER_TICK22 = 0.1;
13726
+ var MONSTER_TICK23 = 0.1;
13131
13727
  function monster_ai_stand21(self, dist, context) {
13132
- ai_stand(self, MONSTER_TICK22, context);
13728
+ ai_stand(self, MONSTER_TICK23, context);
13133
13729
  }
13134
13730
  function monster_ai_run20(self, dist, context) {
13135
- ai_run(self, dist, MONSTER_TICK22, context);
13731
+ ai_run(self, dist, MONSTER_TICK23, context);
13136
13732
  }
13137
13733
  function monster_ai_charge21(self, dist, context) {
13138
- ai_charge(self, dist, MONSTER_TICK22, context);
13734
+ ai_charge(self, dist, MONSTER_TICK23, context);
13139
13735
  }
13140
13736
  var stand_move20;
13141
13737
  var run_move19;
@@ -13271,7 +13867,7 @@ function SP_monster_turret(self, context) {
13271
13867
  };
13272
13868
  self.think = monster_think;
13273
13869
  turret_stand(self);
13274
- self.nextthink = self.timestamp + MONSTER_TICK22;
13870
+ self.nextthink = self.timestamp + MONSTER_TICK23;
13275
13871
  }
13276
13872
  function registerTurretSpawns(registry) {
13277
13873
  registry.register("monster_turret", SP_monster_turret);
@@ -13302,6 +13898,7 @@ function registerMonsterSpawns2(registry) {
13302
13898
  registerJorgSpawns(registry);
13303
13899
  registerMakronSpawns(registry);
13304
13900
  registerInsaneSpawns(registry);
13901
+ registerActorSpawns(registry);
13305
13902
  }
13306
13903
 
13307
13904
  // src/entities/worldspawn.ts
@@ -14749,7 +15346,97 @@ function ClientObituary(self, inflictor, attacker, mod, sys) {
14749
15346
  }
14750
15347
  }
14751
15348
 
15349
+ // src/entities/player_anim.ts
15350
+ var FRAME_stand01 = 0;
15351
+ var FRAME_stand402 = 39;
15352
+ var FRAME_run1 = 40;
15353
+ var FRAME_run6 = 45;
15354
+ var FRAME_pain1012 = 54;
15355
+ var FRAME_pain104 = 57;
15356
+ var FRAME_pain2012 = 58;
15357
+ var FRAME_pain204 = 61;
15358
+ var FRAME_pain3012 = 62;
15359
+ var FRAME_pain304 = 65;
15360
+ var FRAME_death1012 = 66;
15361
+ var FRAME_death106 = 71;
15362
+ var FRAME_death2012 = 72;
15363
+ var FRAME_death206 = 77;
15364
+ var FRAME_death301 = 78;
15365
+ var FRAME_death306 = 83;
15366
+ var ANIM_BASIC = 0;
15367
+ var ANIM_PAIN = 2;
15368
+ var ANIM_DEATH = 3;
15369
+
15370
+ // src/combat/weapons/firing.ts
15371
+ var random9 = createRandomGenerator();
15372
+
14752
15373
  // src/entities/player.ts
15374
+ function P_PlayerThink(ent, sys) {
15375
+ if (!ent.client) return;
15376
+ const client = ent.client;
15377
+ let animChanged = false;
15378
+ if (ent.deadflag) {
15379
+ } else {
15380
+ const speed = Math.sqrt(ent.velocity.x * ent.velocity.x + ent.velocity.y * ent.velocity.y);
15381
+ const moving = speed > 10;
15382
+ if (client.anim_priority === ANIM_BASIC || client.anim_priority === void 0) {
15383
+ if (moving) {
15384
+ if (ent.frame < FRAME_run1 || ent.frame > FRAME_run6) {
15385
+ ent.frame = FRAME_run1;
15386
+ client.anim_end = FRAME_run6;
15387
+ client.anim_priority = ANIM_BASIC;
15388
+ animChanged = true;
15389
+ }
15390
+ } else {
15391
+ if (ent.frame >= FRAME_run1 && ent.frame <= FRAME_run6 || client.anim_priority === ANIM_BASIC && client.anim_end !== FRAME_stand402 || client.anim_priority === void 0) {
15392
+ ent.frame = FRAME_stand01;
15393
+ client.anim_end = FRAME_stand402;
15394
+ client.anim_priority = ANIM_BASIC;
15395
+ animChanged = true;
15396
+ }
15397
+ }
15398
+ }
15399
+ }
15400
+ if (animChanged) {
15401
+ return;
15402
+ }
15403
+ if (client.anim_end !== void 0 && client.anim_end !== ent.frame) {
15404
+ if (ent.frame < client.anim_end) {
15405
+ ent.frame++;
15406
+ } else if (ent.frame > client.anim_end) {
15407
+ ent.frame--;
15408
+ }
15409
+ } else if (client.anim_end === ent.frame) {
15410
+ if (client.anim_priority === ANIM_BASIC) {
15411
+ if (ent.frame === FRAME_run6) ent.frame = FRAME_run1;
15412
+ else if (ent.frame === FRAME_stand402) ent.frame = FRAME_stand01;
15413
+ } else {
15414
+ if (client.anim_priority !== ANIM_DEATH) {
15415
+ client.anim_priority = ANIM_BASIC;
15416
+ }
15417
+ }
15418
+ }
15419
+ }
15420
+ function player_pain(self, damage) {
15421
+ if (!self.client) return;
15422
+ if (self.health < 40) {
15423
+ }
15424
+ if (self.client.anim_priority && self.client.anim_priority >= ANIM_PAIN) {
15425
+ return;
15426
+ }
15427
+ self.client.anim_priority = ANIM_PAIN;
15428
+ const r = random9.frandom();
15429
+ if (r < 0.33) {
15430
+ self.frame = FRAME_pain1012;
15431
+ self.client.anim_end = FRAME_pain104;
15432
+ } else if (r < 0.66) {
15433
+ self.frame = FRAME_pain2012;
15434
+ self.client.anim_end = FRAME_pain204;
15435
+ } else {
15436
+ self.frame = FRAME_pain3012;
15437
+ self.client.anim_end = FRAME_pain304;
15438
+ }
15439
+ }
14753
15440
  function player_die(self, inflictor, attacker, damage, point, mod, sys) {
14754
15441
  self.deadflag = 2 /* Dead */;
14755
15442
  self.solid = 0 /* Not */;
@@ -14757,8 +15444,24 @@ function player_die(self, inflictor, attacker, damage, point, mod, sys) {
14757
15444
  self.takedamage = false;
14758
15445
  if (self.health < -40 && sys) {
14759
15446
  throwGibs(sys, self.origin, damage);
15447
+ return;
15448
+ }
15449
+ if (self.client) {
15450
+ self.client.anim_priority = ANIM_DEATH;
15451
+ const r = random9.frandom();
15452
+ if (r < 0.33) {
15453
+ self.frame = FRAME_death1012;
15454
+ self.client.anim_end = FRAME_death106;
15455
+ } else if (r < 0.66) {
15456
+ self.frame = FRAME_death2012;
15457
+ self.client.anim_end = FRAME_death206;
15458
+ } else {
15459
+ self.frame = FRAME_death301;
15460
+ self.client.anim_end = FRAME_death306;
15461
+ }
15462
+ } else {
15463
+ self.frame = 0;
14760
15464
  }
14761
- self.frame = 0;
14762
15465
  if (sys) {
14763
15466
  ClientObituary(self, inflictor, attacker, mod, sys);
14764
15467
  }
@@ -14792,6 +15495,7 @@ function player_think(self, sys) {
14792
15495
  weaponItem.think(self, sys);
14793
15496
  }
14794
15497
  }
15498
+ P_PlayerThink(self, sys);
14795
15499
  self.nextthink = sys.timeSeconds + 0.1;
14796
15500
  sys.scheduleThink(self, self.nextthink);
14797
15501
  }
@@ -15138,7 +15842,7 @@ var WEAPONS = {
15138
15842
  };
15139
15843
 
15140
15844
  // src/index.ts
15141
- var ZERO_VEC37 = { x: 0, y: 0, z: 0 };
15845
+ var ZERO_VEC36 = { x: 0, y: 0, z: 0 };
15142
15846
  function createGame(imports, engine, options) {
15143
15847
  const gravity = options.gravity;
15144
15848
  const deathmatch = options.deathmatch ?? false;
@@ -15207,8 +15911,8 @@ function createGame(imports, engine, options) {
15207
15911
  };
15208
15912
  entities.runFrame();
15209
15913
  });
15210
- let origin = { ...ZERO_VEC37 };
15211
- let velocity = { ...ZERO_VEC37 };
15914
+ let origin = { ...ZERO_VEC36 };
15915
+ let velocity = { ...ZERO_VEC36 };
15212
15916
  const calculateBlend = (player, time) => {
15213
15917
  const blend = [0, 0, 0, 0];
15214
15918
  if (!player || !player.client) return blend;
@@ -15290,10 +15994,10 @@ function createGame(imports, engine, options) {
15290
15994
  // TODO
15291
15995
  damageIndicators: [],
15292
15996
  stats: player ? populatePlayerStats(player, levelClock.current.timeSeconds) : [],
15293
- kick_angles: player?.client?.kick_angles ?? ZERO_VEC37,
15294
- kick_origin: player?.client?.kick_origin ?? ZERO_VEC37,
15295
- gunoffset: ZERO_VEC37,
15296
- gunangles: ZERO_VEC37,
15997
+ kick_angles: player?.client?.kick_angles ?? ZERO_VEC36,
15998
+ kick_origin: player?.client?.kick_origin ?? ZERO_VEC36,
15999
+ gunoffset: ZERO_VEC36,
16000
+ gunangles: ZERO_VEC36,
15297
16001
  gunindex: 0,
15298
16002
  gun_frame: player?.client?.gun_frame ?? 0,
15299
16003
  rdflags: player?.client?.rdflags ?? 0,
@@ -15307,8 +16011,8 @@ function createGame(imports, engine, options) {
15307
16011
  const resetState = (startTimeMs) => {
15308
16012
  frameLoop.reset(startTimeMs);
15309
16013
  levelClock.start(startTimeMs);
15310
- origin = { ...ZERO_VEC37 };
15311
- velocity = { ...ZERO_VEC37 };
16014
+ origin = { ...ZERO_VEC36 };
16015
+ velocity = { ...ZERO_VEC36 };
15312
16016
  entities.beginFrame(startTimeMs / 1e3);
15313
16017
  entities.runFrame();
15314
16018
  };
@@ -15336,10 +16040,10 @@ function createGame(imports, engine, options) {
15336
16040
  blend: [0, 0, 0, 0],
15337
16041
  // Stubs
15338
16042
  stats: populatePlayerStats(player, levelClock.current.timeSeconds),
15339
- kick_angles: ZERO_VEC37,
15340
- kick_origin: ZERO_VEC37,
15341
- gunoffset: ZERO_VEC37,
15342
- gunangles: ZERO_VEC37,
16043
+ kick_angles: ZERO_VEC36,
16044
+ kick_origin: ZERO_VEC36,
16045
+ gunoffset: ZERO_VEC36,
16046
+ gunangles: ZERO_VEC36,
15343
16047
  gunindex: 0,
15344
16048
  pm_type: 0,
15345
16049
  pm_time: 0,
@@ -15397,6 +16101,9 @@ function createGame(imports, engine, options) {
15397
16101
  player.die = (self, inflictor, attacker, damage, point, mod) => {
15398
16102
  player_die(self, inflictor, attacker, damage, point, mod, entities);
15399
16103
  };
16104
+ player.pain = (self, other, kick, damage) => {
16105
+ player_pain(self, damage);
16106
+ };
15400
16107
  player.think = (self) => {
15401
16108
  player_think(self, entities);
15402
16109
  };
@@ -15466,8 +16173,8 @@ function createGame(imports, engine, options) {
15466
16173
  rng,
15467
16174
  player: player?.client?.inventory
15468
16175
  });
15469
- origin = player ? { ...player.origin } : { ...ZERO_VEC37 };
15470
- velocity = player ? { ...player.velocity } : { ...ZERO_VEC37 };
16176
+ origin = player ? { ...player.origin } : { ...ZERO_VEC36 };
16177
+ velocity = player ? { ...player.velocity } : { ...ZERO_VEC36 };
15471
16178
  frameLoop.reset(save.level.timeSeconds * 1e3);
15472
16179
  }
15473
16180
  };