quake2ts 0.0.270 → 0.0.275
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.
- package/package.json +1 -1
- package/packages/cgame/dist/index.cjs +29 -5
- package/packages/cgame/dist/index.cjs.map +1 -1
- package/packages/cgame/dist/index.js +30 -6
- package/packages/cgame/dist/index.js.map +1 -1
- package/packages/client/dist/browser/index.global.js +13 -13
- package/packages/client/dist/browser/index.global.js.map +1 -1
- package/packages/client/dist/cjs/index.cjs.map +1 -1
- package/packages/client/dist/esm/index.js.map +1 -1
- package/packages/client/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/engine/dist/browser/index.global.js +6 -6
- package/packages/engine/dist/browser/index.global.js.map +1 -1
- package/packages/engine/dist/cjs/index.cjs.map +1 -1
- package/packages/engine/dist/esm/index.js.map +1 -1
- package/packages/engine/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/game/dist/browser/index.global.js +3 -3
- package/packages/game/dist/browser/index.global.js.map +1 -1
- package/packages/game/dist/cjs/index.cjs +1170 -120
- package/packages/game/dist/cjs/index.cjs.map +1 -1
- package/packages/game/dist/esm/index.js +1170 -120
- package/packages/game/dist/esm/index.js.map +1 -1
- package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/game/dist/types/entities/entity.d.ts +2 -0
- package/packages/game/dist/types/entities/entity.d.ts.map +1 -1
- package/packages/game/dist/types/entities/monsters/fixbot.d.ts +5 -0
- package/packages/game/dist/types/entities/monsters/fixbot.d.ts.map +1 -0
- package/packages/game/dist/types/entities/monsters/gekk.d.ts +5 -0
- package/packages/game/dist/types/entities/monsters/gekk.d.ts.map +1 -0
- package/packages/game/dist/types/entities/monsters/index.d.ts.map +1 -1
- package/packages/game/dist/types/entities/playerStats.d.ts.map +1 -1
- package/packages/game/dist/types/entities/system.d.ts.map +1 -1
- package/packages/game/dist/types/entities/targets.d.ts.map +1 -1
- package/packages/game/dist/types/inventory/playerInventory.d.ts +5 -48
- package/packages/game/dist/types/inventory/playerInventory.d.ts.map +1 -1
- package/packages/server/dist/index.cjs +73 -5
- package/packages/server/dist/index.js +73 -5
- package/packages/shared/dist/browser/index.global.js +1 -1
- package/packages/shared/dist/browser/index.global.js.map +1 -1
- package/packages/shared/dist/cjs/index.cjs +47 -4
- package/packages/shared/dist/cjs/index.cjs.map +1 -1
- package/packages/shared/dist/esm/index.js +45 -4
- package/packages/shared/dist/esm/index.js.map +1 -1
- package/packages/shared/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/shared/dist/types/items/index.d.ts +1 -0
- package/packages/shared/dist/types/items/index.d.ts.map +1 -1
- package/packages/shared/dist/types/items/weaponInfo.d.ts +5 -0
- package/packages/shared/dist/types/items/weaponInfo.d.ts.map +1 -0
- package/packages/shared/dist/types/items/weapons.d.ts +8 -7
- package/packages/shared/dist/types/items/weapons.d.ts.map +1 -1
- package/packages/tools/dist/tsconfig.tsbuildinfo +1 -1
|
@@ -767,6 +767,33 @@ function setCompressedInteger(stats, startIndex, id, count, bitsPerValue) {
|
|
|
767
767
|
const valueToWrite = base & ~mask | count << bitShift & mask;
|
|
768
768
|
writeUint16LE(stats, startIndex, byteOffset, valueToWrite & 65535);
|
|
769
769
|
}
|
|
770
|
+
var PowerupId = /* @__PURE__ */ ((PowerupId22) => {
|
|
771
|
+
PowerupId22["QuadDamage"] = "quad";
|
|
772
|
+
PowerupId22["Invulnerability"] = "invulnerability";
|
|
773
|
+
PowerupId22["EnviroSuit"] = "enviro_suit";
|
|
774
|
+
PowerupId22["Rebreather"] = "rebreather";
|
|
775
|
+
PowerupId22["Silencer"] = "silencer";
|
|
776
|
+
PowerupId22["PowerScreen"] = "power_screen";
|
|
777
|
+
PowerupId22["PowerShield"] = "power_shield";
|
|
778
|
+
PowerupId22["QuadFire"] = "quad_fire";
|
|
779
|
+
PowerupId22["Invisibility"] = "invisibility";
|
|
780
|
+
PowerupId22["Bandolier"] = "bandolier";
|
|
781
|
+
PowerupId22["AmmoPack"] = "ammo_pack";
|
|
782
|
+
PowerupId22["IRGoggles"] = "ir_goggles";
|
|
783
|
+
PowerupId22["DoubleDamage"] = "double_damage";
|
|
784
|
+
PowerupId22["SphereVengeance"] = "sphere_vengeance";
|
|
785
|
+
PowerupId22["SphereHunter"] = "sphere_hunter";
|
|
786
|
+
PowerupId22["SphereDefender"] = "sphere_defender";
|
|
787
|
+
PowerupId22["Doppelganger"] = "doppelganger";
|
|
788
|
+
PowerupId22["TagToken"] = "tag_token";
|
|
789
|
+
PowerupId22["TechResistance"] = "tech_resistance";
|
|
790
|
+
PowerupId22["TechStrength"] = "tech_strength";
|
|
791
|
+
PowerupId22["TechHaste"] = "tech_haste";
|
|
792
|
+
PowerupId22["TechRegeneration"] = "tech_regeneration";
|
|
793
|
+
PowerupId22["Flashlight"] = "flashlight";
|
|
794
|
+
PowerupId22["Compass"] = "compass";
|
|
795
|
+
return PowerupId22;
|
|
796
|
+
})(PowerupId || {});
|
|
770
797
|
var PlayerStat = /* @__PURE__ */ ((PlayerStat2) => {
|
|
771
798
|
PlayerStat2[PlayerStat2["STAT_HEALTH_ICON"] = 0] = "STAT_HEALTH_ICON";
|
|
772
799
|
PlayerStat2[PlayerStat2["STAT_HEALTH"] = 1] = "STAT_HEALTH";
|
|
@@ -1081,6 +1108,29 @@ var applyPmove = (state, cmd, trace, pointContents2) => {
|
|
|
1081
1108
|
velocity: finalVelocity
|
|
1082
1109
|
};
|
|
1083
1110
|
};
|
|
1111
|
+
var WeaponId = /* @__PURE__ */ ((WeaponId22) => {
|
|
1112
|
+
WeaponId22["Blaster"] = "blaster";
|
|
1113
|
+
WeaponId22["Shotgun"] = "shotgun";
|
|
1114
|
+
WeaponId22["SuperShotgun"] = "supershotgun";
|
|
1115
|
+
WeaponId22["Machinegun"] = "machinegun";
|
|
1116
|
+
WeaponId22["Chaingun"] = "chaingun";
|
|
1117
|
+
WeaponId22["HandGrenade"] = "grenades";
|
|
1118
|
+
WeaponId22["GrenadeLauncher"] = "grenadelauncher";
|
|
1119
|
+
WeaponId22["RocketLauncher"] = "rocketlauncher";
|
|
1120
|
+
WeaponId22["HyperBlaster"] = "hyperblaster";
|
|
1121
|
+
WeaponId22["Railgun"] = "railgun";
|
|
1122
|
+
WeaponId22["BFG10K"] = "bfg10k";
|
|
1123
|
+
WeaponId22["Grapple"] = "grapple";
|
|
1124
|
+
WeaponId22["ChainFist"] = "chainfist";
|
|
1125
|
+
WeaponId22["EtfRifle"] = "etf_rifle";
|
|
1126
|
+
WeaponId22["ProxLauncher"] = "prox_launcher";
|
|
1127
|
+
WeaponId22["IonRipper"] = "ionripper";
|
|
1128
|
+
WeaponId22["PlasmaBeam"] = "plasmabeam";
|
|
1129
|
+
WeaponId22["Phalanx"] = "phalanx";
|
|
1130
|
+
WeaponId22["Disruptor"] = "disruptor";
|
|
1131
|
+
WeaponId22["Trap"] = "trap";
|
|
1132
|
+
return WeaponId22;
|
|
1133
|
+
})(WeaponId || {});
|
|
1084
1134
|
var AmmoType = /* @__PURE__ */ ((AmmoType22) => {
|
|
1085
1135
|
AmmoType22[AmmoType22["Bullets"] = 0] = "Bullets";
|
|
1086
1136
|
AmmoType22[AmmoType22["Shells"] = 1] = "Shells";
|
|
@@ -1114,6 +1164,20 @@ var AmmoItemId = /* @__PURE__ */ ((AmmoItemId22) => {
|
|
|
1114
1164
|
AmmoItemId22["Prox"] = "ammo_prox";
|
|
1115
1165
|
return AmmoItemId22;
|
|
1116
1166
|
})(AmmoItemId || {});
|
|
1167
|
+
var WEAPON_WHEEL_ORDER = [
|
|
1168
|
+
"blaster",
|
|
1169
|
+
"shotgun",
|
|
1170
|
+
"supershotgun",
|
|
1171
|
+
"machinegun",
|
|
1172
|
+
"chaingun",
|
|
1173
|
+
"grenadelauncher",
|
|
1174
|
+
"rocketlauncher",
|
|
1175
|
+
"grenades",
|
|
1176
|
+
"hyperblaster",
|
|
1177
|
+
"railgun",
|
|
1178
|
+
"bfg10k"
|
|
1179
|
+
/* BFG10K */
|
|
1180
|
+
];
|
|
1117
1181
|
|
|
1118
1182
|
// src/inventory/ammo.ts
|
|
1119
1183
|
var AMMO_ITEM_DEFINITIONS = {
|
|
@@ -1296,54 +1360,6 @@ function applyPowerArmor(damage, flags, hitPoint, _hitNormal, state, options = {
|
|
|
1296
1360
|
}
|
|
1297
1361
|
|
|
1298
1362
|
// src/inventory/playerInventory.ts
|
|
1299
|
-
var WeaponId = /* @__PURE__ */ ((WeaponId3) => {
|
|
1300
|
-
WeaponId3["Blaster"] = "blaster";
|
|
1301
|
-
WeaponId3["Shotgun"] = "shotgun";
|
|
1302
|
-
WeaponId3["SuperShotgun"] = "supershotgun";
|
|
1303
|
-
WeaponId3["Machinegun"] = "machinegun";
|
|
1304
|
-
WeaponId3["Chaingun"] = "chaingun";
|
|
1305
|
-
WeaponId3["GrenadeLauncher"] = "grenadelauncher";
|
|
1306
|
-
WeaponId3["RocketLauncher"] = "rocketlauncher";
|
|
1307
|
-
WeaponId3["HyperBlaster"] = "hyperblaster";
|
|
1308
|
-
WeaponId3["Railgun"] = "railgun";
|
|
1309
|
-
WeaponId3["BFG10K"] = "bfg10k";
|
|
1310
|
-
WeaponId3["HandGrenade"] = "grenades";
|
|
1311
|
-
WeaponId3["Grapple"] = "grapple";
|
|
1312
|
-
WeaponId3["IonRipper"] = "ionripper";
|
|
1313
|
-
WeaponId3["Phalanx"] = "phalanx";
|
|
1314
|
-
WeaponId3["Trap"] = "trap";
|
|
1315
|
-
WeaponId3["PlasmaBeam"] = "plasmabeam";
|
|
1316
|
-
WeaponId3["EtfRifle"] = "etfrifle";
|
|
1317
|
-
WeaponId3["ProxLauncher"] = "proxlauncher";
|
|
1318
|
-
WeaponId3["ChainFist"] = "chainfist";
|
|
1319
|
-
WeaponId3["Disruptor"] = "disruptor";
|
|
1320
|
-
return WeaponId3;
|
|
1321
|
-
})(WeaponId || {});
|
|
1322
|
-
var PowerupId = /* @__PURE__ */ ((PowerupId3) => {
|
|
1323
|
-
PowerupId3["QuadDamage"] = "quad";
|
|
1324
|
-
PowerupId3["Invulnerability"] = "invulnerability";
|
|
1325
|
-
PowerupId3["Silencer"] = "silencer";
|
|
1326
|
-
PowerupId3["Rebreather"] = "rebreather";
|
|
1327
|
-
PowerupId3["EnviroSuit"] = "enviro";
|
|
1328
|
-
PowerupId3["DoubleDamage"] = "double";
|
|
1329
|
-
PowerupId3["QuadFire"] = "quadfire";
|
|
1330
|
-
PowerupId3["Invisibility"] = "invisibility";
|
|
1331
|
-
PowerupId3["Bandolier"] = "bandolier";
|
|
1332
|
-
PowerupId3["AmmoPack"] = "pack";
|
|
1333
|
-
PowerupId3["IRGoggles"] = "goggles";
|
|
1334
|
-
PowerupId3["SphereVengeance"] = "vengeance";
|
|
1335
|
-
PowerupId3["SphereHunter"] = "hunter";
|
|
1336
|
-
PowerupId3["SphereDefender"] = "defender";
|
|
1337
|
-
PowerupId3["Doppelganger"] = "doppelganger";
|
|
1338
|
-
PowerupId3["TagToken"] = "tagtoken";
|
|
1339
|
-
PowerupId3["TechResistance"] = "tech_resistance";
|
|
1340
|
-
PowerupId3["TechStrength"] = "tech_strength";
|
|
1341
|
-
PowerupId3["TechHaste"] = "tech_haste";
|
|
1342
|
-
PowerupId3["TechRegeneration"] = "tech_regeneration";
|
|
1343
|
-
PowerupId3["Flashlight"] = "flashlight";
|
|
1344
|
-
PowerupId3["Compass"] = "compass";
|
|
1345
|
-
return PowerupId3;
|
|
1346
|
-
})(PowerupId || {});
|
|
1347
1363
|
var KeyId = /* @__PURE__ */ ((KeyId2) => {
|
|
1348
1364
|
KeyId2["Blue"] = "key_blue";
|
|
1349
1365
|
KeyId2["Red"] = "key_red";
|
|
@@ -1368,7 +1384,7 @@ function createPlayerInventory(init = {}) {
|
|
|
1368
1384
|
const ammoCaps = init.ammoCaps;
|
|
1369
1385
|
const inv = {
|
|
1370
1386
|
ammo: createAmmoInventory(ammoCaps),
|
|
1371
|
-
ownedWeapons: new Set(init.weapons ?? [
|
|
1387
|
+
ownedWeapons: new Set(init.weapons ?? [WeaponId.Blaster]),
|
|
1372
1388
|
armor: null,
|
|
1373
1389
|
powerups: /* @__PURE__ */ new Map(),
|
|
1374
1390
|
keys: /* @__PURE__ */ new Set(),
|
|
@@ -1382,8 +1398,8 @@ function createPlayerInventory(init = {}) {
|
|
|
1382
1398
|
if (init.currentWeapon) {
|
|
1383
1399
|
inv.currentWeapon = init.currentWeapon;
|
|
1384
1400
|
} else if (inv.ownedWeapons.size > 0) {
|
|
1385
|
-
if (inv.ownedWeapons.has(
|
|
1386
|
-
else if (inv.ownedWeapons.has(
|
|
1401
|
+
if (inv.ownedWeapons.has(WeaponId.Blaster)) inv.currentWeapon = WeaponId.Blaster;
|
|
1402
|
+
else if (inv.ownedWeapons.has(WeaponId.Shotgun)) inv.currentWeapon = WeaponId.Shotgun;
|
|
1387
1403
|
else inv.currentWeapon = [...inv.ownedWeapons][0];
|
|
1388
1404
|
}
|
|
1389
1405
|
return inv;
|
|
@@ -1512,27 +1528,27 @@ function pickupPowerup(client, item, time) {
|
|
|
1512
1528
|
let icon = "";
|
|
1513
1529
|
switch (item.id) {
|
|
1514
1530
|
case "item_quad":
|
|
1515
|
-
powerupId =
|
|
1531
|
+
powerupId = PowerupId.QuadDamage;
|
|
1516
1532
|
icon = "p_quad";
|
|
1517
1533
|
break;
|
|
1518
1534
|
case "item_invulnerability":
|
|
1519
|
-
powerupId =
|
|
1535
|
+
powerupId = PowerupId.Invulnerability;
|
|
1520
1536
|
icon = "p_invulnerability";
|
|
1521
1537
|
break;
|
|
1522
1538
|
case "item_silencer":
|
|
1523
|
-
powerupId =
|
|
1539
|
+
powerupId = PowerupId.Silencer;
|
|
1524
1540
|
icon = "p_silencer";
|
|
1525
1541
|
break;
|
|
1526
1542
|
case "item_rebreather":
|
|
1527
|
-
powerupId =
|
|
1543
|
+
powerupId = PowerupId.Rebreather;
|
|
1528
1544
|
icon = "p_rebreather";
|
|
1529
1545
|
break;
|
|
1530
1546
|
case "item_enviro":
|
|
1531
|
-
powerupId =
|
|
1547
|
+
powerupId = PowerupId.EnviroSuit;
|
|
1532
1548
|
icon = "p_envirosuit";
|
|
1533
1549
|
break;
|
|
1534
1550
|
case "item_double":
|
|
1535
|
-
powerupId =
|
|
1551
|
+
powerupId = PowerupId.DoubleDamage;
|
|
1536
1552
|
icon = "p_double";
|
|
1537
1553
|
break;
|
|
1538
1554
|
}
|
|
@@ -1540,9 +1556,9 @@ function pickupPowerup(client, item, time) {
|
|
|
1540
1556
|
const expiresAt = inventory.powerups.get(powerupId);
|
|
1541
1557
|
const newExpiresAt = expiresAt && expiresAt > time ? expiresAt + item.timer * 1e3 : time + item.timer * 1e3;
|
|
1542
1558
|
inventory.powerups.set(powerupId, newExpiresAt);
|
|
1543
|
-
if (powerupId ===
|
|
1559
|
+
if (powerupId === PowerupId.QuadDamage) {
|
|
1544
1560
|
client.quad_time = newExpiresAt / 1e3;
|
|
1545
|
-
} else if (powerupId ===
|
|
1561
|
+
} else if (powerupId === PowerupId.DoubleDamage) {
|
|
1546
1562
|
client.double_time = newExpiresAt / 1e3;
|
|
1547
1563
|
}
|
|
1548
1564
|
setPickup(inventory, icon, time);
|
|
@@ -1750,6 +1766,8 @@ var Entity = class {
|
|
|
1750
1766
|
this.attenuation = 0;
|
|
1751
1767
|
this.volume = 0;
|
|
1752
1768
|
this.fly_sound_debounce_time = 0;
|
|
1769
|
+
this.last_move_time = 0;
|
|
1770
|
+
this.damage_debounce_time = 0;
|
|
1753
1771
|
this.enemy = null;
|
|
1754
1772
|
this.movetarget = null;
|
|
1755
1773
|
this.target_ent = null;
|
|
@@ -1889,6 +1907,8 @@ var Entity = class {
|
|
|
1889
1907
|
this.sounds = 0;
|
|
1890
1908
|
this.noise_index = 0;
|
|
1891
1909
|
this.fly_sound_debounce_time = 0;
|
|
1910
|
+
this.last_move_time = 0;
|
|
1911
|
+
this.damage_debounce_time = 0;
|
|
1892
1912
|
this.enemy = null;
|
|
1893
1913
|
this.movetarget = null;
|
|
1894
1914
|
this.target_ent = null;
|
|
@@ -1984,6 +2004,8 @@ var ENTITY_FIELD_METADATA = [
|
|
|
1984
2004
|
{ name: "attenuation", type: "float", save: true },
|
|
1985
2005
|
{ name: "volume", type: "float", save: true },
|
|
1986
2006
|
{ name: "fly_sound_debounce_time", type: "float", save: true },
|
|
2007
|
+
{ name: "last_move_time", type: "float", save: true },
|
|
2008
|
+
{ name: "damage_debounce_time", type: "float", save: true },
|
|
1987
2009
|
{ name: "enemy", type: "entity", save: true },
|
|
1988
2010
|
{ name: "movetarget", type: "entity", save: true },
|
|
1989
2011
|
{ name: "target_ent", type: "entity", save: true },
|
|
@@ -3222,7 +3244,9 @@ var EntitySystem = class {
|
|
|
3222
3244
|
}
|
|
3223
3245
|
forEachEntity(callback) {
|
|
3224
3246
|
for (const entity of this.pool) {
|
|
3225
|
-
|
|
3247
|
+
if (entity.inUse && !entity.freePending) {
|
|
3248
|
+
callback(entity);
|
|
3249
|
+
}
|
|
3226
3250
|
}
|
|
3227
3251
|
}
|
|
3228
3252
|
find(predicate) {
|
|
@@ -4373,6 +4397,7 @@ function createBfgBall(sys, owner, start, dir, damage, speed, damageRadius) {
|
|
|
4373
4397
|
}
|
|
4374
4398
|
|
|
4375
4399
|
// src/entities/targets.ts
|
|
4400
|
+
var ATTN_NONE = 0;
|
|
4376
4401
|
var ATTN_NORM = 1;
|
|
4377
4402
|
var SPEAKER_SPAWNFLAGS = {
|
|
4378
4403
|
LoopedOn: 1 << 0,
|
|
@@ -4465,6 +4490,88 @@ function useTargetBlaster(self, other, activator, context) {
|
|
|
4465
4490
|
}
|
|
4466
4491
|
context.entities.sound(self, 2, "weapons/laser2.wav", 1, ATTN_NORM, 0);
|
|
4467
4492
|
}
|
|
4493
|
+
var SPAWNFLAG_EARTHQUAKE_SILENT = 1;
|
|
4494
|
+
var SPAWNFLAG_EARTHQUAKE_TOGGLE = 2;
|
|
4495
|
+
var SPAWNFLAG_EARTHQUAKE_ONE_SHOT = 8;
|
|
4496
|
+
function target_earthquake_think(self, context) {
|
|
4497
|
+
if (!(self.spawnflags & SPAWNFLAG_EARTHQUAKE_SILENT)) {
|
|
4498
|
+
if (self.last_move_time < context.entities.timeSeconds) {
|
|
4499
|
+
context.entities.sound(self, 2, "world/quake.wav", 1, ATTN_NONE, 0);
|
|
4500
|
+
self.last_move_time = context.entities.timeSeconds + 0.5;
|
|
4501
|
+
}
|
|
4502
|
+
}
|
|
4503
|
+
context.entities.forEachEntity((ent) => {
|
|
4504
|
+
if (!ent.client) return;
|
|
4505
|
+
ent.client.quake_time = context.entities.timeSeconds + 0.2;
|
|
4506
|
+
});
|
|
4507
|
+
if (context.entities.timeSeconds < self.timestamp) {
|
|
4508
|
+
self.nextthink = context.entities.timeSeconds + 0.1;
|
|
4509
|
+
}
|
|
4510
|
+
}
|
|
4511
|
+
function useTargetEarthquake(self, other, activator, context) {
|
|
4512
|
+
if (self.spawnflags & SPAWNFLAG_EARTHQUAKE_ONE_SHOT) {
|
|
4513
|
+
context.entities.forEachEntity((ent) => {
|
|
4514
|
+
if (!ent.client) return;
|
|
4515
|
+
if (ent.client) {
|
|
4516
|
+
if (!ent.client.kick_angles) ent.client.kick_angles = { x: 0, y: 0, z: 0 };
|
|
4517
|
+
ent.client.kick_angles = { ...ent.client.kick_angles, x: -self.speed * 0.1 };
|
|
4518
|
+
}
|
|
4519
|
+
});
|
|
4520
|
+
return;
|
|
4521
|
+
}
|
|
4522
|
+
self.timestamp = context.entities.timeSeconds + self.count;
|
|
4523
|
+
if (self.spawnflags & SPAWNFLAG_EARTHQUAKE_TOGGLE) {
|
|
4524
|
+
if (self.style) {
|
|
4525
|
+
self.nextthink = 0;
|
|
4526
|
+
} else {
|
|
4527
|
+
self.nextthink = context.entities.timeSeconds + 0.1;
|
|
4528
|
+
}
|
|
4529
|
+
self.style = !self.style ? 1 : 0;
|
|
4530
|
+
} else {
|
|
4531
|
+
self.nextthink = context.entities.timeSeconds + 0.1;
|
|
4532
|
+
self.last_move_time = 0;
|
|
4533
|
+
}
|
|
4534
|
+
self.activator = activator;
|
|
4535
|
+
}
|
|
4536
|
+
var SPAWNFLAG_LIGHTRAMP_TOGGLE = 1;
|
|
4537
|
+
function target_lightramp_think(self, context) {
|
|
4538
|
+
const timeDelta = context.entities.timeSeconds - self.timestamp;
|
|
4539
|
+
const val = self.movedir.x + timeDelta / 0.1 * self.movedir.z;
|
|
4540
|
+
let charCode = Math.floor("a".charCodeAt(0) + val);
|
|
4541
|
+
const styleStr = String.fromCharCode(charCode);
|
|
4542
|
+
const CS_LIGHTS = 32;
|
|
4543
|
+
if (self.enemy && self.enemy.style !== void 0) {
|
|
4544
|
+
context.entities.configstring(CS_LIGHTS + self.enemy.style, styleStr);
|
|
4545
|
+
}
|
|
4546
|
+
if (timeDelta < self.speed) {
|
|
4547
|
+
self.nextthink = context.entities.timeSeconds + 0.1;
|
|
4548
|
+
} else if (self.spawnflags & SPAWNFLAG_LIGHTRAMP_TOGGLE) {
|
|
4549
|
+
const temp = self.movedir.x;
|
|
4550
|
+
self.movedir = { ...self.movedir, x: self.movedir.y, y: temp, z: self.movedir.z * -1 };
|
|
4551
|
+
}
|
|
4552
|
+
}
|
|
4553
|
+
function useTargetLightramp(self, other, activator, context) {
|
|
4554
|
+
if (!self.enemy) {
|
|
4555
|
+
let e = null;
|
|
4556
|
+
let found = false;
|
|
4557
|
+
context.entities.forEachEntity((ent) => {
|
|
4558
|
+
if (ent.targetname === self.target) {
|
|
4559
|
+
if (ent.classname === "light") {
|
|
4560
|
+
self.enemy = ent;
|
|
4561
|
+
found = true;
|
|
4562
|
+
} else {
|
|
4563
|
+
context.warn(`${self.classname} target ${self.target} is not a light`);
|
|
4564
|
+
}
|
|
4565
|
+
}
|
|
4566
|
+
});
|
|
4567
|
+
if (!found) {
|
|
4568
|
+
context.warn(`${self.classname} target ${self.target} not found`);
|
|
4569
|
+
return;
|
|
4570
|
+
}
|
|
4571
|
+
}
|
|
4572
|
+
self.timestamp = context.entities.timeSeconds;
|
|
4573
|
+
target_lightramp_think(self, context);
|
|
4574
|
+
}
|
|
4468
4575
|
var TARGET_LASER_START_ON = 1;
|
|
4469
4576
|
var TARGET_LASER_RED = 2;
|
|
4470
4577
|
var TARGET_LASER_GREEN = 4;
|
|
@@ -4721,6 +4828,26 @@ function registerTargetSpawns(registry) {
|
|
|
4721
4828
|
};
|
|
4722
4829
|
context.entities.scheduleThink(entity, context.entities.timeSeconds + entity.delay);
|
|
4723
4830
|
});
|
|
4831
|
+
registry.register("target_earthquake", (entity, context) => {
|
|
4832
|
+
if (!entity.count) entity.count = 5;
|
|
4833
|
+
if (!entity.speed) entity.speed = 200;
|
|
4834
|
+
entity.svflags |= 1 /* NoClient */;
|
|
4835
|
+
entity.think = (self) => target_earthquake_think(self, context);
|
|
4836
|
+
entity.use = (self, other, activator) => useTargetEarthquake(self, other, activator ?? null, context);
|
|
4837
|
+
if (!(entity.spawnflags & SPAWNFLAG_EARTHQUAKE_SILENT)) {
|
|
4838
|
+
}
|
|
4839
|
+
});
|
|
4840
|
+
registry.register("target_lightramp", (entity, context) => {
|
|
4841
|
+
entity.svflags |= 1 /* NoClient */;
|
|
4842
|
+
entity.use = (self, other, activator) => useTargetLightramp(self, other, activator ?? null, context);
|
|
4843
|
+
entity.think = (self) => target_lightramp_think(self, context);
|
|
4844
|
+
if (entity.message && entity.message.length === 2 && entity.speed) {
|
|
4845
|
+
const start = entity.message.charCodeAt(0) - "a".charCodeAt(0);
|
|
4846
|
+
const end = entity.message.charCodeAt(1) - "a".charCodeAt(0);
|
|
4847
|
+
const slope = (end - start) / (entity.speed / 0.1);
|
|
4848
|
+
entity.movedir = { x: start, y: end, z: slope };
|
|
4849
|
+
}
|
|
4850
|
+
});
|
|
4724
4851
|
}
|
|
4725
4852
|
|
|
4726
4853
|
// src/entities/triggers.ts
|
|
@@ -5306,7 +5433,7 @@ function chaingunThink(player, sys) {
|
|
|
5306
5433
|
if (!player.client) {
|
|
5307
5434
|
return;
|
|
5308
5435
|
}
|
|
5309
|
-
const weaponState = getWeaponState(player.client.weaponStates,
|
|
5436
|
+
const weaponState = getWeaponState(player.client.weaponStates, WeaponId.Chaingun);
|
|
5310
5437
|
if (!(player.client.buttons & BUTTON_ATTACK) && weaponState.spinupCount && weaponState.spinupCount > 0) {
|
|
5311
5438
|
sys.sound(player, 0, "weapons/chngnd1a.wav", 1, 0, 0);
|
|
5312
5439
|
weaponState.spinupCount = 0;
|
|
@@ -5319,7 +5446,7 @@ var WEAPON_ITEMS = {
|
|
|
5319
5446
|
type: "weapon",
|
|
5320
5447
|
id: "weapon_blaster",
|
|
5321
5448
|
name: "Blaster",
|
|
5322
|
-
weaponId:
|
|
5449
|
+
weaponId: WeaponId.Blaster,
|
|
5323
5450
|
ammoType: null,
|
|
5324
5451
|
initialAmmo: 0,
|
|
5325
5452
|
pickupAmmo: 0,
|
|
@@ -5329,7 +5456,7 @@ var WEAPON_ITEMS = {
|
|
|
5329
5456
|
type: "weapon",
|
|
5330
5457
|
id: "weapon_shotgun",
|
|
5331
5458
|
name: "Shotgun",
|
|
5332
|
-
weaponId:
|
|
5459
|
+
weaponId: WeaponId.Shotgun,
|
|
5333
5460
|
ammoType: AmmoType.Shells,
|
|
5334
5461
|
initialAmmo: 10,
|
|
5335
5462
|
pickupAmmo: 10,
|
|
@@ -5339,7 +5466,7 @@ var WEAPON_ITEMS = {
|
|
|
5339
5466
|
type: "weapon",
|
|
5340
5467
|
id: "weapon_supershotgun",
|
|
5341
5468
|
name: "Super Shotgun",
|
|
5342
|
-
weaponId:
|
|
5469
|
+
weaponId: WeaponId.SuperShotgun,
|
|
5343
5470
|
ammoType: AmmoType.Shells,
|
|
5344
5471
|
initialAmmo: 10,
|
|
5345
5472
|
pickupAmmo: 10,
|
|
@@ -5349,7 +5476,7 @@ var WEAPON_ITEMS = {
|
|
|
5349
5476
|
type: "weapon",
|
|
5350
5477
|
id: "weapon_machinegun",
|
|
5351
5478
|
name: "Machinegun",
|
|
5352
|
-
weaponId:
|
|
5479
|
+
weaponId: WeaponId.Machinegun,
|
|
5353
5480
|
ammoType: AmmoType.Bullets,
|
|
5354
5481
|
initialAmmo: 50,
|
|
5355
5482
|
pickupAmmo: 50,
|
|
@@ -5360,7 +5487,7 @@ var WEAPON_ITEMS = {
|
|
|
5360
5487
|
type: "weapon",
|
|
5361
5488
|
id: "weapon_chaingun",
|
|
5362
5489
|
name: "Chaingun",
|
|
5363
|
-
weaponId:
|
|
5490
|
+
weaponId: WeaponId.Chaingun,
|
|
5364
5491
|
ammoType: AmmoType.Bullets,
|
|
5365
5492
|
initialAmmo: 50,
|
|
5366
5493
|
pickupAmmo: 50,
|
|
@@ -5370,7 +5497,7 @@ var WEAPON_ITEMS = {
|
|
|
5370
5497
|
type: "weapon",
|
|
5371
5498
|
id: "weapon_grenades",
|
|
5372
5499
|
name: "Hand Grenade",
|
|
5373
|
-
weaponId:
|
|
5500
|
+
weaponId: WeaponId.HandGrenade,
|
|
5374
5501
|
ammoType: AmmoType.Grenades,
|
|
5375
5502
|
initialAmmo: 5,
|
|
5376
5503
|
pickupAmmo: 5,
|
|
@@ -5380,7 +5507,7 @@ var WEAPON_ITEMS = {
|
|
|
5380
5507
|
type: "weapon",
|
|
5381
5508
|
id: "weapon_grenadelauncher",
|
|
5382
5509
|
name: "Grenade Launcher",
|
|
5383
|
-
weaponId:
|
|
5510
|
+
weaponId: WeaponId.GrenadeLauncher,
|
|
5384
5511
|
ammoType: AmmoType.Grenades,
|
|
5385
5512
|
initialAmmo: 10,
|
|
5386
5513
|
pickupAmmo: 10,
|
|
@@ -5390,7 +5517,7 @@ var WEAPON_ITEMS = {
|
|
|
5390
5517
|
type: "weapon",
|
|
5391
5518
|
id: "weapon_rocketlauncher",
|
|
5392
5519
|
name: "Rocket Launcher",
|
|
5393
|
-
weaponId:
|
|
5520
|
+
weaponId: WeaponId.RocketLauncher,
|
|
5394
5521
|
ammoType: AmmoType.Rockets,
|
|
5395
5522
|
initialAmmo: 5,
|
|
5396
5523
|
pickupAmmo: 5,
|
|
@@ -5400,7 +5527,7 @@ var WEAPON_ITEMS = {
|
|
|
5400
5527
|
type: "weapon",
|
|
5401
5528
|
id: "weapon_hyperblaster",
|
|
5402
5529
|
name: "HyperBlaster",
|
|
5403
|
-
weaponId:
|
|
5530
|
+
weaponId: WeaponId.HyperBlaster,
|
|
5404
5531
|
ammoType: AmmoType.Cells,
|
|
5405
5532
|
initialAmmo: 50,
|
|
5406
5533
|
pickupAmmo: 50,
|
|
@@ -5410,7 +5537,7 @@ var WEAPON_ITEMS = {
|
|
|
5410
5537
|
type: "weapon",
|
|
5411
5538
|
id: "weapon_railgun",
|
|
5412
5539
|
name: "Railgun",
|
|
5413
|
-
weaponId:
|
|
5540
|
+
weaponId: WeaponId.Railgun,
|
|
5414
5541
|
ammoType: AmmoType.Slugs,
|
|
5415
5542
|
initialAmmo: 10,
|
|
5416
5543
|
pickupAmmo: 10,
|
|
@@ -5420,7 +5547,7 @@ var WEAPON_ITEMS = {
|
|
|
5420
5547
|
type: "weapon",
|
|
5421
5548
|
id: "weapon_bfg",
|
|
5422
5549
|
name: "BFG10K",
|
|
5423
|
-
weaponId:
|
|
5550
|
+
weaponId: WeaponId.BFG10K,
|
|
5424
5551
|
ammoType: AmmoType.Cells,
|
|
5425
5552
|
initialAmmo: 50,
|
|
5426
5553
|
pickupAmmo: 50,
|
|
@@ -5432,7 +5559,7 @@ var WEAPON_ITEMS = {
|
|
|
5432
5559
|
id: "weapon_boomer",
|
|
5433
5560
|
// Ion Ripper
|
|
5434
5561
|
name: "Ion Ripper",
|
|
5435
|
-
weaponId:
|
|
5562
|
+
weaponId: WeaponId.IonRipper,
|
|
5436
5563
|
ammoType: AmmoType.Cells,
|
|
5437
5564
|
initialAmmo: 50,
|
|
5438
5565
|
pickupAmmo: 50,
|
|
@@ -5442,7 +5569,7 @@ var WEAPON_ITEMS = {
|
|
|
5442
5569
|
type: "weapon",
|
|
5443
5570
|
id: "weapon_phalanx",
|
|
5444
5571
|
name: "Phalanx",
|
|
5445
|
-
weaponId:
|
|
5572
|
+
weaponId: WeaponId.Phalanx,
|
|
5446
5573
|
ammoType: AmmoType.MagSlugs,
|
|
5447
5574
|
initialAmmo: 50,
|
|
5448
5575
|
pickupAmmo: 50,
|
|
@@ -5452,7 +5579,7 @@ var WEAPON_ITEMS = {
|
|
|
5452
5579
|
type: "weapon",
|
|
5453
5580
|
id: "weapon_beam",
|
|
5454
5581
|
name: "Plasma Beam",
|
|
5455
|
-
weaponId:
|
|
5582
|
+
weaponId: WeaponId.PlasmaBeam,
|
|
5456
5583
|
ammoType: AmmoType.Cells,
|
|
5457
5584
|
initialAmmo: 50,
|
|
5458
5585
|
pickupAmmo: 50,
|
|
@@ -5462,7 +5589,7 @@ var WEAPON_ITEMS = {
|
|
|
5462
5589
|
type: "weapon",
|
|
5463
5590
|
id: "weapon_etf_rifle",
|
|
5464
5591
|
name: "ETF Rifle",
|
|
5465
|
-
weaponId:
|
|
5592
|
+
weaponId: WeaponId.EtfRifle,
|
|
5466
5593
|
ammoType: AmmoType.Flechettes,
|
|
5467
5594
|
initialAmmo: 50,
|
|
5468
5595
|
pickupAmmo: 50,
|
|
@@ -5472,7 +5599,7 @@ var WEAPON_ITEMS = {
|
|
|
5472
5599
|
type: "weapon",
|
|
5473
5600
|
id: "weapon_proxlauncher",
|
|
5474
5601
|
name: "Prox Launcher",
|
|
5475
|
-
weaponId:
|
|
5602
|
+
weaponId: WeaponId.ProxLauncher,
|
|
5476
5603
|
ammoType: AmmoType.Prox,
|
|
5477
5604
|
initialAmmo: 5,
|
|
5478
5605
|
pickupAmmo: 5,
|
|
@@ -11381,8 +11508,8 @@ function actor_pain(self, other, kick, damage) {
|
|
|
11381
11508
|
if (context.timeSeconds < self.pain_debounce_time)
|
|
11382
11509
|
return;
|
|
11383
11510
|
self.pain_debounce_time = context.timeSeconds + 3;
|
|
11384
|
-
const
|
|
11385
|
-
if (other && other.client &&
|
|
11511
|
+
const random12 = Math.random();
|
|
11512
|
+
if (other && other.client && random12 < 0.4) {
|
|
11386
11513
|
const v = subtractVec3(other.origin, self.origin);
|
|
11387
11514
|
self.ideal_yaw = vectorToYaw(v);
|
|
11388
11515
|
if (Math.random() < 0.5)
|
|
@@ -14078,6 +14205,934 @@ function registerTurretSpawns(registry) {
|
|
|
14078
14205
|
registry.register("monster_turret", SP_monster_turret);
|
|
14079
14206
|
}
|
|
14080
14207
|
|
|
14208
|
+
// src/entities/monsters/gekk.ts
|
|
14209
|
+
var MONSTER_TICK24 = 0.1;
|
|
14210
|
+
var random8 = () => Math.random();
|
|
14211
|
+
var frandom2 = () => Math.random();
|
|
14212
|
+
var irandom2 = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
|
|
14213
|
+
function monster_ai_stand22(self, dist, context) {
|
|
14214
|
+
ai_stand(self, MONSTER_TICK24, context);
|
|
14215
|
+
}
|
|
14216
|
+
function monster_ai_walk20(self, dist, context) {
|
|
14217
|
+
ai_walk(self, dist, MONSTER_TICK24, context);
|
|
14218
|
+
}
|
|
14219
|
+
function monster_ai_run21(self, dist, context) {
|
|
14220
|
+
ai_run(self, dist, MONSTER_TICK24, context);
|
|
14221
|
+
}
|
|
14222
|
+
function monster_ai_charge22(self, dist, context) {
|
|
14223
|
+
ai_charge(self, dist, MONSTER_TICK24, context);
|
|
14224
|
+
}
|
|
14225
|
+
function monster_ai_move21(self, dist, context) {
|
|
14226
|
+
ai_move(self, dist);
|
|
14227
|
+
}
|
|
14228
|
+
var gekk_move_stand;
|
|
14229
|
+
var gekk_move_standunderwater;
|
|
14230
|
+
var gekk_move_swim_loop;
|
|
14231
|
+
var gekk_move_swim_start;
|
|
14232
|
+
var gekk_move_chant;
|
|
14233
|
+
var gekk_move_idle;
|
|
14234
|
+
var gekk_move_idle2;
|
|
14235
|
+
var gekk_move_walk;
|
|
14236
|
+
var gekk_move_run;
|
|
14237
|
+
var gekk_move_run_start;
|
|
14238
|
+
var gekk_move_attack1;
|
|
14239
|
+
var gekk_move_attack2;
|
|
14240
|
+
var gekk_move_spit;
|
|
14241
|
+
var gekk_move_leapatk;
|
|
14242
|
+
var gekk_move_leapatk2;
|
|
14243
|
+
var gekk_move_attack;
|
|
14244
|
+
var gekk_move_pain;
|
|
14245
|
+
var gekk_move_pain1;
|
|
14246
|
+
var gekk_move_pain2;
|
|
14247
|
+
var gekk_move_death1;
|
|
14248
|
+
var gekk_move_death3;
|
|
14249
|
+
var gekk_move_death4;
|
|
14250
|
+
var gekk_move_wdeath;
|
|
14251
|
+
var WATER_WAIST = 2;
|
|
14252
|
+
var RANGE_MELEE2 = 80;
|
|
14253
|
+
var RANGE_NEAR2 = 100;
|
|
14254
|
+
var RANGE_MID2 = 400;
|
|
14255
|
+
var SPAWNFLAG_GEKK_CHANT = 8;
|
|
14256
|
+
var SPAWNFLAG_GEKK_NOJUMPING = 16;
|
|
14257
|
+
var SPAWNFLAG_GEKK_NOSWIM = 32;
|
|
14258
|
+
var GIB_HEALTH = -30;
|
|
14259
|
+
function gekk_check_underwater(self, context) {
|
|
14260
|
+
if (!(self.spawnflags & SPAWNFLAG_GEKK_NOSWIM) && self.waterlevel >= WATER_WAIST) {
|
|
14261
|
+
land_to_water(self);
|
|
14262
|
+
}
|
|
14263
|
+
}
|
|
14264
|
+
function gekk_stand(self) {
|
|
14265
|
+
if (self.waterlevel >= WATER_WAIST) {
|
|
14266
|
+
self.flags |= 2 /* Swim */;
|
|
14267
|
+
self.monsterinfo.current_move = gekk_move_standunderwater;
|
|
14268
|
+
} else {
|
|
14269
|
+
if (self.monsterinfo.current_move !== gekk_move_chant) {
|
|
14270
|
+
self.monsterinfo.current_move = gekk_move_stand;
|
|
14271
|
+
}
|
|
14272
|
+
}
|
|
14273
|
+
}
|
|
14274
|
+
function gekk_swim_loop_func(self) {
|
|
14275
|
+
self.flags |= 2 /* Swim */;
|
|
14276
|
+
self.monsterinfo.current_move = gekk_move_swim_loop;
|
|
14277
|
+
}
|
|
14278
|
+
function gekk_hit_left(self, context) {
|
|
14279
|
+
if (!self.enemy) return;
|
|
14280
|
+
const damage = irandom2(5, 10);
|
|
14281
|
+
const range = 100;
|
|
14282
|
+
const dir = subtractVec3(self.enemy.origin, self.origin);
|
|
14283
|
+
const dist = lengthVec3(dir);
|
|
14284
|
+
if (dist <= range) {
|
|
14285
|
+
context.engine.sound?.(self, 0, "gek/gk_atck2.wav", 1, 1, 0);
|
|
14286
|
+
T_Damage(self.enemy, self, self, normalizeVec3(dir), self.enemy.origin, ZERO_VEC3, damage, damage, 0, 0 /* UNKNOWN */, context.timeSeconds);
|
|
14287
|
+
} else {
|
|
14288
|
+
context.engine.sound?.(self, 0, "gek/gk_atck1.wav", 1, 1, 0);
|
|
14289
|
+
}
|
|
14290
|
+
}
|
|
14291
|
+
function gekk_hit_right(self, context) {
|
|
14292
|
+
if (!self.enemy) return;
|
|
14293
|
+
const damage = irandom2(5, 10);
|
|
14294
|
+
const range = 100;
|
|
14295
|
+
const dir = subtractVec3(self.enemy.origin, self.origin);
|
|
14296
|
+
const dist = lengthVec3(dir);
|
|
14297
|
+
if (dist <= range) {
|
|
14298
|
+
context.engine.sound?.(self, 0, "gek/gk_atck3.wav", 1, 1, 0);
|
|
14299
|
+
T_Damage(self.enemy, self, self, normalizeVec3(dir), self.enemy.origin, ZERO_VEC3, damage, damage, 0, 0 /* UNKNOWN */, context.timeSeconds);
|
|
14300
|
+
} else {
|
|
14301
|
+
context.engine.sound?.(self, 0, "gek/gk_atck1.wav", 1, 1, 0);
|
|
14302
|
+
}
|
|
14303
|
+
}
|
|
14304
|
+
function gekk_bite(self, context) {
|
|
14305
|
+
if (!self.enemy) return;
|
|
14306
|
+
const damage = 5;
|
|
14307
|
+
const range = RANGE_MELEE2;
|
|
14308
|
+
const dir = subtractVec3(self.enemy.origin, self.origin);
|
|
14309
|
+
const dist = lengthVec3(dir);
|
|
14310
|
+
if (dist <= range) {
|
|
14311
|
+
T_Damage(self.enemy, self, self, normalizeVec3(dir), self.enemy.origin, ZERO_VEC3, damage, 0, 0, 0 /* UNKNOWN */, context.timeSeconds);
|
|
14312
|
+
}
|
|
14313
|
+
}
|
|
14314
|
+
function gekk_check_melee(self, context) {
|
|
14315
|
+
if (!self.enemy || self.enemy.health <= 0 || self.monsterinfo.melee_debounce_time && self.monsterinfo.melee_debounce_time > context.timeSeconds)
|
|
14316
|
+
return false;
|
|
14317
|
+
const dist = lengthVec3(subtractVec3(self.enemy.origin, self.origin));
|
|
14318
|
+
return dist <= RANGE_MELEE2;
|
|
14319
|
+
}
|
|
14320
|
+
function gekk_check_jump(self, context) {
|
|
14321
|
+
if (!self.enemy) return false;
|
|
14322
|
+
if (self.absmin.z + 125 < self.enemy.absmin.z)
|
|
14323
|
+
return false;
|
|
14324
|
+
const v = subtractVec3(self.origin, self.enemy.origin);
|
|
14325
|
+
v.z = 0;
|
|
14326
|
+
const distance2 = lengthVec3(v);
|
|
14327
|
+
if (distance2 < 100) return false;
|
|
14328
|
+
if (distance2 > 100) {
|
|
14329
|
+
if (frandom2() < (self.waterlevel >= WATER_WAIST ? 0.2 : 0.9))
|
|
14330
|
+
return false;
|
|
14331
|
+
}
|
|
14332
|
+
return true;
|
|
14333
|
+
}
|
|
14334
|
+
function gekk_check_jump_close(self, context) {
|
|
14335
|
+
if (!self.enemy) return false;
|
|
14336
|
+
const v = subtractVec3(self.origin, self.enemy.origin);
|
|
14337
|
+
v.z = 0;
|
|
14338
|
+
const distance2 = lengthVec3(v);
|
|
14339
|
+
if (distance2 < 100) {
|
|
14340
|
+
if (self.absmax.z <= self.enemy.absmin.z) return false;
|
|
14341
|
+
}
|
|
14342
|
+
return true;
|
|
14343
|
+
}
|
|
14344
|
+
function gekk_checkattack(self, context) {
|
|
14345
|
+
if (!self.enemy || self.enemy.health <= 0) return false;
|
|
14346
|
+
if (gekk_check_melee(self, context)) {
|
|
14347
|
+
return true;
|
|
14348
|
+
}
|
|
14349
|
+
if (gekk_check_jump(self, context)) {
|
|
14350
|
+
return true;
|
|
14351
|
+
}
|
|
14352
|
+
if (gekk_check_jump_close(self, context) && !(self.flags & 2 /* Swim */)) {
|
|
14353
|
+
return true;
|
|
14354
|
+
}
|
|
14355
|
+
return false;
|
|
14356
|
+
}
|
|
14357
|
+
function gekk_chant(self) {
|
|
14358
|
+
self.monsterinfo.current_move = gekk_move_chant;
|
|
14359
|
+
}
|
|
14360
|
+
function gekk_idle_loop(self) {
|
|
14361
|
+
if (frandom2() > 0.75 && self.health < self.max_health) {
|
|
14362
|
+
self.monsterinfo.nextframe = 0;
|
|
14363
|
+
}
|
|
14364
|
+
}
|
|
14365
|
+
function gekk_step(self, context) {
|
|
14366
|
+
const n = irandom2(0, 2);
|
|
14367
|
+
const sounds = ["gek/gk_step1.wav", "gek/gk_step2.wav", "gek/gk_step3.wav"];
|
|
14368
|
+
context.engine.sound?.(self, 0, sounds[n], 1, 1, 0);
|
|
14369
|
+
}
|
|
14370
|
+
function gekk_search(self, context) {
|
|
14371
|
+
if (self.spawnflags & SPAWNFLAG_GEKK_CHANT) {
|
|
14372
|
+
const r = frandom2();
|
|
14373
|
+
if (r < 0.33) context.engine.sound?.(self, 0, "gek/gek_low.wav", 1, 1, 0);
|
|
14374
|
+
else if (r < 0.66) context.engine.sound?.(self, 0, "gek/gek_mid.wav", 1, 1, 0);
|
|
14375
|
+
else context.engine.sound?.(self, 0, "gek/gek_high.wav", 1, 1, 0);
|
|
14376
|
+
} else {
|
|
14377
|
+
context.engine.sound?.(self, 0, "gek/gk_idle1.wav", 1, 1, 0);
|
|
14378
|
+
}
|
|
14379
|
+
self.health += irandom2(10, 20);
|
|
14380
|
+
if (self.health > self.max_health) self.health = self.max_health;
|
|
14381
|
+
if (self.health < self.max_health / 4) self.skin = 2;
|
|
14382
|
+
else if (self.health < self.max_health / 2) self.skin = 1;
|
|
14383
|
+
else self.skin = 0;
|
|
14384
|
+
}
|
|
14385
|
+
function gekk_run_start(self) {
|
|
14386
|
+
if (!(self.spawnflags & SPAWNFLAG_GEKK_NOSWIM) && self.waterlevel >= WATER_WAIST) {
|
|
14387
|
+
self.monsterinfo.current_move = gekk_move_swim_start;
|
|
14388
|
+
} else {
|
|
14389
|
+
self.monsterinfo.current_move = gekk_move_run_start;
|
|
14390
|
+
}
|
|
14391
|
+
}
|
|
14392
|
+
function gekk_run(self) {
|
|
14393
|
+
if (!(self.spawnflags & SPAWNFLAG_GEKK_NOSWIM) && self.waterlevel >= WATER_WAIST) {
|
|
14394
|
+
self.monsterinfo.current_move = gekk_move_swim_start;
|
|
14395
|
+
} else {
|
|
14396
|
+
self.monsterinfo.current_move = gekk_move_run;
|
|
14397
|
+
}
|
|
14398
|
+
}
|
|
14399
|
+
function gekk_check_refire(self) {
|
|
14400
|
+
if (!self.enemy || self.enemy.health <= 0) return;
|
|
14401
|
+
const dist = lengthVec3(subtractVec3(self.enemy.origin, self.origin));
|
|
14402
|
+
if (dist <= RANGE_MELEE2) {
|
|
14403
|
+
if (self.frame === 114) {
|
|
14404
|
+
self.monsterinfo.current_move = gekk_move_attack2;
|
|
14405
|
+
} else if (self.frame === 123) {
|
|
14406
|
+
self.monsterinfo.current_move = gekk_move_attack1;
|
|
14407
|
+
}
|
|
14408
|
+
}
|
|
14409
|
+
}
|
|
14410
|
+
function fire_loogie(self, start, dir, damage, speed, context) {
|
|
14411
|
+
const bolt = createBlasterBolt(context, self, start, dir, damage, speed, 0 /* UNKNOWN */);
|
|
14412
|
+
bolt.model = "models/objects/loogy/tris.md2";
|
|
14413
|
+
}
|
|
14414
|
+
function loogie_fire(self, context) {
|
|
14415
|
+
if (!self.enemy || self.enemy.health <= 0) return;
|
|
14416
|
+
const vectors = angleVectors(self.angles);
|
|
14417
|
+
const forward = vectors.forward;
|
|
14418
|
+
const right = vectors.right;
|
|
14419
|
+
const up = vectors.up;
|
|
14420
|
+
const offset = { x: -18, y: -0.8, z: 24 };
|
|
14421
|
+
const start = addVec3(self.origin, addVec3(scaleVec3(forward, offset.x), addVec3(scaleVec3(right, offset.y), scaleVec3(up, offset.z))));
|
|
14422
|
+
start.z += 2;
|
|
14423
|
+
const end = copyVec3(self.enemy.origin);
|
|
14424
|
+
end.z += self.enemy.viewheight || 0;
|
|
14425
|
+
const dir = normalizeVec3(subtractVec3(end, start));
|
|
14426
|
+
fire_loogie(self, start, dir, 5, 550, context);
|
|
14427
|
+
context.engine.sound?.(self, 0, "gek/gk_atck4.wav", 1, 1, 0);
|
|
14428
|
+
}
|
|
14429
|
+
function reloogie(self) {
|
|
14430
|
+
if (frandom2() > 0.8 && self.health < self.max_health) {
|
|
14431
|
+
self.monsterinfo.current_move = gekk_move_idle2;
|
|
14432
|
+
return;
|
|
14433
|
+
}
|
|
14434
|
+
if (self.enemy && self.enemy.health > 0) {
|
|
14435
|
+
const dist = lengthVec3(subtractVec3(self.enemy.origin, self.origin));
|
|
14436
|
+
if (frandom2() > 0.7 && dist <= RANGE_NEAR2) {
|
|
14437
|
+
self.monsterinfo.current_move = gekk_move_spit;
|
|
14438
|
+
}
|
|
14439
|
+
}
|
|
14440
|
+
}
|
|
14441
|
+
function gekk_jump_touch(self, other, plane, surf) {
|
|
14442
|
+
if (self.health <= 0) {
|
|
14443
|
+
self.touch = void 0;
|
|
14444
|
+
return;
|
|
14445
|
+
}
|
|
14446
|
+
self.touch = void 0;
|
|
14447
|
+
}
|
|
14448
|
+
function gekk_jump_takeoff(self, context) {
|
|
14449
|
+
const vectors = angleVectors(self.angles);
|
|
14450
|
+
const forward = vectors.forward;
|
|
14451
|
+
context.engine.sound?.(self, 0, "gek/gk_sght1.wav", 1, 1, 0);
|
|
14452
|
+
self.origin.z += 1;
|
|
14453
|
+
self.velocity = addVec3(scaleVec3(forward, 700), { x: 0, y: 0, z: 250 });
|
|
14454
|
+
self.groundentity = null;
|
|
14455
|
+
self.touch = gekk_jump_touch;
|
|
14456
|
+
}
|
|
14457
|
+
function gekk_check_landing(self, context) {
|
|
14458
|
+
if (self.groundentity) {
|
|
14459
|
+
context.engine.sound?.(self, 0, "mutant/thud1.wav", 1, 1, 0);
|
|
14460
|
+
self.velocity = ZERO_VEC3;
|
|
14461
|
+
return;
|
|
14462
|
+
}
|
|
14463
|
+
}
|
|
14464
|
+
function gekk_stop_skid(self) {
|
|
14465
|
+
if (self.groundentity) self.velocity = ZERO_VEC3;
|
|
14466
|
+
}
|
|
14467
|
+
function gekk_preattack(self, context) {
|
|
14468
|
+
}
|
|
14469
|
+
function gekk_dead(self) {
|
|
14470
|
+
self.mins = { x: -16, y: -16, z: -24 };
|
|
14471
|
+
self.maxs = { x: 16, y: 16, z: -8 };
|
|
14472
|
+
self.nextthink = -1;
|
|
14473
|
+
}
|
|
14474
|
+
function gekk_gibfest(self, context) {
|
|
14475
|
+
throwGibs(context, self.origin, 20);
|
|
14476
|
+
self.deadflag = 2 /* Dead */;
|
|
14477
|
+
}
|
|
14478
|
+
function isgibfest(self, context) {
|
|
14479
|
+
if (frandom2() > 0.9) gekk_gibfest(self, context);
|
|
14480
|
+
}
|
|
14481
|
+
function gekk_shrink(self) {
|
|
14482
|
+
self.maxs.z = 0;
|
|
14483
|
+
}
|
|
14484
|
+
function land_to_water(self) {
|
|
14485
|
+
self.flags |= 2 /* Swim */;
|
|
14486
|
+
self.yaw_speed = 10;
|
|
14487
|
+
self.viewheight = 10;
|
|
14488
|
+
self.monsterinfo.current_move = gekk_move_swim_start;
|
|
14489
|
+
self.mins = { x: -18, y: -18, z: -24 };
|
|
14490
|
+
self.maxs = { x: 18, y: 18, z: 16 };
|
|
14491
|
+
}
|
|
14492
|
+
var frames_stand2 = Array(38).fill({ ai: monster_ai_stand22, dist: 0 });
|
|
14493
|
+
frames_stand2[38] = { ai: monster_ai_stand22, dist: 0, think: gekk_check_underwater };
|
|
14494
|
+
gekk_move_stand = {
|
|
14495
|
+
firstframe: 0,
|
|
14496
|
+
lastframe: 38,
|
|
14497
|
+
frames: frames_stand2,
|
|
14498
|
+
endfunc: null
|
|
14499
|
+
};
|
|
14500
|
+
var frames_standunderwater = Array(32).fill({ ai: monster_ai_stand22, dist: 14 });
|
|
14501
|
+
gekk_move_standunderwater = {
|
|
14502
|
+
firstframe: 39,
|
|
14503
|
+
lastframe: 70,
|
|
14504
|
+
frames: frames_standunderwater,
|
|
14505
|
+
endfunc: null
|
|
14506
|
+
};
|
|
14507
|
+
var frames_swim = Array(32).fill({ ai: monster_ai_run21, dist: 14 });
|
|
14508
|
+
gekk_move_swim_loop = {
|
|
14509
|
+
firstframe: 39,
|
|
14510
|
+
lastframe: 70,
|
|
14511
|
+
frames: frames_swim,
|
|
14512
|
+
endfunc: gekk_swim_loop_func
|
|
14513
|
+
};
|
|
14514
|
+
var frames_swim_start = Array(32).fill({ ai: monster_ai_run21, dist: 14 });
|
|
14515
|
+
frames_swim_start[8] = { ai: monster_ai_run21, dist: 18, think: gekk_hit_left };
|
|
14516
|
+
frames_swim_start[14] = { ai: monster_ai_run21, dist: 24, think: gekk_hit_right };
|
|
14517
|
+
frames_swim_start[20] = { ai: monster_ai_run21, dist: 22, think: gekk_bite };
|
|
14518
|
+
gekk_move_swim_start = {
|
|
14519
|
+
firstframe: 39,
|
|
14520
|
+
lastframe: 70,
|
|
14521
|
+
frames: frames_swim_start,
|
|
14522
|
+
endfunc: gekk_swim_loop_func
|
|
14523
|
+
};
|
|
14524
|
+
var frames_idle = Array(32).fill({ ai: monster_ai_stand22, dist: 0 });
|
|
14525
|
+
frames_idle[0] = { ai: monster_ai_stand22, dist: 0, think: gekk_search };
|
|
14526
|
+
frames_idle[31] = { ai: monster_ai_stand22, dist: 0, think: gekk_idle_loop };
|
|
14527
|
+
gekk_move_idle = {
|
|
14528
|
+
firstframe: 71,
|
|
14529
|
+
lastframe: 102,
|
|
14530
|
+
frames: frames_idle,
|
|
14531
|
+
endfunc: gekk_stand
|
|
14532
|
+
};
|
|
14533
|
+
var frames_idle2 = Array(32).fill({ ai: monster_ai_move21, dist: 0 });
|
|
14534
|
+
frames_idle2[0] = { ai: monster_ai_move21, dist: 0, think: gekk_search };
|
|
14535
|
+
frames_idle2[31] = { ai: monster_ai_move21, dist: 0, think: gekk_idle_loop };
|
|
14536
|
+
gekk_move_idle2 = {
|
|
14537
|
+
firstframe: 71,
|
|
14538
|
+
lastframe: 102,
|
|
14539
|
+
frames: frames_idle2,
|
|
14540
|
+
endfunc: (s) => M_SetAnimation2(s, gekk_move_stand)
|
|
14541
|
+
// or face
|
|
14542
|
+
};
|
|
14543
|
+
gekk_move_chant = {
|
|
14544
|
+
firstframe: 71,
|
|
14545
|
+
lastframe: 102,
|
|
14546
|
+
frames: frames_idle2,
|
|
14547
|
+
endfunc: gekk_chant
|
|
14548
|
+
};
|
|
14549
|
+
var frames_walk2 = [
|
|
14550
|
+
{ ai: monster_ai_walk20, dist: 3.8, think: gekk_check_underwater },
|
|
14551
|
+
{ ai: monster_ai_walk20, dist: 19.6 },
|
|
14552
|
+
{ ai: monster_ai_walk20, dist: 25.5 },
|
|
14553
|
+
{ ai: monster_ai_walk20, dist: 34.6, think: gekk_step },
|
|
14554
|
+
{ ai: monster_ai_walk20, dist: 27.3 },
|
|
14555
|
+
{ ai: monster_ai_walk20, dist: 28.4 }
|
|
14556
|
+
];
|
|
14557
|
+
gekk_move_walk = {
|
|
14558
|
+
firstframe: 103,
|
|
14559
|
+
lastframe: 108,
|
|
14560
|
+
frames: frames_walk2,
|
|
14561
|
+
endfunc: null
|
|
14562
|
+
};
|
|
14563
|
+
var frames_run2 = [
|
|
14564
|
+
{ ai: monster_ai_run21, dist: 3.8, think: gekk_check_underwater },
|
|
14565
|
+
{ ai: monster_ai_run21, dist: 19.6 },
|
|
14566
|
+
{ ai: monster_ai_run21, dist: 25.5 },
|
|
14567
|
+
{ ai: monster_ai_run21, dist: 34.6, think: gekk_step },
|
|
14568
|
+
{ ai: monster_ai_run21, dist: 27.3 },
|
|
14569
|
+
{ ai: monster_ai_run21, dist: 28.4 }
|
|
14570
|
+
];
|
|
14571
|
+
gekk_move_run = {
|
|
14572
|
+
firstframe: 103,
|
|
14573
|
+
lastframe: 108,
|
|
14574
|
+
frames: frames_run2,
|
|
14575
|
+
endfunc: null
|
|
14576
|
+
};
|
|
14577
|
+
var frames_run_st = [
|
|
14578
|
+
{ ai: monster_ai_run21, dist: 0.2 },
|
|
14579
|
+
{ ai: monster_ai_run21, dist: 19.7 }
|
|
14580
|
+
];
|
|
14581
|
+
gekk_move_run_start = {
|
|
14582
|
+
firstframe: 0,
|
|
14583
|
+
lastframe: 1,
|
|
14584
|
+
// Frames 0 and 1 reuse stand start? C says FRAME_stand_01, FRAME_stand_02
|
|
14585
|
+
frames: frames_run_st,
|
|
14586
|
+
endfunc: gekk_run
|
|
14587
|
+
};
|
|
14588
|
+
var frames_spit = [
|
|
14589
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14590
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14591
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14592
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14593
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14594
|
+
{ ai: monster_ai_charge22, dist: 0, think: loogie_fire },
|
|
14595
|
+
{ ai: monster_ai_charge22, dist: 0, think: reloogie }
|
|
14596
|
+
];
|
|
14597
|
+
gekk_move_spit = {
|
|
14598
|
+
firstframe: 133,
|
|
14599
|
+
// FRAME_spit_01
|
|
14600
|
+
lastframe: 139,
|
|
14601
|
+
frames: frames_spit,
|
|
14602
|
+
endfunc: gekk_run_start
|
|
14603
|
+
};
|
|
14604
|
+
var frames_attack1 = [
|
|
14605
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14606
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14607
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14608
|
+
{ ai: monster_ai_charge22, dist: 0, think: gekk_hit_left },
|
|
14609
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14610
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14611
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14612
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14613
|
+
{ ai: monster_ai_charge22, dist: 0, think: gekk_check_refire }
|
|
14614
|
+
];
|
|
14615
|
+
gekk_move_attack1 = {
|
|
14616
|
+
firstframe: 109,
|
|
14617
|
+
lastframe: 117,
|
|
14618
|
+
frames: frames_attack1,
|
|
14619
|
+
endfunc: gekk_run_start
|
|
14620
|
+
};
|
|
14621
|
+
var frames_attack2 = [
|
|
14622
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14623
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14624
|
+
{ ai: monster_ai_charge22, dist: 0, think: gekk_hit_left },
|
|
14625
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14626
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14627
|
+
{ ai: monster_ai_charge22, dist: 0, think: gekk_hit_right },
|
|
14628
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14629
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14630
|
+
{ ai: monster_ai_charge22, dist: 0, think: gekk_check_refire }
|
|
14631
|
+
];
|
|
14632
|
+
gekk_move_attack2 = {
|
|
14633
|
+
firstframe: 118,
|
|
14634
|
+
lastframe: 126,
|
|
14635
|
+
frames: frames_attack2,
|
|
14636
|
+
endfunc: gekk_run_start
|
|
14637
|
+
};
|
|
14638
|
+
var frames_leapatk = [
|
|
14639
|
+
{ ai: monster_ai_charge22, dist: 0 },
|
|
14640
|
+
{ ai: monster_ai_charge22, dist: -0.3 },
|
|
14641
|
+
{ ai: monster_ai_charge22, dist: -1.1 },
|
|
14642
|
+
{ ai: monster_ai_charge22, dist: -0.2 },
|
|
14643
|
+
{ ai: monster_ai_charge22, dist: 6.7, think: gekk_jump_takeoff },
|
|
14644
|
+
{ ai: monster_ai_charge22, dist: 6.4 },
|
|
14645
|
+
{ ai: monster_ai_charge22, dist: 0.1 },
|
|
14646
|
+
{ ai: monster_ai_charge22, dist: 28.3 },
|
|
14647
|
+
{ ai: monster_ai_charge22, dist: 24.1 },
|
|
14648
|
+
{ ai: monster_ai_charge22, dist: 31.7 },
|
|
14649
|
+
{ ai: monster_ai_charge22, dist: 35.9, think: gekk_check_landing },
|
|
14650
|
+
{ ai: monster_ai_charge22, dist: 12.3, think: gekk_stop_skid },
|
|
14651
|
+
{ ai: monster_ai_charge22, dist: 20.1, think: gekk_stop_skid },
|
|
14652
|
+
{ ai: monster_ai_charge22, dist: -1, think: gekk_stop_skid },
|
|
14653
|
+
{ ai: monster_ai_charge22, dist: 2.5, think: gekk_stop_skid },
|
|
14654
|
+
{ ai: monster_ai_charge22, dist: 0.5, think: gekk_stop_skid },
|
|
14655
|
+
{ ai: monster_ai_charge22, dist: 1.8, think: gekk_stop_skid },
|
|
14656
|
+
{ ai: monster_ai_charge22, dist: 1.2, think: gekk_stop_skid },
|
|
14657
|
+
{ ai: monster_ai_charge22, dist: -0.4, think: gekk_check_underwater }
|
|
14658
|
+
];
|
|
14659
|
+
gekk_move_leapatk = {
|
|
14660
|
+
firstframe: 140,
|
|
14661
|
+
lastframe: 158,
|
|
14662
|
+
frames: frames_leapatk,
|
|
14663
|
+
endfunc: gekk_run_start
|
|
14664
|
+
};
|
|
14665
|
+
gekk_move_leapatk2 = {
|
|
14666
|
+
firstframe: 140,
|
|
14667
|
+
lastframe: 158,
|
|
14668
|
+
frames: frames_leapatk,
|
|
14669
|
+
// reusing frames
|
|
14670
|
+
endfunc: gekk_run_start
|
|
14671
|
+
};
|
|
14672
|
+
var frames_attack3 = Array(21).fill({ ai: monster_ai_charge22, dist: 16 });
|
|
14673
|
+
frames_attack3[0] = { ai: monster_ai_charge22, dist: 16, think: gekk_preattack };
|
|
14674
|
+
frames_attack3[4] = { ai: monster_ai_charge22, dist: 16, think: gekk_bite };
|
|
14675
|
+
frames_attack3[9] = { ai: monster_ai_charge22, dist: 16, think: gekk_bite };
|
|
14676
|
+
frames_attack3[13] = { ai: monster_ai_charge22, dist: 16, think: gekk_hit_left };
|
|
14677
|
+
frames_attack3[18] = { ai: monster_ai_charge22, dist: 16, think: gekk_hit_right };
|
|
14678
|
+
gekk_move_attack = {
|
|
14679
|
+
firstframe: 159,
|
|
14680
|
+
lastframe: 179,
|
|
14681
|
+
frames: frames_attack3,
|
|
14682
|
+
endfunc: gekk_run_start
|
|
14683
|
+
};
|
|
14684
|
+
var frames_pain = Array(6).fill({ ai: monster_ai_move21, dist: 0 });
|
|
14685
|
+
gekk_move_pain = {
|
|
14686
|
+
firstframe: 180,
|
|
14687
|
+
lastframe: 185,
|
|
14688
|
+
frames: frames_pain,
|
|
14689
|
+
endfunc: gekk_run_start
|
|
14690
|
+
};
|
|
14691
|
+
var frames_pain12 = Array(11).fill({ ai: monster_ai_move21, dist: 0 });
|
|
14692
|
+
frames_pain12[10] = { ai: monster_ai_move21, dist: 0, think: gekk_check_underwater };
|
|
14693
|
+
gekk_move_pain1 = {
|
|
14694
|
+
firstframe: 186,
|
|
14695
|
+
lastframe: 196,
|
|
14696
|
+
frames: frames_pain12,
|
|
14697
|
+
endfunc: gekk_run_start
|
|
14698
|
+
};
|
|
14699
|
+
var frames_pain22 = Array(13).fill({ ai: monster_ai_move21, dist: 0 });
|
|
14700
|
+
frames_pain22[12] = { ai: monster_ai_move21, dist: 0, think: gekk_check_underwater };
|
|
14701
|
+
gekk_move_pain2 = {
|
|
14702
|
+
firstframe: 197,
|
|
14703
|
+
lastframe: 209,
|
|
14704
|
+
frames: frames_pain22,
|
|
14705
|
+
endfunc: gekk_run_start
|
|
14706
|
+
};
|
|
14707
|
+
function gekk_pain(self, other, kick, damage, context) {
|
|
14708
|
+
if (self.spawnflags & SPAWNFLAG_GEKK_CHANT) {
|
|
14709
|
+
self.spawnflags &= ~SPAWNFLAG_GEKK_CHANT;
|
|
14710
|
+
return;
|
|
14711
|
+
}
|
|
14712
|
+
context.engine.sound?.(self, 0, "gek/gk_pain1.wav", 1, 1, 0);
|
|
14713
|
+
if (self.waterlevel >= WATER_WAIST) {
|
|
14714
|
+
if (!(self.flags & 2 /* Swim */)) {
|
|
14715
|
+
self.flags |= 2 /* Swim */;
|
|
14716
|
+
}
|
|
14717
|
+
self.monsterinfo.current_move = gekk_move_pain;
|
|
14718
|
+
} else {
|
|
14719
|
+
if (random8() > 0.5) self.monsterinfo.current_move = gekk_move_pain1;
|
|
14720
|
+
else self.monsterinfo.current_move = gekk_move_pain2;
|
|
14721
|
+
}
|
|
14722
|
+
}
|
|
14723
|
+
var frames_death12 = Array(10).fill({ ai: monster_ai_move21, dist: 0 });
|
|
14724
|
+
frames_death12[5] = { ai: monster_ai_move21, dist: -7, think: gekk_shrink };
|
|
14725
|
+
gekk_move_death1 = {
|
|
14726
|
+
firstframe: 210,
|
|
14727
|
+
lastframe: 219,
|
|
14728
|
+
frames: frames_death12,
|
|
14729
|
+
endfunc: gekk_dead
|
|
14730
|
+
};
|
|
14731
|
+
var frames_death3 = Array(7).fill({ ai: monster_ai_move21, dist: 0 });
|
|
14732
|
+
frames_death3[5] = { ai: monster_ai_move21, dist: -7, think: isgibfest };
|
|
14733
|
+
gekk_move_death3 = {
|
|
14734
|
+
firstframe: 220,
|
|
14735
|
+
lastframe: 226,
|
|
14736
|
+
frames: frames_death3,
|
|
14737
|
+
endfunc: gekk_dead
|
|
14738
|
+
};
|
|
14739
|
+
var frames_death4 = Array(35).fill({ ai: monster_ai_move21, dist: 0 });
|
|
14740
|
+
frames_death4[34] = { ai: monster_ai_move21, dist: 0, think: gekk_gibfest };
|
|
14741
|
+
gekk_move_death4 = {
|
|
14742
|
+
firstframe: 227,
|
|
14743
|
+
lastframe: 261,
|
|
14744
|
+
frames: frames_death4,
|
|
14745
|
+
endfunc: gekk_dead
|
|
14746
|
+
};
|
|
14747
|
+
var frames_wdeath = Array(45).fill({ ai: monster_ai_move21, dist: 0 });
|
|
14748
|
+
gekk_move_wdeath = {
|
|
14749
|
+
firstframe: 262,
|
|
14750
|
+
lastframe: 306,
|
|
14751
|
+
frames: frames_wdeath,
|
|
14752
|
+
endfunc: gekk_dead
|
|
14753
|
+
};
|
|
14754
|
+
function gekk_die(self, inflictor, attacker, damage, point, mod, context) {
|
|
14755
|
+
if (self.health <= GIB_HEALTH) {
|
|
14756
|
+
throwGibs(context, self.origin, damage);
|
|
14757
|
+
return;
|
|
14758
|
+
}
|
|
14759
|
+
if (self.deadflag === 2 /* Dead */) return;
|
|
14760
|
+
context.engine.sound?.(self, 0, "gek/gk_deth1.wav", 1, 1, 0);
|
|
14761
|
+
self.deadflag = 2 /* Dead */;
|
|
14762
|
+
self.takedamage = true;
|
|
14763
|
+
if (self.waterlevel >= WATER_WAIST) {
|
|
14764
|
+
gekk_shrink(self);
|
|
14765
|
+
self.monsterinfo.current_move = gekk_move_wdeath;
|
|
14766
|
+
} else {
|
|
14767
|
+
const r = frandom2();
|
|
14768
|
+
if (r > 0.66) self.monsterinfo.current_move = gekk_move_death1;
|
|
14769
|
+
else if (r > 0.33) self.monsterinfo.current_move = gekk_move_death3;
|
|
14770
|
+
else self.monsterinfo.current_move = gekk_move_death4;
|
|
14771
|
+
}
|
|
14772
|
+
}
|
|
14773
|
+
function SP_monster_gekk(self, context) {
|
|
14774
|
+
self.classname = "monster_gekk";
|
|
14775
|
+
self.model = "models/monsters/gekk/tris.md2";
|
|
14776
|
+
self.movetype = 5 /* Step */;
|
|
14777
|
+
self.solid = 2 /* BoundingBox */;
|
|
14778
|
+
self.mins = { x: -18, y: -18, z: -24 };
|
|
14779
|
+
self.maxs = { x: 18, y: 18, z: 24 };
|
|
14780
|
+
self.health = 125;
|
|
14781
|
+
self.max_health = 125;
|
|
14782
|
+
self.mass = 300;
|
|
14783
|
+
self.pain = (e, o, k, d) => gekk_pain(e, o, k, d, context.entities);
|
|
14784
|
+
self.die = (e, i, a, d, p, m3) => gekk_die(e, i, a, d, p, m3, context.entities);
|
|
14785
|
+
self.monsterinfo.stand = gekk_stand;
|
|
14786
|
+
self.monsterinfo.walk = (s) => M_SetAnimation2(s, gekk_move_walk);
|
|
14787
|
+
self.monsterinfo.run = gekk_run_start;
|
|
14788
|
+
self.monsterinfo.attack = (s) => gekk_attack(s, context.entities);
|
|
14789
|
+
self.monsterinfo.melee = gekk_melee;
|
|
14790
|
+
self.monsterinfo.sight = (s, o) => context.entities.sound?.(s, 0, "gek/gk_sght1.wav", 1, 1, 0);
|
|
14791
|
+
self.monsterinfo.search = (s) => gekk_search(s, context.entities);
|
|
14792
|
+
self.monsterinfo.idle = (s) => {
|
|
14793
|
+
if (s.spawnflags & SPAWNFLAG_GEKK_NOSWIM || s.waterlevel < WATER_WAIST) {
|
|
14794
|
+
M_SetAnimation2(s, gekk_move_idle);
|
|
14795
|
+
} else {
|
|
14796
|
+
M_SetAnimation2(s, gekk_move_swim_start);
|
|
14797
|
+
}
|
|
14798
|
+
};
|
|
14799
|
+
self.monsterinfo.checkattack = (s) => gekk_checkattack(s, context.entities);
|
|
14800
|
+
context.entities.linkentity(self);
|
|
14801
|
+
M_SetAnimation2(self, gekk_move_stand);
|
|
14802
|
+
self.think = monster_think;
|
|
14803
|
+
self.nextthink = context.entities.timeSeconds + MONSTER_TICK24;
|
|
14804
|
+
if (self.spawnflags & SPAWNFLAG_GEKK_CHANT) {
|
|
14805
|
+
M_SetAnimation2(self, gekk_move_chant);
|
|
14806
|
+
}
|
|
14807
|
+
}
|
|
14808
|
+
function M_SetAnimation2(self, move) {
|
|
14809
|
+
self.monsterinfo.current_move = move;
|
|
14810
|
+
}
|
|
14811
|
+
function gekk_attack(self, context) {
|
|
14812
|
+
if (!self.enemy) return;
|
|
14813
|
+
const r = lengthVec3(subtractVec3(self.enemy.origin, self.origin));
|
|
14814
|
+
if (self.flags & 2 /* Swim */) {
|
|
14815
|
+
if (self.enemy && self.enemy.waterlevel >= WATER_WAIST && r <= RANGE_NEAR2)
|
|
14816
|
+
return;
|
|
14817
|
+
self.flags &= ~2 /* Swim */;
|
|
14818
|
+
M_SetAnimation2(self, gekk_move_leapatk);
|
|
14819
|
+
self.frame = 144;
|
|
14820
|
+
} else {
|
|
14821
|
+
if (r >= RANGE_MID2) {
|
|
14822
|
+
if (frandom2() > 0.5) {
|
|
14823
|
+
M_SetAnimation2(self, gekk_move_spit);
|
|
14824
|
+
} else {
|
|
14825
|
+
M_SetAnimation2(self, gekk_move_run_start);
|
|
14826
|
+
}
|
|
14827
|
+
} else if (frandom2() > 0.7) {
|
|
14828
|
+
M_SetAnimation2(self, gekk_move_spit);
|
|
14829
|
+
} else {
|
|
14830
|
+
if (self.spawnflags & SPAWNFLAG_GEKK_NOJUMPING || frandom2() > 0.7) {
|
|
14831
|
+
M_SetAnimation2(self, gekk_move_run_start);
|
|
14832
|
+
} else {
|
|
14833
|
+
M_SetAnimation2(self, gekk_move_leapatk);
|
|
14834
|
+
}
|
|
14835
|
+
}
|
|
14836
|
+
}
|
|
14837
|
+
}
|
|
14838
|
+
function gekk_melee(self) {
|
|
14839
|
+
if (self.waterlevel >= WATER_WAIST) {
|
|
14840
|
+
M_SetAnimation2(self, gekk_move_attack);
|
|
14841
|
+
} else {
|
|
14842
|
+
if (frandom2() > 0.66) M_SetAnimation2(self, gekk_move_attack1);
|
|
14843
|
+
else M_SetAnimation2(self, gekk_move_attack2);
|
|
14844
|
+
}
|
|
14845
|
+
}
|
|
14846
|
+
function registerGekkSpawns(registry) {
|
|
14847
|
+
registry.register("monster_gekk", SP_monster_gekk);
|
|
14848
|
+
}
|
|
14849
|
+
|
|
14850
|
+
// src/entities/monsters/fixbot.ts
|
|
14851
|
+
var MONSTER_TICK25 = 0.1;
|
|
14852
|
+
var random9 = () => Math.random();
|
|
14853
|
+
var frandom3 = () => Math.random();
|
|
14854
|
+
function monster_ai_walk21(self, dist, context) {
|
|
14855
|
+
ai_walk(self, dist, MONSTER_TICK25, context);
|
|
14856
|
+
}
|
|
14857
|
+
function monster_ai_run22(self, dist, context) {
|
|
14858
|
+
ai_run(self, dist, MONSTER_TICK25, context);
|
|
14859
|
+
}
|
|
14860
|
+
function monster_ai_charge23(self, dist, context) {
|
|
14861
|
+
ai_charge(self, dist, MONSTER_TICK25, context);
|
|
14862
|
+
}
|
|
14863
|
+
function monster_ai_move22(self, dist, context) {
|
|
14864
|
+
ai_move(self, dist);
|
|
14865
|
+
}
|
|
14866
|
+
var fixbot_move_stand;
|
|
14867
|
+
var fixbot_move_walk;
|
|
14868
|
+
var fixbot_move_run;
|
|
14869
|
+
var fixbot_move_attack2;
|
|
14870
|
+
var fixbot_move_laserattack;
|
|
14871
|
+
var fixbot_move_weld_start;
|
|
14872
|
+
var fixbot_move_weld;
|
|
14873
|
+
var fixbot_move_weld_end;
|
|
14874
|
+
var fixbot_move_start_attack;
|
|
14875
|
+
var fixbot_move_pain3;
|
|
14876
|
+
var fixbot_move_painb;
|
|
14877
|
+
var fixbot_move_paina;
|
|
14878
|
+
var MZ2_HOVER_BLASTER_1 = 1;
|
|
14879
|
+
function fixbot_set_fly_parameters(self, heal, weld) {
|
|
14880
|
+
if (heal) {
|
|
14881
|
+
} else if (weld) {
|
|
14882
|
+
} else {
|
|
14883
|
+
}
|
|
14884
|
+
}
|
|
14885
|
+
function fixbot_FindDeadMonster(self, context) {
|
|
14886
|
+
const radius = 1024;
|
|
14887
|
+
const candidates = context.findByRadius(self.origin, radius);
|
|
14888
|
+
let best = null;
|
|
14889
|
+
for (const ent of candidates) {
|
|
14890
|
+
if (ent === self) continue;
|
|
14891
|
+
if (!ent.monsterinfo) continue;
|
|
14892
|
+
if (ent.monsterinfo.aiflags & 256 /* GoodGuy */) continue;
|
|
14893
|
+
if (ent.health > 0) continue;
|
|
14894
|
+
if (ent.nextthink && ent.think === context.free) continue;
|
|
14895
|
+
if (ent.health <= -40) continue;
|
|
14896
|
+
if (!visible(self, ent, context.trace)) continue;
|
|
14897
|
+
if (!best) {
|
|
14898
|
+
best = ent;
|
|
14899
|
+
continue;
|
|
14900
|
+
}
|
|
14901
|
+
if (ent.max_health <= best.max_health) continue;
|
|
14902
|
+
best = ent;
|
|
14903
|
+
}
|
|
14904
|
+
return best;
|
|
14905
|
+
}
|
|
14906
|
+
function fixbot_search(self, context) {
|
|
14907
|
+
if (self.enemy) return;
|
|
14908
|
+
const ent = fixbot_FindDeadMonster(self, context);
|
|
14909
|
+
if (ent) {
|
|
14910
|
+
self.enemy = ent;
|
|
14911
|
+
self.monsterinfo.aiflags |= 8192 /* Medic */;
|
|
14912
|
+
fixbot_run(self);
|
|
14913
|
+
fixbot_set_fly_parameters(self, true, false);
|
|
14914
|
+
} else {
|
|
14915
|
+
if (random9() < 0.1) {
|
|
14916
|
+
context.engine.sound?.(self, 0, "flyer/flysght1.wav", 1, 1, 0);
|
|
14917
|
+
}
|
|
14918
|
+
}
|
|
14919
|
+
}
|
|
14920
|
+
function fixbot_die(self, inflictor, attacker, damage, point, mod, context) {
|
|
14921
|
+
context.engine.sound?.(self, 0, "flyer/flydeth1.wav", 1, 1, 0);
|
|
14922
|
+
throwGibs(context, self.origin, damage);
|
|
14923
|
+
self.deadflag = 2 /* Dead */;
|
|
14924
|
+
self.takedamage = false;
|
|
14925
|
+
context.free(self);
|
|
14926
|
+
}
|
|
14927
|
+
function fixbot_fire_blaster_func(self, context) {
|
|
14928
|
+
if (!self.enemy || !self.enemy.inUse) {
|
|
14929
|
+
self.monsterinfo.current_move = fixbot_move_run;
|
|
14930
|
+
return;
|
|
14931
|
+
}
|
|
14932
|
+
const vectors = angleVectors(self.angles);
|
|
14933
|
+
const start = addVec3(self.origin, addVec3(scaleVec3(vectors.forward, 0), addVec3(scaleVec3(vectors.right, 0), scaleVec3(vectors.up, 0))));
|
|
14934
|
+
const end = copyVec3(self.enemy.origin);
|
|
14935
|
+
end.z += self.enemy.viewheight || 0;
|
|
14936
|
+
const dir = normalizeVec3(subtractVec3(end, start));
|
|
14937
|
+
monster_fire_blaster(self, start, dir, 15, 1e3, MZ2_HOVER_BLASTER_1, 0, context);
|
|
14938
|
+
}
|
|
14939
|
+
function fixbot_fire_laser(self, context) {
|
|
14940
|
+
if (!self.enemy || !self.enemy.inUse || self.enemy.health <= -40) {
|
|
14941
|
+
self.monsterinfo.current_move = fixbot_move_stand;
|
|
14942
|
+
self.monsterinfo.aiflags &= ~8192 /* Medic */;
|
|
14943
|
+
return;
|
|
14944
|
+
}
|
|
14945
|
+
if (self.enemy.health < self.enemy.max_health) {
|
|
14946
|
+
self.enemy.health += 5;
|
|
14947
|
+
if (self.enemy.health > self.enemy.max_health) self.enemy.health = self.enemy.max_health;
|
|
14948
|
+
} else {
|
|
14949
|
+
if (self.enemy.deadflag === 2 /* Dead */) {
|
|
14950
|
+
self.enemy.deadflag = 0 /* Alive */;
|
|
14951
|
+
self.enemy.solid = 2 /* BoundingBox */;
|
|
14952
|
+
self.enemy.takedamage = true;
|
|
14953
|
+
self.enemy.health = self.enemy.max_health;
|
|
14954
|
+
self.enemy.monsterinfo.aiflags &= ~128 /* HoldFrame */;
|
|
14955
|
+
}
|
|
14956
|
+
self.monsterinfo.current_move = fixbot_move_stand;
|
|
14957
|
+
self.monsterinfo.aiflags &= ~8192 /* Medic */;
|
|
14958
|
+
self.enemy = null;
|
|
14959
|
+
}
|
|
14960
|
+
}
|
|
14961
|
+
function fixbot_fire_welder(self, context) {
|
|
14962
|
+
if (frandom3() > 0.8) {
|
|
14963
|
+
const r = frandom3();
|
|
14964
|
+
if (r < 0.33) context.engine.sound?.(self, 0, "misc/welder1.wav", 1, 1, 0);
|
|
14965
|
+
else if (r < 0.66) context.engine.sound?.(self, 0, "misc/welder2.wav", 1, 1, 0);
|
|
14966
|
+
else context.engine.sound?.(self, 0, "misc/welder3.wav", 1, 1, 0);
|
|
14967
|
+
}
|
|
14968
|
+
}
|
|
14969
|
+
function fixbot_pain(self, other, kick, damage, context) {
|
|
14970
|
+
if (self.timestamp < (self.pain_debounce_time || 0)) return;
|
|
14971
|
+
self.pain_debounce_time = self.timestamp + 3;
|
|
14972
|
+
context.engine.sound?.(self, 0, "flyer/flypain1.wav", 1, 1, 0);
|
|
14973
|
+
if (damage <= 10) self.monsterinfo.current_move = fixbot_move_pain3;
|
|
14974
|
+
else if (damage <= 25) self.monsterinfo.current_move = fixbot_move_painb;
|
|
14975
|
+
else self.monsterinfo.current_move = fixbot_move_paina;
|
|
14976
|
+
}
|
|
14977
|
+
function fixbot_stand(self) {
|
|
14978
|
+
self.monsterinfo.current_move = fixbot_move_stand;
|
|
14979
|
+
}
|
|
14980
|
+
function fixbot_walk(self) {
|
|
14981
|
+
self.monsterinfo.current_move = fixbot_move_walk;
|
|
14982
|
+
}
|
|
14983
|
+
function fixbot_run(self) {
|
|
14984
|
+
if (self.monsterinfo.aiflags & 1 /* StandGround */)
|
|
14985
|
+
self.monsterinfo.current_move = fixbot_move_stand;
|
|
14986
|
+
else
|
|
14987
|
+
self.monsterinfo.current_move = fixbot_move_run;
|
|
14988
|
+
}
|
|
14989
|
+
function fixbot_start_attack(self) {
|
|
14990
|
+
self.monsterinfo.current_move = fixbot_move_start_attack;
|
|
14991
|
+
}
|
|
14992
|
+
function fixbot_attack(self) {
|
|
14993
|
+
if (self.monsterinfo.aiflags & 8192 /* Medic */) {
|
|
14994
|
+
self.monsterinfo.current_move = fixbot_move_laserattack;
|
|
14995
|
+
} else {
|
|
14996
|
+
self.monsterinfo.current_move = fixbot_move_attack2;
|
|
14997
|
+
}
|
|
14998
|
+
}
|
|
14999
|
+
function weldstate(self) {
|
|
15000
|
+
if (self.goalentity && self.goalentity.health > 0) {
|
|
15001
|
+
} else {
|
|
15002
|
+
self.monsterinfo.current_move = fixbot_move_stand;
|
|
15003
|
+
}
|
|
15004
|
+
}
|
|
15005
|
+
var frames_stand3 = Array(19).fill({ ai: monster_ai_move22, dist: 0 });
|
|
15006
|
+
frames_stand3[18] = { ai: monster_ai_move22, dist: 0, think: fixbot_search };
|
|
15007
|
+
fixbot_move_stand = {
|
|
15008
|
+
firstframe: 58,
|
|
15009
|
+
// FRAME_ambient_01
|
|
15010
|
+
lastframe: 76,
|
|
15011
|
+
frames: frames_stand3,
|
|
15012
|
+
endfunc: null
|
|
15013
|
+
};
|
|
15014
|
+
var frames_walk3 = [
|
|
15015
|
+
{ ai: monster_ai_walk21, dist: 5 }
|
|
15016
|
+
];
|
|
15017
|
+
fixbot_move_walk = {
|
|
15018
|
+
firstframe: 0,
|
|
15019
|
+
lastframe: 0,
|
|
15020
|
+
frames: frames_walk3,
|
|
15021
|
+
endfunc: null
|
|
15022
|
+
};
|
|
15023
|
+
var frames_run3 = [
|
|
15024
|
+
{ ai: monster_ai_run22, dist: 10 }
|
|
15025
|
+
];
|
|
15026
|
+
fixbot_move_run = {
|
|
15027
|
+
firstframe: 0,
|
|
15028
|
+
lastframe: 0,
|
|
15029
|
+
frames: frames_run3,
|
|
15030
|
+
endfunc: null
|
|
15031
|
+
};
|
|
15032
|
+
var frames_attack22 = Array(31).fill({ ai: monster_ai_charge23, dist: 0 });
|
|
15033
|
+
frames_attack22[20] = { ai: monster_ai_charge23, dist: 0, think: fixbot_fire_blaster_func };
|
|
15034
|
+
fixbot_move_attack2 = {
|
|
15035
|
+
firstframe: 121,
|
|
15036
|
+
// FRAME_charging_01
|
|
15037
|
+
lastframe: 151,
|
|
15038
|
+
frames: frames_attack22,
|
|
15039
|
+
endfunc: fixbot_run
|
|
15040
|
+
};
|
|
15041
|
+
var frames_laserattack = Array(6).fill({ ai: monster_ai_charge23, dist: 0, think: fixbot_fire_laser });
|
|
15042
|
+
fixbot_move_laserattack = {
|
|
15043
|
+
firstframe: 115,
|
|
15044
|
+
// FRAME_shoot_01
|
|
15045
|
+
lastframe: 120,
|
|
15046
|
+
frames: frames_laserattack,
|
|
15047
|
+
endfunc: null
|
|
15048
|
+
// Loops or handled by AI?
|
|
15049
|
+
};
|
|
15050
|
+
var frames_weld_start = Array(10).fill({ ai: monster_ai_move22, dist: 0 });
|
|
15051
|
+
frames_weld_start[9] = { ai: monster_ai_move22, dist: 0, think: weldstate };
|
|
15052
|
+
fixbot_move_weld_start = {
|
|
15053
|
+
firstframe: 77,
|
|
15054
|
+
// FRAME_weldstart_01
|
|
15055
|
+
lastframe: 86,
|
|
15056
|
+
frames: frames_weld_start,
|
|
15057
|
+
endfunc: null
|
|
15058
|
+
};
|
|
15059
|
+
var frames_weld = Array(7).fill({ ai: monster_ai_move22, dist: 0, think: fixbot_fire_welder });
|
|
15060
|
+
frames_weld[6] = { ai: monster_ai_move22, dist: 0, think: weldstate };
|
|
15061
|
+
fixbot_move_weld = {
|
|
15062
|
+
firstframe: 87,
|
|
15063
|
+
// FRAME_weldmiddle_01
|
|
15064
|
+
lastframe: 93,
|
|
15065
|
+
frames: frames_weld,
|
|
15066
|
+
endfunc: null
|
|
15067
|
+
};
|
|
15068
|
+
var frames_weld_end = Array(7).fill({ ai: monster_ai_move22, dist: -2 });
|
|
15069
|
+
frames_weld_end[6] = { ai: monster_ai_move22, dist: -2, think: weldstate };
|
|
15070
|
+
fixbot_move_weld_end = {
|
|
15071
|
+
firstframe: 94,
|
|
15072
|
+
// FRAME_weldend_01
|
|
15073
|
+
lastframe: 100,
|
|
15074
|
+
frames: frames_weld_end,
|
|
15075
|
+
endfunc: null
|
|
15076
|
+
};
|
|
15077
|
+
var frames_start_attack = [
|
|
15078
|
+
{ ai: monster_ai_charge23, dist: 0 }
|
|
15079
|
+
];
|
|
15080
|
+
fixbot_move_start_attack = {
|
|
15081
|
+
firstframe: 0,
|
|
15082
|
+
lastframe: 0,
|
|
15083
|
+
frames: frames_start_attack,
|
|
15084
|
+
endfunc: fixbot_attack
|
|
15085
|
+
};
|
|
15086
|
+
var frames_pain32 = [
|
|
15087
|
+
{ ai: monster_ai_move22, dist: -1 }
|
|
15088
|
+
];
|
|
15089
|
+
fixbot_move_pain3 = {
|
|
15090
|
+
firstframe: 0,
|
|
15091
|
+
lastframe: 0,
|
|
15092
|
+
frames: frames_pain32,
|
|
15093
|
+
endfunc: fixbot_run
|
|
15094
|
+
};
|
|
15095
|
+
var frames_painb = Array(8).fill({ ai: monster_ai_move22, dist: 0 });
|
|
15096
|
+
fixbot_move_painb = {
|
|
15097
|
+
firstframe: 107,
|
|
15098
|
+
// FRAME_painb_01
|
|
15099
|
+
lastframe: 114,
|
|
15100
|
+
frames: frames_painb,
|
|
15101
|
+
endfunc: fixbot_run
|
|
15102
|
+
};
|
|
15103
|
+
var frames_paina = Array(6).fill({ ai: monster_ai_move22, dist: 0 });
|
|
15104
|
+
fixbot_move_paina = {
|
|
15105
|
+
firstframe: 101,
|
|
15106
|
+
// FRAME_paina_01
|
|
15107
|
+
lastframe: 106,
|
|
15108
|
+
frames: frames_paina,
|
|
15109
|
+
endfunc: fixbot_run
|
|
15110
|
+
};
|
|
15111
|
+
function SP_monster_fixbot(self, context) {
|
|
15112
|
+
self.classname = "monster_fixbot";
|
|
15113
|
+
self.model = "models/monsters/fixbot/tris.md2";
|
|
15114
|
+
self.mins = { x: -32, y: -32, z: -24 };
|
|
15115
|
+
self.maxs = { x: 32, y: 32, z: 24 };
|
|
15116
|
+
self.movetype = 5 /* Step */;
|
|
15117
|
+
self.solid = 2 /* BoundingBox */;
|
|
15118
|
+
self.health = 150;
|
|
15119
|
+
self.mass = 150;
|
|
15120
|
+
self.pain = (e, o, k, d) => fixbot_pain(e, o, k, d, context.entities);
|
|
15121
|
+
self.die = (e, i, a, d, p, m3) => fixbot_die(e, i, a, d, p, m3, context.entities);
|
|
15122
|
+
self.monsterinfo.stand = fixbot_stand;
|
|
15123
|
+
self.monsterinfo.walk = fixbot_walk;
|
|
15124
|
+
self.monsterinfo.run = fixbot_run;
|
|
15125
|
+
self.monsterinfo.attack = fixbot_start_attack;
|
|
15126
|
+
context.entities.linkentity(self);
|
|
15127
|
+
self.monsterinfo.current_move = fixbot_move_stand;
|
|
15128
|
+
self.think = monster_think;
|
|
15129
|
+
self.nextthink = context.entities.timeSeconds + MONSTER_TICK25;
|
|
15130
|
+
self.flags |= 1 /* Fly */;
|
|
15131
|
+
}
|
|
15132
|
+
function registerFixbotSpawns(registry) {
|
|
15133
|
+
registry.register("monster_fixbot", SP_monster_fixbot);
|
|
15134
|
+
}
|
|
15135
|
+
|
|
14081
15136
|
// src/entities/monsters/index.ts
|
|
14082
15137
|
function registerMonsterSpawns2(registry) {
|
|
14083
15138
|
registerMonsterSpawns(registry);
|
|
@@ -14104,6 +15159,8 @@ function registerMonsterSpawns2(registry) {
|
|
|
14104
15159
|
registerMakronSpawns(registry);
|
|
14105
15160
|
registerInsaneSpawns(registry);
|
|
14106
15161
|
registerActorSpawns(registry);
|
|
15162
|
+
registerGekkSpawns(registry);
|
|
15163
|
+
registerFixbotSpawns(registry);
|
|
14107
15164
|
}
|
|
14108
15165
|
|
|
14109
15166
|
// src/entities/worldspawn.ts
|
|
@@ -15414,7 +16471,7 @@ function PlayerNoise(who, where, type, context) {
|
|
|
15414
16471
|
}
|
|
15415
16472
|
|
|
15416
16473
|
// src/combat/obituary.ts
|
|
15417
|
-
var
|
|
16474
|
+
var random10 = createRandomGenerator();
|
|
15418
16475
|
var PRINT_MEDIUM = 1;
|
|
15419
16476
|
function getGender(ent) {
|
|
15420
16477
|
return "male";
|
|
@@ -15577,7 +16634,7 @@ var ANIM_PAIN = 2;
|
|
|
15577
16634
|
var ANIM_DEATH = 3;
|
|
15578
16635
|
|
|
15579
16636
|
// src/combat/weapons/firing.ts
|
|
15580
|
-
var
|
|
16637
|
+
var random11 = createRandomGenerator();
|
|
15581
16638
|
|
|
15582
16639
|
// src/entities/player.ts
|
|
15583
16640
|
function P_PlayerThink(ent, sys) {
|
|
@@ -15634,7 +16691,7 @@ function player_pain(self, damage) {
|
|
|
15634
16691
|
return;
|
|
15635
16692
|
}
|
|
15636
16693
|
self.client.anim_priority = ANIM_PAIN;
|
|
15637
|
-
const r =
|
|
16694
|
+
const r = random11.frandom();
|
|
15638
16695
|
if (r < 0.33) {
|
|
15639
16696
|
self.frame = FRAME_pain1012;
|
|
15640
16697
|
self.client.anim_end = FRAME_pain104;
|
|
@@ -15657,7 +16714,7 @@ function player_die(self, inflictor, attacker, damage, point, mod, sys) {
|
|
|
15657
16714
|
}
|
|
15658
16715
|
if (self.client) {
|
|
15659
16716
|
self.client.anim_priority = ANIM_DEATH;
|
|
15660
|
-
const r =
|
|
16717
|
+
const r = random11.frandom();
|
|
15661
16718
|
if (r < 0.33) {
|
|
15662
16719
|
self.frame = FRAME_death1012;
|
|
15663
16720
|
self.client.anim_end = FRAME_death106;
|
|
@@ -15710,25 +16767,12 @@ function player_think(self, sys) {
|
|
|
15710
16767
|
}
|
|
15711
16768
|
|
|
15712
16769
|
// src/entities/playerStats.ts
|
|
15713
|
-
var WEAPON_WHEEL_ORDER = [
|
|
15714
|
-
"blaster" /* Blaster */,
|
|
15715
|
-
"shotgun" /* Shotgun */,
|
|
15716
|
-
"supershotgun" /* SuperShotgun */,
|
|
15717
|
-
"machinegun" /* Machinegun */,
|
|
15718
|
-
"chaingun" /* Chaingun */,
|
|
15719
|
-
"grenadelauncher" /* GrenadeLauncher */,
|
|
15720
|
-
"rocketlauncher" /* RocketLauncher */,
|
|
15721
|
-
"grenades" /* HandGrenade */,
|
|
15722
|
-
"hyperblaster" /* HyperBlaster */,
|
|
15723
|
-
"railgun" /* Railgun */,
|
|
15724
|
-
"bfg10k" /* BFG10K */
|
|
15725
|
-
];
|
|
15726
16770
|
var POWERUP_TIMERS = [
|
|
15727
|
-
{ id:
|
|
15728
|
-
{ id:
|
|
15729
|
-
{ id:
|
|
15730
|
-
{ id:
|
|
15731
|
-
{ id:
|
|
16771
|
+
{ id: PowerupId.QuadDamage, priority: 1 },
|
|
16772
|
+
{ id: PowerupId.Invulnerability, priority: 2 },
|
|
16773
|
+
{ id: PowerupId.EnviroSuit, priority: 3 },
|
|
16774
|
+
{ id: PowerupId.Rebreather, priority: 4 },
|
|
16775
|
+
{ id: PowerupId.Silencer, priority: 5 }
|
|
15732
16776
|
];
|
|
15733
16777
|
function populatePlayerStats(player, timeSeconds) {
|
|
15734
16778
|
if (!player.client) return [];
|
|
@@ -15747,6 +16791,12 @@ function populatePlayerStats(player, timeSeconds) {
|
|
|
15747
16791
|
}
|
|
15748
16792
|
statArray[PlayerStat.STAT_WEAPONS_OWNED_1] = weaponBits & 65535;
|
|
15749
16793
|
statArray[PlayerStat.STAT_WEAPONS_OWNED_2] = weaponBits >> 16 & 65535;
|
|
16794
|
+
if (inventory.currentWeapon) {
|
|
16795
|
+
const index = WEAPON_WHEEL_ORDER.indexOf(inventory.currentWeapon);
|
|
16796
|
+
if (index !== -1) {
|
|
16797
|
+
statArray[PlayerStat.STAT_ACTIVE_WHEEL_WEAPON] = index;
|
|
16798
|
+
}
|
|
16799
|
+
}
|
|
15750
16800
|
statArray[PlayerStat.STAT_AMMO] = 0;
|
|
15751
16801
|
if (inventory.currentWeapon) {
|
|
15752
16802
|
const weaponItem = Object.values(WEAPON_ITEMS).find((item) => item.weaponId === inventory.currentWeapon);
|
|
@@ -16051,7 +17101,7 @@ var WEAPONS = {
|
|
|
16051
17101
|
};
|
|
16052
17102
|
|
|
16053
17103
|
// src/index.ts
|
|
16054
|
-
var
|
|
17104
|
+
var ZERO_VEC37 = { x: 0, y: 0, z: 0 };
|
|
16055
17105
|
function createGame(imports, engine, options) {
|
|
16056
17106
|
const gravity = options.gravity;
|
|
16057
17107
|
const deathmatch = options.deathmatch ?? false;
|
|
@@ -16120,26 +17170,26 @@ function createGame(imports, engine, options) {
|
|
|
16120
17170
|
};
|
|
16121
17171
|
entities.runFrame();
|
|
16122
17172
|
});
|
|
16123
|
-
let origin = { ...
|
|
16124
|
-
let velocity = { ...
|
|
17173
|
+
let origin = { ...ZERO_VEC37 };
|
|
17174
|
+
let velocity = { ...ZERO_VEC37 };
|
|
16125
17175
|
const calculateBlend = (player, time) => {
|
|
16126
17176
|
const blend = [0, 0, 0, 0];
|
|
16127
17177
|
if (!player || !player.client) return blend;
|
|
16128
17178
|
const inventory = player.client.inventory;
|
|
16129
|
-
if (inventory.powerups.has(
|
|
17179
|
+
if (inventory.powerups.has(PowerupId.QuadDamage)) {
|
|
16130
17180
|
blend[2] = 1;
|
|
16131
17181
|
blend[3] = 0.08;
|
|
16132
17182
|
}
|
|
16133
|
-
if (inventory.powerups.has(
|
|
17183
|
+
if (inventory.powerups.has(PowerupId.Invulnerability)) {
|
|
16134
17184
|
blend[0] = 1;
|
|
16135
17185
|
blend[1] = 1;
|
|
16136
17186
|
blend[3] = 0.08;
|
|
16137
17187
|
}
|
|
16138
|
-
if (inventory.powerups.has(
|
|
17188
|
+
if (inventory.powerups.has(PowerupId.EnviroSuit)) {
|
|
16139
17189
|
blend[1] = 1;
|
|
16140
17190
|
blend[3] = 0.08;
|
|
16141
17191
|
}
|
|
16142
|
-
if (inventory.powerups.has(
|
|
17192
|
+
if (inventory.powerups.has(PowerupId.Rebreather)) {
|
|
16143
17193
|
blend[0] = 0.4;
|
|
16144
17194
|
blend[1] = 1;
|
|
16145
17195
|
blend[2] = 0.4;
|
|
@@ -16203,10 +17253,10 @@ function createGame(imports, engine, options) {
|
|
|
16203
17253
|
// TODO
|
|
16204
17254
|
damageIndicators: [],
|
|
16205
17255
|
stats: player ? populatePlayerStats(player, levelClock.current.timeSeconds) : [],
|
|
16206
|
-
kick_angles: player?.client?.kick_angles ??
|
|
16207
|
-
kick_origin: player?.client?.kick_origin ??
|
|
16208
|
-
gunoffset:
|
|
16209
|
-
gunangles:
|
|
17256
|
+
kick_angles: player?.client?.kick_angles ?? ZERO_VEC37,
|
|
17257
|
+
kick_origin: player?.client?.kick_origin ?? ZERO_VEC37,
|
|
17258
|
+
gunoffset: ZERO_VEC37,
|
|
17259
|
+
gunangles: ZERO_VEC37,
|
|
16210
17260
|
gunindex: 0,
|
|
16211
17261
|
gun_frame: player?.client?.gun_frame ?? 0,
|
|
16212
17262
|
rdflags: player?.client?.rdflags ?? 0,
|
|
@@ -16220,8 +17270,8 @@ function createGame(imports, engine, options) {
|
|
|
16220
17270
|
const resetState = (startTimeMs) => {
|
|
16221
17271
|
frameLoop.reset(startTimeMs);
|
|
16222
17272
|
levelClock.start(startTimeMs);
|
|
16223
|
-
origin = { ...
|
|
16224
|
-
velocity = { ...
|
|
17273
|
+
origin = { ...ZERO_VEC37 };
|
|
17274
|
+
velocity = { ...ZERO_VEC37 };
|
|
16225
17275
|
entities.beginFrame(startTimeMs / 1e3);
|
|
16226
17276
|
entities.runFrame();
|
|
16227
17277
|
};
|
|
@@ -16249,10 +17299,10 @@ function createGame(imports, engine, options) {
|
|
|
16249
17299
|
blend: [0, 0, 0, 0],
|
|
16250
17300
|
// Stubs
|
|
16251
17301
|
stats: populatePlayerStats(player, levelClock.current.timeSeconds),
|
|
16252
|
-
kick_angles:
|
|
16253
|
-
kick_origin:
|
|
16254
|
-
gunoffset:
|
|
16255
|
-
gunangles:
|
|
17302
|
+
kick_angles: ZERO_VEC37,
|
|
17303
|
+
kick_origin: ZERO_VEC37,
|
|
17304
|
+
gunoffset: ZERO_VEC37,
|
|
17305
|
+
gunangles: ZERO_VEC37,
|
|
16256
17306
|
gunindex: 0,
|
|
16257
17307
|
pm_type: 0,
|
|
16258
17308
|
pm_time: 0,
|
|
@@ -16382,8 +17432,8 @@ function createGame(imports, engine, options) {
|
|
|
16382
17432
|
rng,
|
|
16383
17433
|
player: player?.client?.inventory
|
|
16384
17434
|
});
|
|
16385
|
-
origin = player ? { ...player.origin } : { ...
|
|
16386
|
-
velocity = player ? { ...player.velocity } : { ...
|
|
17435
|
+
origin = player ? { ...player.origin } : { ...ZERO_VEC37 };
|
|
17436
|
+
velocity = player ? { ...player.velocity } : { ...ZERO_VEC37 };
|
|
16387
17437
|
frameLoop.reset(save.level.timeSeconds * 1e3);
|
|
16388
17438
|
}
|
|
16389
17439
|
};
|