@quake2ts/cgame 0.0.739
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/dist/browser/index.global.js +10 -0
- package/dist/browser/index.global.js.map +1 -0
- package/dist/cjs/index.cjs +947 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/esm/index.js +940 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/index.cjs +1353 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +202 -0
- package/dist/index.d.ts +202 -0
- package/dist/index.js +1346 -0
- package/dist/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/hud/blends.d.ts +4 -0
- package/dist/types/hud/blends.d.ts.map +1 -0
- package/dist/types/hud/crosshair.d.ts +7 -0
- package/dist/types/hud/crosshair.d.ts.map +1 -0
- package/dist/types/hud/damage.d.ts +5 -0
- package/dist/types/hud/damage.d.ts.map +1 -0
- package/dist/types/hud/diagnostics.d.ts +3 -0
- package/dist/types/hud/diagnostics.d.ts.map +1 -0
- package/dist/types/hud/icons.d.ts +12 -0
- package/dist/types/hud/icons.d.ts.map +1 -0
- package/dist/types/hud/layout.d.ts +30 -0
- package/dist/types/hud/layout.d.ts.map +1 -0
- package/dist/types/hud/messages.d.ts +15 -0
- package/dist/types/hud/messages.d.ts.map +1 -0
- package/dist/types/hud/numbers.d.ts +3 -0
- package/dist/types/hud/numbers.d.ts.map +1 -0
- package/dist/types/hud/pickup.d.ts +4 -0
- package/dist/types/hud/pickup.d.ts.map +1 -0
- package/dist/types/hud/statusbar.d.ts +16 -0
- package/dist/types/hud/statusbar.d.ts.map +1 -0
- package/dist/types/hud/subtitles.d.ts +7 -0
- package/dist/types/hud/subtitles.d.ts.map +1 -0
- package/dist/types/hud/types.d.ts +39 -0
- package/dist/types/hud/types.d.ts.map +1 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/parse.d.ts +7 -0
- package/dist/types/parse.d.ts.map +1 -0
- package/dist/types/prediction/index.d.ts +53 -0
- package/dist/types/prediction/index.d.ts.map +1 -0
- package/dist/types/screen.d.ts +64 -0
- package/dist/types/screen.d.ts.map +1 -0
- package/dist/types/types.d.ts +109 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/view/camera.d.ts +4 -0
- package/dist/types/view/camera.d.ts.map +1 -0
- package/dist/types/view/effects.d.ts +42 -0
- package/dist/types/view/effects.d.ts.map +1 -0
- package/package.json +56 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1346 @@
|
|
|
1
|
+
import { angleVectors, clampViewAngles, ZERO_VEC3, hasPmFlag, PmFlag, dotVec3, PmType, WaterLevel, subtractVec3, lengthVec3, scaleVec3, angleMod, applyPmove, PlayerStat, PowerupId, G_GetPowerupStat, WEAPON_WHEEL_ORDER, WEAPON_AMMO_MAP, G_GetAmmoStat, ConfigStringIndex, MAX_MODELS, MAX_SOUNDS, MAX_IMAGES } from '@quake2ts/shared';
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __export = (target, all) => {
|
|
5
|
+
for (var name in all)
|
|
6
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
// src/hud/crosshair.ts
|
|
10
|
+
var crosshairPic = null;
|
|
11
|
+
var crosshairColor = [1, 1, 1, 1];
|
|
12
|
+
var CROSSHAIR_NAMES = ["ch1", "ch2", "ch3"];
|
|
13
|
+
var crosshairPics = [null, null, null];
|
|
14
|
+
var Init_Crosshair = (cgi3) => {
|
|
15
|
+
for (let i = 0; i < CROSSHAIR_NAMES.length; i++) {
|
|
16
|
+
const name = CROSSHAIR_NAMES[i];
|
|
17
|
+
try {
|
|
18
|
+
crosshairPics[i] = cgi3.Draw_RegisterPic(`pics/${name}.pcx`);
|
|
19
|
+
} catch (e) {
|
|
20
|
+
if (i === 0) {
|
|
21
|
+
try {
|
|
22
|
+
crosshairPics[i] = cgi3.Draw_RegisterPic("pics/crosshair.pcx");
|
|
23
|
+
} catch (e2) {
|
|
24
|
+
cgi3.Com_Print("Failed to load crosshair image\n");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
crosshairPic = crosshairPics[0];
|
|
30
|
+
};
|
|
31
|
+
var Draw_Crosshair = (cgi3, width, height) => {
|
|
32
|
+
if (crosshairPic) {
|
|
33
|
+
const size = cgi3.Draw_GetPicSize(crosshairPic);
|
|
34
|
+
const x = (width - size.width) / 2;
|
|
35
|
+
const y = (height - size.height) / 2;
|
|
36
|
+
cgi3.SCR_DrawColorPic(x, y, crosshairPic, { x: crosshairColor[0], y: crosshairColor[1], z: crosshairColor[2] }, crosshairColor[3]);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// src/hud/icons.ts
|
|
41
|
+
var iconPics = /* @__PURE__ */ new Map();
|
|
42
|
+
var ICON_NAMES = [
|
|
43
|
+
// Weapons
|
|
44
|
+
"w_blaster",
|
|
45
|
+
"w_shotgun",
|
|
46
|
+
"w_sshotgun",
|
|
47
|
+
"w_machinegun",
|
|
48
|
+
"w_chaingun",
|
|
49
|
+
"w_glauncher",
|
|
50
|
+
"w_rlauncher",
|
|
51
|
+
"w_hyperblaster",
|
|
52
|
+
"w_railgun",
|
|
53
|
+
"w_bfg",
|
|
54
|
+
"w_grapple",
|
|
55
|
+
// Ammo
|
|
56
|
+
"a_grenades",
|
|
57
|
+
"a_bullets",
|
|
58
|
+
"a_cells",
|
|
59
|
+
"a_rockets",
|
|
60
|
+
"a_shells",
|
|
61
|
+
"a_slugs",
|
|
62
|
+
// Powerups
|
|
63
|
+
"p_quad",
|
|
64
|
+
"p_invulnerability",
|
|
65
|
+
"p_silencer",
|
|
66
|
+
"p_rebreather",
|
|
67
|
+
"p_envirosuit",
|
|
68
|
+
"p_adrenaline",
|
|
69
|
+
"p_megahealth",
|
|
70
|
+
// Armor
|
|
71
|
+
"i_jacketarmor",
|
|
72
|
+
"i_combatarmor",
|
|
73
|
+
"i_bodyarmor",
|
|
74
|
+
"i_powerscreen",
|
|
75
|
+
"i_powershield",
|
|
76
|
+
// Keys
|
|
77
|
+
"k_datacd",
|
|
78
|
+
"k_powercube",
|
|
79
|
+
"k_pyramid",
|
|
80
|
+
"k_dataspin",
|
|
81
|
+
"k_security",
|
|
82
|
+
"k_bluekey",
|
|
83
|
+
"k_redkey"
|
|
84
|
+
];
|
|
85
|
+
var Init_Icons = (cgi3) => {
|
|
86
|
+
for (const name of ICON_NAMES) {
|
|
87
|
+
try {
|
|
88
|
+
const pic = cgi3.Draw_RegisterPic(`pics/${name}.pcx`);
|
|
89
|
+
iconPics.set(name, pic);
|
|
90
|
+
} catch (e) {
|
|
91
|
+
cgi3.Com_Print(`Failed to load HUD image: pics/${name}.pcx
|
|
92
|
+
`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
var damagePics = /* @__PURE__ */ new Map();
|
|
97
|
+
var DAMAGE_INDICATOR_NAMES = [
|
|
98
|
+
"d_left",
|
|
99
|
+
"d_right",
|
|
100
|
+
"d_up",
|
|
101
|
+
"d_down"
|
|
102
|
+
];
|
|
103
|
+
var Init_Damage = (cgi3) => {
|
|
104
|
+
for (const name of DAMAGE_INDICATOR_NAMES) {
|
|
105
|
+
try {
|
|
106
|
+
const pic = cgi3.Draw_RegisterPic(`pics/${name}.pcx`);
|
|
107
|
+
damagePics.set(name, pic);
|
|
108
|
+
} catch (e) {
|
|
109
|
+
cgi3.Com_Print(`Failed to load HUD image: pics/${name}.pcx
|
|
110
|
+
`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
var WHITE = { x: 1, y: 1, z: 1 };
|
|
115
|
+
var Draw_Damage = (cgi3, ps, width, height) => {
|
|
116
|
+
if ((!ps.damageAlpha || ps.damageAlpha <= 0) && (!ps.damageIndicators || ps.damageIndicators.length === 0)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (!ps.damageIndicators || ps.damageIndicators.length === 0) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const cx = width * 0.5;
|
|
123
|
+
const cy = height * 0.5;
|
|
124
|
+
const { forward, right } = angleVectors(ps.viewAngles);
|
|
125
|
+
const radius = Math.min(width, height) * 0.25;
|
|
126
|
+
for (const indicator of ps.damageIndicators) {
|
|
127
|
+
const localRight = dotVec3(indicator.direction, right);
|
|
128
|
+
const localForward = dotVec3(indicator.direction, forward);
|
|
129
|
+
const angle2 = Math.atan2(localForward, localRight) * (180 / Math.PI);
|
|
130
|
+
let picName = "";
|
|
131
|
+
let xOff = 0;
|
|
132
|
+
let yOff = 0;
|
|
133
|
+
if (angle2 >= 45 && angle2 < 135) {
|
|
134
|
+
picName = "d_up";
|
|
135
|
+
yOff = -radius;
|
|
136
|
+
} else if (angle2 >= -45 && angle2 < 45) {
|
|
137
|
+
picName = "d_right";
|
|
138
|
+
xOff = radius;
|
|
139
|
+
} else if (angle2 >= -135 && angle2 < -45) {
|
|
140
|
+
picName = "d_down";
|
|
141
|
+
yOff = radius;
|
|
142
|
+
} else {
|
|
143
|
+
picName = "d_left";
|
|
144
|
+
xOff = -radius;
|
|
145
|
+
}
|
|
146
|
+
const pic = damagePics.get(picName);
|
|
147
|
+
if (pic) {
|
|
148
|
+
const size = cgi3.Draw_GetPicSize(pic);
|
|
149
|
+
const x = cx + xOff - size.width * 0.5;
|
|
150
|
+
const y = cy + yOff - size.height * 0.5;
|
|
151
|
+
const alpha = Math.max(0, Math.min(1, indicator.strength));
|
|
152
|
+
cgi3.SCR_DrawColorPic(x, y, pic, WHITE, alpha);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
// src/hud/messages.ts
|
|
158
|
+
var CENTER_PRINT_DURATION = 3e3;
|
|
159
|
+
var NOTIFY_DURATION = 5e3;
|
|
160
|
+
var MAX_NOTIFY_MESSAGES = 4;
|
|
161
|
+
var MessageSystem = class {
|
|
162
|
+
constructor() {
|
|
163
|
+
this.centerPrintMsg = null;
|
|
164
|
+
this.notifyMessages = [];
|
|
165
|
+
}
|
|
166
|
+
addCenterPrint(text, now) {
|
|
167
|
+
this.centerPrintMsg = {
|
|
168
|
+
text,
|
|
169
|
+
startTime: now,
|
|
170
|
+
duration: CENTER_PRINT_DURATION
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
addNotify(text, now) {
|
|
174
|
+
this.notifyMessages.push({
|
|
175
|
+
text,
|
|
176
|
+
startTime: now,
|
|
177
|
+
duration: NOTIFY_DURATION
|
|
178
|
+
});
|
|
179
|
+
if (this.notifyMessages.length > MAX_NOTIFY_MESSAGES) {
|
|
180
|
+
this.notifyMessages.shift();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Additional methods for cgame API
|
|
184
|
+
setCenterPrint(text, now) {
|
|
185
|
+
this.centerPrintMsg = {
|
|
186
|
+
text,
|
|
187
|
+
startTime: now,
|
|
188
|
+
duration: CENTER_PRINT_DURATION
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
addNotification(text, is_chat, now) {
|
|
192
|
+
this.notifyMessages.push({
|
|
193
|
+
text,
|
|
194
|
+
startTime: now,
|
|
195
|
+
duration: NOTIFY_DURATION
|
|
196
|
+
});
|
|
197
|
+
if (this.notifyMessages.length > MAX_NOTIFY_MESSAGES) {
|
|
198
|
+
this.notifyMessages.shift();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
clearNotifications() {
|
|
202
|
+
this.notifyMessages = [];
|
|
203
|
+
}
|
|
204
|
+
clearCenterPrint() {
|
|
205
|
+
this.centerPrintMsg = null;
|
|
206
|
+
}
|
|
207
|
+
drawCenterPrint(cgi3, now, layout) {
|
|
208
|
+
if (!this.centerPrintMsg) return;
|
|
209
|
+
if (now > this.centerPrintMsg.startTime + this.centerPrintMsg.duration) {
|
|
210
|
+
this.centerPrintMsg = null;
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const y = layout.CENTER_PRINT_Y;
|
|
214
|
+
cgi3.SCR_DrawCenterString(y, this.centerPrintMsg.text);
|
|
215
|
+
}
|
|
216
|
+
drawNotifications(cgi3, now) {
|
|
217
|
+
while (this.notifyMessages.length > 0 && now > this.notifyMessages[0].startTime + this.notifyMessages[0].duration) {
|
|
218
|
+
this.notifyMessages.shift();
|
|
219
|
+
}
|
|
220
|
+
let y = 10;
|
|
221
|
+
for (const msg of this.notifyMessages) {
|
|
222
|
+
cgi3.SCR_DrawFontString(10, y, msg.text);
|
|
223
|
+
y += cgi3.SCR_FontLineHeight();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// src/hud/subtitles.ts
|
|
229
|
+
var SUBTITLE_DURATION = 3e3;
|
|
230
|
+
var SubtitleSystem = class {
|
|
231
|
+
constructor() {
|
|
232
|
+
this.subtitle = null;
|
|
233
|
+
}
|
|
234
|
+
addSubtitle(text, now) {
|
|
235
|
+
this.subtitle = {
|
|
236
|
+
text,
|
|
237
|
+
startTime: now,
|
|
238
|
+
duration: SUBTITLE_DURATION
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
drawSubtitles(cgi3, now) {
|
|
242
|
+
if (!this.subtitle) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (now > this.subtitle.startTime + this.subtitle.duration) {
|
|
246
|
+
this.subtitle = null;
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const y = 200;
|
|
250
|
+
cgi3.SCR_DrawCenterString(y, this.subtitle.text);
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// src/hud/blends.ts
|
|
255
|
+
var Draw_Blends = (cgi3, ps, width, height) => {
|
|
256
|
+
if (!ps.blend) return;
|
|
257
|
+
const [r, g, b, a] = ps.blend;
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
// src/hud/pickup.ts
|
|
261
|
+
var Draw_Pickup = (cgi3, ps, width, height) => {
|
|
262
|
+
if (!ps.pickupIcon) return;
|
|
263
|
+
const icon = iconPics.get(ps.pickupIcon);
|
|
264
|
+
if (icon) {
|
|
265
|
+
const size = cgi3.Draw_GetPicSize(icon);
|
|
266
|
+
const x = width - size.width - 10;
|
|
267
|
+
const y = height - size.height - 10;
|
|
268
|
+
cgi3.SCR_DrawPic(x, y, icon);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
// src/hud/numbers.ts
|
|
273
|
+
var Draw_Number = (cgi3, x, y, value, pics, width, color) => {
|
|
274
|
+
const s = Math.abs(value).toString();
|
|
275
|
+
for (let i = 0; i < s.length; i++) {
|
|
276
|
+
const digit = parseInt(s[i]);
|
|
277
|
+
const pic = pics[digit];
|
|
278
|
+
if (pic) {
|
|
279
|
+
if (color) {
|
|
280
|
+
cgi3.SCR_DrawColorPic(x + i * width, y, pic, { x: color[0], y: color[1], z: color[2] }, color[3]);
|
|
281
|
+
} else {
|
|
282
|
+
cgi3.SCR_DrawPic(x + i * width, y, pic);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
var Draw_StatusBar = (cgi3, ps, hudNumberPics2, numberWidth2, timeMs, layout) => {
|
|
288
|
+
const health = ps.stats[PlayerStat.STAT_HEALTH] || 0;
|
|
289
|
+
const armor = ps.stats[PlayerStat.STAT_ARMOR] || 0;
|
|
290
|
+
const ammo = ps.stats[PlayerStat.STAT_AMMO] || 0;
|
|
291
|
+
const armorIconIdx = ps.stats[PlayerStat.STAT_ARMOR_ICON] || 0;
|
|
292
|
+
let healthColor = void 0;
|
|
293
|
+
if (health <= 25) {
|
|
294
|
+
{
|
|
295
|
+
healthColor = [1, 0, 0, 1];
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (hudNumberPics2.length > 0) {
|
|
299
|
+
Draw_Number(cgi3, layout.HEALTH_X, layout.HEALTH_Y, health, hudNumberPics2, numberWidth2, healthColor);
|
|
300
|
+
Draw_Number(cgi3, layout.ARMOR_X, layout.ARMOR_Y, armor, hudNumberPics2, numberWidth2);
|
|
301
|
+
Draw_Number(cgi3, layout.AMMO_X, layout.AMMO_Y, ammo, hudNumberPics2, numberWidth2);
|
|
302
|
+
}
|
|
303
|
+
if (armorIconIdx > 0) {
|
|
304
|
+
const iconName = cgi3.get_configstring(ConfigStringIndex.Images + armorIconIdx);
|
|
305
|
+
if (iconName) {
|
|
306
|
+
const icon = cgi3.Draw_RegisterPic(iconName);
|
|
307
|
+
if (icon) {
|
|
308
|
+
cgi3.SCR_DrawPic(layout.ARMOR_X - 24, layout.ARMOR_Y - 2, icon);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
if (ps.pickupIcon) {
|
|
313
|
+
const icon = cgi3.Draw_RegisterPic(ps.pickupIcon);
|
|
314
|
+
if (icon) {
|
|
315
|
+
cgi3.SCR_DrawPic(layout.WEAPON_ICON_X, layout.WEAPON_ICON_Y, icon);
|
|
316
|
+
}
|
|
317
|
+
} else {
|
|
318
|
+
const selectedIconIdx = ps.stats[PlayerStat.STAT_SELECTED_ICON] || 0;
|
|
319
|
+
if (selectedIconIdx > 0) {
|
|
320
|
+
const iconName = cgi3.get_configstring(ConfigStringIndex.Images + selectedIconIdx);
|
|
321
|
+
if (iconName) {
|
|
322
|
+
const icon = cgi3.Draw_RegisterPic(iconName);
|
|
323
|
+
if (icon) {
|
|
324
|
+
cgi3.SCR_DrawPic(layout.WEAPON_ICON_X, layout.WEAPON_ICON_Y, icon);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
// src/hud/layout.ts
|
|
332
|
+
var REFERENCE_WIDTH = 640;
|
|
333
|
+
var REFERENCE_HEIGHT = 480;
|
|
334
|
+
var getHudLayout = (width, height) => {
|
|
335
|
+
const scaleX = width / REFERENCE_WIDTH;
|
|
336
|
+
const scaleY = height / REFERENCE_HEIGHT;
|
|
337
|
+
const scale2 = Math.min(scaleX, scaleY);
|
|
338
|
+
return {
|
|
339
|
+
// Status bar numbers - Anchored Bottom-Left / Center / Right
|
|
340
|
+
HEALTH_X: 100 * scale2,
|
|
341
|
+
HEALTH_Y: height - (REFERENCE_HEIGHT - 450) * scale2,
|
|
342
|
+
ARMOR_X: 200 * scale2,
|
|
343
|
+
ARMOR_Y: height - (REFERENCE_HEIGHT - 450) * scale2,
|
|
344
|
+
AMMO_X: width - (REFERENCE_WIDTH - 540) * scale2,
|
|
345
|
+
// Anchor right? 540 is near right (640)
|
|
346
|
+
AMMO_Y: height - (REFERENCE_HEIGHT - 450) * scale2,
|
|
347
|
+
// Center print messages - Center
|
|
348
|
+
CENTER_PRINT_X: width / 2,
|
|
349
|
+
CENTER_PRINT_Y: 100 * scale2,
|
|
350
|
+
// Top anchor
|
|
351
|
+
// Weapon and powerup icons
|
|
352
|
+
WEAPON_ICON_X: 10 * scale2,
|
|
353
|
+
WEAPON_ICON_Y: height - (REFERENCE_HEIGHT - 450) * scale2,
|
|
354
|
+
POWERUP_X: width - (REFERENCE_WIDTH - 610) * scale2,
|
|
355
|
+
POWERUP_Y: height - (REFERENCE_HEIGHT - 450) * scale2,
|
|
356
|
+
scale: scale2
|
|
357
|
+
};
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
// src/screen.ts
|
|
361
|
+
var cgi = null;
|
|
362
|
+
var hudNumberPics = [];
|
|
363
|
+
var numberWidth = 0;
|
|
364
|
+
var messageSystem = new MessageSystem();
|
|
365
|
+
var subtitleSystem = new SubtitleSystem();
|
|
366
|
+
function CG_InitScreen(imports) {
|
|
367
|
+
cgi = imports;
|
|
368
|
+
}
|
|
369
|
+
function CG_TouchPics() {
|
|
370
|
+
if (!cgi) return;
|
|
371
|
+
hudNumberPics.length = 0;
|
|
372
|
+
for (let i = 0; i < 10; i++) {
|
|
373
|
+
try {
|
|
374
|
+
const pic = cgi.Draw_RegisterPic(`pics/hud/num_${i}.pcx`);
|
|
375
|
+
hudNumberPics.push(pic);
|
|
376
|
+
if (i === 0) {
|
|
377
|
+
const size = cgi.Draw_GetPicSize(pic);
|
|
378
|
+
numberWidth = size.width;
|
|
379
|
+
}
|
|
380
|
+
} catch (e) {
|
|
381
|
+
cgi.Com_Print(`Warning: Failed to load HUD image: pics/hud/num_${i}.pcx
|
|
382
|
+
`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
Init_Crosshair(cgi);
|
|
386
|
+
Init_Icons(cgi);
|
|
387
|
+
Init_Damage(cgi);
|
|
388
|
+
}
|
|
389
|
+
function CG_DrawHUD(isplit, data, hud_vrect, hud_safe, scale2, playernum, ps) {
|
|
390
|
+
if (!cgi) {
|
|
391
|
+
console.error("CG_DrawHUD: cgame imports not initialized");
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
const timeMs = cgi.CL_ClientTime();
|
|
395
|
+
const layout = getHudLayout(hud_vrect.width, hud_vrect.height);
|
|
396
|
+
Draw_Blends(cgi, ps, hud_vrect.width, hud_vrect.height);
|
|
397
|
+
Draw_StatusBar(cgi, ps, hudNumberPics, numberWidth, timeMs, layout);
|
|
398
|
+
Draw_Pickup(cgi, ps, hud_vrect.width, hud_vrect.height);
|
|
399
|
+
Draw_Damage(cgi, ps, hud_vrect.width, hud_vrect.height);
|
|
400
|
+
if (ps.centerPrint) {
|
|
401
|
+
const lines = ps.centerPrint.split("\n");
|
|
402
|
+
let y = hud_vrect.height / 2 - lines.length * 10;
|
|
403
|
+
for (const line of lines) {
|
|
404
|
+
cgi.SCR_DrawCenterString(y, line);
|
|
405
|
+
y += 16;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
messageSystem.drawCenterPrint(cgi, timeMs, layout);
|
|
409
|
+
messageSystem.drawNotifications(cgi, timeMs);
|
|
410
|
+
subtitleSystem.drawSubtitles(cgi, timeMs);
|
|
411
|
+
Draw_Crosshair(cgi, hud_vrect.width, hud_vrect.height);
|
|
412
|
+
}
|
|
413
|
+
function CG_GetMessageSystem() {
|
|
414
|
+
return messageSystem;
|
|
415
|
+
}
|
|
416
|
+
function CG_GetSubtitleSystem() {
|
|
417
|
+
return subtitleSystem;
|
|
418
|
+
}
|
|
419
|
+
function CG_ParseConfigString(cgi3, i, s) {
|
|
420
|
+
if (i >= ConfigStringIndex.Models && i < ConfigStringIndex.Models + MAX_MODELS) {
|
|
421
|
+
cgi3.RegisterModel(s);
|
|
422
|
+
} else if (i >= ConfigStringIndex.Sounds && i < ConfigStringIndex.Sounds + MAX_SOUNDS) {
|
|
423
|
+
cgi3.RegisterSound(s);
|
|
424
|
+
} else if (i >= ConfigStringIndex.Images && i < ConfigStringIndex.Images + MAX_IMAGES) {
|
|
425
|
+
cgi3.Draw_RegisterPic(s);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// ../../node_modules/.pnpm/gl-matrix@3.4.4/node_modules/gl-matrix/esm/common.js
|
|
430
|
+
var EPSILON = 1e-6;
|
|
431
|
+
var ARRAY_TYPE = typeof Float32Array !== "undefined" ? Float32Array : Array;
|
|
432
|
+
var RANDOM = Math.random;
|
|
433
|
+
function round(a) {
|
|
434
|
+
if (a >= 0) return Math.round(a);
|
|
435
|
+
return a % 0.5 === 0 ? Math.floor(a) : Math.round(a);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// ../../node_modules/.pnpm/gl-matrix@3.4.4/node_modules/gl-matrix/esm/vec3.js
|
|
439
|
+
var vec3_exports = {};
|
|
440
|
+
__export(vec3_exports, {
|
|
441
|
+
add: () => add,
|
|
442
|
+
angle: () => angle,
|
|
443
|
+
bezier: () => bezier,
|
|
444
|
+
ceil: () => ceil,
|
|
445
|
+
clone: () => clone,
|
|
446
|
+
copy: () => copy,
|
|
447
|
+
create: () => create,
|
|
448
|
+
cross: () => cross,
|
|
449
|
+
dist: () => dist,
|
|
450
|
+
distance: () => distance,
|
|
451
|
+
div: () => div,
|
|
452
|
+
divide: () => divide,
|
|
453
|
+
dot: () => dot,
|
|
454
|
+
equals: () => equals,
|
|
455
|
+
exactEquals: () => exactEquals,
|
|
456
|
+
floor: () => floor,
|
|
457
|
+
forEach: () => forEach,
|
|
458
|
+
fromValues: () => fromValues,
|
|
459
|
+
hermite: () => hermite,
|
|
460
|
+
inverse: () => inverse,
|
|
461
|
+
len: () => len,
|
|
462
|
+
length: () => length,
|
|
463
|
+
lerp: () => lerp,
|
|
464
|
+
max: () => max,
|
|
465
|
+
min: () => min,
|
|
466
|
+
mul: () => mul,
|
|
467
|
+
multiply: () => multiply,
|
|
468
|
+
negate: () => negate,
|
|
469
|
+
normalize: () => normalize,
|
|
470
|
+
random: () => random,
|
|
471
|
+
rotateX: () => rotateX,
|
|
472
|
+
rotateY: () => rotateY,
|
|
473
|
+
rotateZ: () => rotateZ,
|
|
474
|
+
round: () => round2,
|
|
475
|
+
scale: () => scale,
|
|
476
|
+
scaleAndAdd: () => scaleAndAdd,
|
|
477
|
+
set: () => set,
|
|
478
|
+
slerp: () => slerp,
|
|
479
|
+
sqrDist: () => sqrDist,
|
|
480
|
+
sqrLen: () => sqrLen,
|
|
481
|
+
squaredDistance: () => squaredDistance,
|
|
482
|
+
squaredLength: () => squaredLength,
|
|
483
|
+
str: () => str,
|
|
484
|
+
sub: () => sub,
|
|
485
|
+
subtract: () => subtract,
|
|
486
|
+
transformMat3: () => transformMat3,
|
|
487
|
+
transformMat4: () => transformMat4,
|
|
488
|
+
transformQuat: () => transformQuat,
|
|
489
|
+
zero: () => zero
|
|
490
|
+
});
|
|
491
|
+
function create() {
|
|
492
|
+
var out = new ARRAY_TYPE(3);
|
|
493
|
+
if (ARRAY_TYPE != Float32Array) {
|
|
494
|
+
out[0] = 0;
|
|
495
|
+
out[1] = 0;
|
|
496
|
+
out[2] = 0;
|
|
497
|
+
}
|
|
498
|
+
return out;
|
|
499
|
+
}
|
|
500
|
+
function clone(a) {
|
|
501
|
+
var out = new ARRAY_TYPE(3);
|
|
502
|
+
out[0] = a[0];
|
|
503
|
+
out[1] = a[1];
|
|
504
|
+
out[2] = a[2];
|
|
505
|
+
return out;
|
|
506
|
+
}
|
|
507
|
+
function length(a) {
|
|
508
|
+
var x = a[0];
|
|
509
|
+
var y = a[1];
|
|
510
|
+
var z = a[2];
|
|
511
|
+
return Math.sqrt(x * x + y * y + z * z);
|
|
512
|
+
}
|
|
513
|
+
function fromValues(x, y, z) {
|
|
514
|
+
var out = new ARRAY_TYPE(3);
|
|
515
|
+
out[0] = x;
|
|
516
|
+
out[1] = y;
|
|
517
|
+
out[2] = z;
|
|
518
|
+
return out;
|
|
519
|
+
}
|
|
520
|
+
function copy(out, a) {
|
|
521
|
+
out[0] = a[0];
|
|
522
|
+
out[1] = a[1];
|
|
523
|
+
out[2] = a[2];
|
|
524
|
+
return out;
|
|
525
|
+
}
|
|
526
|
+
function set(out, x, y, z) {
|
|
527
|
+
out[0] = x;
|
|
528
|
+
out[1] = y;
|
|
529
|
+
out[2] = z;
|
|
530
|
+
return out;
|
|
531
|
+
}
|
|
532
|
+
function add(out, a, b) {
|
|
533
|
+
out[0] = a[0] + b[0];
|
|
534
|
+
out[1] = a[1] + b[1];
|
|
535
|
+
out[2] = a[2] + b[2];
|
|
536
|
+
return out;
|
|
537
|
+
}
|
|
538
|
+
function subtract(out, a, b) {
|
|
539
|
+
out[0] = a[0] - b[0];
|
|
540
|
+
out[1] = a[1] - b[1];
|
|
541
|
+
out[2] = a[2] - b[2];
|
|
542
|
+
return out;
|
|
543
|
+
}
|
|
544
|
+
function multiply(out, a, b) {
|
|
545
|
+
out[0] = a[0] * b[0];
|
|
546
|
+
out[1] = a[1] * b[1];
|
|
547
|
+
out[2] = a[2] * b[2];
|
|
548
|
+
return out;
|
|
549
|
+
}
|
|
550
|
+
function divide(out, a, b) {
|
|
551
|
+
out[0] = a[0] / b[0];
|
|
552
|
+
out[1] = a[1] / b[1];
|
|
553
|
+
out[2] = a[2] / b[2];
|
|
554
|
+
return out;
|
|
555
|
+
}
|
|
556
|
+
function ceil(out, a) {
|
|
557
|
+
out[0] = Math.ceil(a[0]);
|
|
558
|
+
out[1] = Math.ceil(a[1]);
|
|
559
|
+
out[2] = Math.ceil(a[2]);
|
|
560
|
+
return out;
|
|
561
|
+
}
|
|
562
|
+
function floor(out, a) {
|
|
563
|
+
out[0] = Math.floor(a[0]);
|
|
564
|
+
out[1] = Math.floor(a[1]);
|
|
565
|
+
out[2] = Math.floor(a[2]);
|
|
566
|
+
return out;
|
|
567
|
+
}
|
|
568
|
+
function min(out, a, b) {
|
|
569
|
+
out[0] = Math.min(a[0], b[0]);
|
|
570
|
+
out[1] = Math.min(a[1], b[1]);
|
|
571
|
+
out[2] = Math.min(a[2], b[2]);
|
|
572
|
+
return out;
|
|
573
|
+
}
|
|
574
|
+
function max(out, a, b) {
|
|
575
|
+
out[0] = Math.max(a[0], b[0]);
|
|
576
|
+
out[1] = Math.max(a[1], b[1]);
|
|
577
|
+
out[2] = Math.max(a[2], b[2]);
|
|
578
|
+
return out;
|
|
579
|
+
}
|
|
580
|
+
function round2(out, a) {
|
|
581
|
+
out[0] = round(a[0]);
|
|
582
|
+
out[1] = round(a[1]);
|
|
583
|
+
out[2] = round(a[2]);
|
|
584
|
+
return out;
|
|
585
|
+
}
|
|
586
|
+
function scale(out, a, b) {
|
|
587
|
+
out[0] = a[0] * b;
|
|
588
|
+
out[1] = a[1] * b;
|
|
589
|
+
out[2] = a[2] * b;
|
|
590
|
+
return out;
|
|
591
|
+
}
|
|
592
|
+
function scaleAndAdd(out, a, b, scale2) {
|
|
593
|
+
out[0] = a[0] + b[0] * scale2;
|
|
594
|
+
out[1] = a[1] + b[1] * scale2;
|
|
595
|
+
out[2] = a[2] + b[2] * scale2;
|
|
596
|
+
return out;
|
|
597
|
+
}
|
|
598
|
+
function distance(a, b) {
|
|
599
|
+
var x = b[0] - a[0];
|
|
600
|
+
var y = b[1] - a[1];
|
|
601
|
+
var z = b[2] - a[2];
|
|
602
|
+
return Math.sqrt(x * x + y * y + z * z);
|
|
603
|
+
}
|
|
604
|
+
function squaredDistance(a, b) {
|
|
605
|
+
var x = b[0] - a[0];
|
|
606
|
+
var y = b[1] - a[1];
|
|
607
|
+
var z = b[2] - a[2];
|
|
608
|
+
return x * x + y * y + z * z;
|
|
609
|
+
}
|
|
610
|
+
function squaredLength(a) {
|
|
611
|
+
var x = a[0];
|
|
612
|
+
var y = a[1];
|
|
613
|
+
var z = a[2];
|
|
614
|
+
return x * x + y * y + z * z;
|
|
615
|
+
}
|
|
616
|
+
function negate(out, a) {
|
|
617
|
+
out[0] = -a[0];
|
|
618
|
+
out[1] = -a[1];
|
|
619
|
+
out[2] = -a[2];
|
|
620
|
+
return out;
|
|
621
|
+
}
|
|
622
|
+
function inverse(out, a) {
|
|
623
|
+
out[0] = 1 / a[0];
|
|
624
|
+
out[1] = 1 / a[1];
|
|
625
|
+
out[2] = 1 / a[2];
|
|
626
|
+
return out;
|
|
627
|
+
}
|
|
628
|
+
function normalize(out, a) {
|
|
629
|
+
var x = a[0];
|
|
630
|
+
var y = a[1];
|
|
631
|
+
var z = a[2];
|
|
632
|
+
var len2 = x * x + y * y + z * z;
|
|
633
|
+
if (len2 > 0) {
|
|
634
|
+
len2 = 1 / Math.sqrt(len2);
|
|
635
|
+
}
|
|
636
|
+
out[0] = a[0] * len2;
|
|
637
|
+
out[1] = a[1] * len2;
|
|
638
|
+
out[2] = a[2] * len2;
|
|
639
|
+
return out;
|
|
640
|
+
}
|
|
641
|
+
function dot(a, b) {
|
|
642
|
+
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
643
|
+
}
|
|
644
|
+
function cross(out, a, b) {
|
|
645
|
+
var ax = a[0], ay = a[1], az = a[2];
|
|
646
|
+
var bx = b[0], by = b[1], bz = b[2];
|
|
647
|
+
out[0] = ay * bz - az * by;
|
|
648
|
+
out[1] = az * bx - ax * bz;
|
|
649
|
+
out[2] = ax * by - ay * bx;
|
|
650
|
+
return out;
|
|
651
|
+
}
|
|
652
|
+
function lerp(out, a, b, t) {
|
|
653
|
+
var ax = a[0];
|
|
654
|
+
var ay = a[1];
|
|
655
|
+
var az = a[2];
|
|
656
|
+
out[0] = ax + t * (b[0] - ax);
|
|
657
|
+
out[1] = ay + t * (b[1] - ay);
|
|
658
|
+
out[2] = az + t * (b[2] - az);
|
|
659
|
+
return out;
|
|
660
|
+
}
|
|
661
|
+
function slerp(out, a, b, t) {
|
|
662
|
+
var angle2 = Math.acos(Math.min(Math.max(dot(a, b), -1), 1));
|
|
663
|
+
var sinTotal = Math.sin(angle2);
|
|
664
|
+
var ratioA = Math.sin((1 - t) * angle2) / sinTotal;
|
|
665
|
+
var ratioB = Math.sin(t * angle2) / sinTotal;
|
|
666
|
+
out[0] = ratioA * a[0] + ratioB * b[0];
|
|
667
|
+
out[1] = ratioA * a[1] + ratioB * b[1];
|
|
668
|
+
out[2] = ratioA * a[2] + ratioB * b[2];
|
|
669
|
+
return out;
|
|
670
|
+
}
|
|
671
|
+
function hermite(out, a, b, c, d, t) {
|
|
672
|
+
var factorTimes2 = t * t;
|
|
673
|
+
var factor1 = factorTimes2 * (2 * t - 3) + 1;
|
|
674
|
+
var factor2 = factorTimes2 * (t - 2) + t;
|
|
675
|
+
var factor3 = factorTimes2 * (t - 1);
|
|
676
|
+
var factor4 = factorTimes2 * (3 - 2 * t);
|
|
677
|
+
out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
|
|
678
|
+
out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
|
|
679
|
+
out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
|
|
680
|
+
return out;
|
|
681
|
+
}
|
|
682
|
+
function bezier(out, a, b, c, d, t) {
|
|
683
|
+
var inverseFactor = 1 - t;
|
|
684
|
+
var inverseFactorTimesTwo = inverseFactor * inverseFactor;
|
|
685
|
+
var factorTimes2 = t * t;
|
|
686
|
+
var factor1 = inverseFactorTimesTwo * inverseFactor;
|
|
687
|
+
var factor2 = 3 * t * inverseFactorTimesTwo;
|
|
688
|
+
var factor3 = 3 * factorTimes2 * inverseFactor;
|
|
689
|
+
var factor4 = factorTimes2 * t;
|
|
690
|
+
out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
|
|
691
|
+
out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
|
|
692
|
+
out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
|
|
693
|
+
return out;
|
|
694
|
+
}
|
|
695
|
+
function random(out, scale2) {
|
|
696
|
+
scale2 = scale2 === void 0 ? 1 : scale2;
|
|
697
|
+
var r = RANDOM() * 2 * Math.PI;
|
|
698
|
+
var z = RANDOM() * 2 - 1;
|
|
699
|
+
var zScale = Math.sqrt(1 - z * z) * scale2;
|
|
700
|
+
out[0] = Math.cos(r) * zScale;
|
|
701
|
+
out[1] = Math.sin(r) * zScale;
|
|
702
|
+
out[2] = z * scale2;
|
|
703
|
+
return out;
|
|
704
|
+
}
|
|
705
|
+
function transformMat4(out, a, m) {
|
|
706
|
+
var x = a[0], y = a[1], z = a[2];
|
|
707
|
+
var w = m[3] * x + m[7] * y + m[11] * z + m[15];
|
|
708
|
+
w = w || 1;
|
|
709
|
+
out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
|
|
710
|
+
out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
|
|
711
|
+
out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
|
|
712
|
+
return out;
|
|
713
|
+
}
|
|
714
|
+
function transformMat3(out, a, m) {
|
|
715
|
+
var x = a[0], y = a[1], z = a[2];
|
|
716
|
+
out[0] = x * m[0] + y * m[3] + z * m[6];
|
|
717
|
+
out[1] = x * m[1] + y * m[4] + z * m[7];
|
|
718
|
+
out[2] = x * m[2] + y * m[5] + z * m[8];
|
|
719
|
+
return out;
|
|
720
|
+
}
|
|
721
|
+
function transformQuat(out, a, q) {
|
|
722
|
+
var qx = q[0], qy = q[1], qz = q[2], qw = q[3];
|
|
723
|
+
var vx = a[0], vy = a[1], vz = a[2];
|
|
724
|
+
var tx = qy * vz - qz * vy;
|
|
725
|
+
var ty = qz * vx - qx * vz;
|
|
726
|
+
var tz = qx * vy - qy * vx;
|
|
727
|
+
tx = tx + tx;
|
|
728
|
+
ty = ty + ty;
|
|
729
|
+
tz = tz + tz;
|
|
730
|
+
out[0] = vx + qw * tx + qy * tz - qz * ty;
|
|
731
|
+
out[1] = vy + qw * ty + qz * tx - qx * tz;
|
|
732
|
+
out[2] = vz + qw * tz + qx * ty - qy * tx;
|
|
733
|
+
return out;
|
|
734
|
+
}
|
|
735
|
+
function rotateX(out, a, b, rad) {
|
|
736
|
+
var p = [], r = [];
|
|
737
|
+
p[0] = a[0] - b[0];
|
|
738
|
+
p[1] = a[1] - b[1];
|
|
739
|
+
p[2] = a[2] - b[2];
|
|
740
|
+
r[0] = p[0];
|
|
741
|
+
r[1] = p[1] * Math.cos(rad) - p[2] * Math.sin(rad);
|
|
742
|
+
r[2] = p[1] * Math.sin(rad) + p[2] * Math.cos(rad);
|
|
743
|
+
out[0] = r[0] + b[0];
|
|
744
|
+
out[1] = r[1] + b[1];
|
|
745
|
+
out[2] = r[2] + b[2];
|
|
746
|
+
return out;
|
|
747
|
+
}
|
|
748
|
+
function rotateY(out, a, b, rad) {
|
|
749
|
+
var p = [], r = [];
|
|
750
|
+
p[0] = a[0] - b[0];
|
|
751
|
+
p[1] = a[1] - b[1];
|
|
752
|
+
p[2] = a[2] - b[2];
|
|
753
|
+
r[0] = p[2] * Math.sin(rad) + p[0] * Math.cos(rad);
|
|
754
|
+
r[1] = p[1];
|
|
755
|
+
r[2] = p[2] * Math.cos(rad) - p[0] * Math.sin(rad);
|
|
756
|
+
out[0] = r[0] + b[0];
|
|
757
|
+
out[1] = r[1] + b[1];
|
|
758
|
+
out[2] = r[2] + b[2];
|
|
759
|
+
return out;
|
|
760
|
+
}
|
|
761
|
+
function rotateZ(out, a, b, rad) {
|
|
762
|
+
var p = [], r = [];
|
|
763
|
+
p[0] = a[0] - b[0];
|
|
764
|
+
p[1] = a[1] - b[1];
|
|
765
|
+
p[2] = a[2] - b[2];
|
|
766
|
+
r[0] = p[0] * Math.cos(rad) - p[1] * Math.sin(rad);
|
|
767
|
+
r[1] = p[0] * Math.sin(rad) + p[1] * Math.cos(rad);
|
|
768
|
+
r[2] = p[2];
|
|
769
|
+
out[0] = r[0] + b[0];
|
|
770
|
+
out[1] = r[1] + b[1];
|
|
771
|
+
out[2] = r[2] + b[2];
|
|
772
|
+
return out;
|
|
773
|
+
}
|
|
774
|
+
function angle(a, b) {
|
|
775
|
+
var ax = a[0], ay = a[1], az = a[2], bx = b[0], by = b[1], bz = b[2], mag = Math.sqrt((ax * ax + ay * ay + az * az) * (bx * bx + by * by + bz * bz)), cosine = mag && dot(a, b) / mag;
|
|
776
|
+
return Math.acos(Math.min(Math.max(cosine, -1), 1));
|
|
777
|
+
}
|
|
778
|
+
function zero(out) {
|
|
779
|
+
out[0] = 0;
|
|
780
|
+
out[1] = 0;
|
|
781
|
+
out[2] = 0;
|
|
782
|
+
return out;
|
|
783
|
+
}
|
|
784
|
+
function str(a) {
|
|
785
|
+
return "vec3(" + a[0] + ", " + a[1] + ", " + a[2] + ")";
|
|
786
|
+
}
|
|
787
|
+
function exactEquals(a, b) {
|
|
788
|
+
return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];
|
|
789
|
+
}
|
|
790
|
+
function equals(a, b) {
|
|
791
|
+
var a0 = a[0], a1 = a[1], a2 = a[2];
|
|
792
|
+
var b0 = b[0], b1 = b[1], b2 = b[2];
|
|
793
|
+
return Math.abs(a0 - b0) <= EPSILON * Math.max(1, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1, Math.abs(a2), Math.abs(b2));
|
|
794
|
+
}
|
|
795
|
+
var sub = subtract;
|
|
796
|
+
var mul = multiply;
|
|
797
|
+
var div = divide;
|
|
798
|
+
var dist = distance;
|
|
799
|
+
var sqrDist = squaredDistance;
|
|
800
|
+
var len = length;
|
|
801
|
+
var sqrLen = squaredLength;
|
|
802
|
+
var forEach = (function() {
|
|
803
|
+
var vec = create();
|
|
804
|
+
return function(a, stride, offset, count, fn, arg) {
|
|
805
|
+
var i, l;
|
|
806
|
+
if (!stride) {
|
|
807
|
+
stride = 3;
|
|
808
|
+
}
|
|
809
|
+
if (!offset) {
|
|
810
|
+
offset = 0;
|
|
811
|
+
}
|
|
812
|
+
if (count) {
|
|
813
|
+
l = Math.min(count * stride + offset, a.length);
|
|
814
|
+
} else {
|
|
815
|
+
l = a.length;
|
|
816
|
+
}
|
|
817
|
+
for (i = offset; i < l; i += stride) {
|
|
818
|
+
vec[0] = a[i];
|
|
819
|
+
vec[1] = a[i + 1];
|
|
820
|
+
vec[2] = a[i + 2];
|
|
821
|
+
fn(vec, vec, arg);
|
|
822
|
+
a[i] = vec[0];
|
|
823
|
+
a[i + 1] = vec[1];
|
|
824
|
+
a[i + 2] = vec[2];
|
|
825
|
+
}
|
|
826
|
+
return a;
|
|
827
|
+
};
|
|
828
|
+
})();
|
|
829
|
+
|
|
830
|
+
// src/view/camera.ts
|
|
831
|
+
var toGlMatrixVec3 = (v) => {
|
|
832
|
+
return vec3_exports.fromValues(v.x, v.y, v.z);
|
|
833
|
+
};
|
|
834
|
+
var updateCamera = (camera, viewSample) => {
|
|
835
|
+
camera.bobAngles = toGlMatrixVec3(viewSample.angles);
|
|
836
|
+
camera.bobOffset = toGlMatrixVec3(viewSample.offset);
|
|
837
|
+
};
|
|
838
|
+
var DEFAULT_SETTINGS = {
|
|
839
|
+
runPitch: 2e-3,
|
|
840
|
+
runRoll: 0.01,
|
|
841
|
+
bobUp: 5e-3,
|
|
842
|
+
bobPitch: 2e-3,
|
|
843
|
+
bobRoll: 2e-3,
|
|
844
|
+
maxBobHeight: 6,
|
|
845
|
+
maxBobAngle: 1.2
|
|
846
|
+
};
|
|
847
|
+
function clampViewOffset(offset) {
|
|
848
|
+
return {
|
|
849
|
+
x: Math.max(-14, Math.min(14, offset.x)),
|
|
850
|
+
y: Math.max(-14, Math.min(14, offset.y)),
|
|
851
|
+
z: Math.max(-22, Math.min(30, offset.z))
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
function computeBobMove(xyspeed, onGround, frameTimeMs) {
|
|
855
|
+
if (!onGround) return 0;
|
|
856
|
+
if (xyspeed > 210) return frameTimeMs / 400;
|
|
857
|
+
if (xyspeed > 100) return frameTimeMs / 800;
|
|
858
|
+
return frameTimeMs / 1600;
|
|
859
|
+
}
|
|
860
|
+
function computeBobValues(previousBobTime, xyspeed, pmFlags, onGround, frameTimeMs) {
|
|
861
|
+
if (xyspeed < 5) {
|
|
862
|
+
return { bobTime: 0, bobCycle: 0, bobCycleRun: 0, bobFracSin: 0 };
|
|
863
|
+
}
|
|
864
|
+
const bobMove = computeBobMove(xyspeed, onGround, frameTimeMs);
|
|
865
|
+
const bobTimeRun = previousBobTime + bobMove;
|
|
866
|
+
const crouched = hasPmFlag(pmFlags, PmFlag.Ducked) && onGround;
|
|
867
|
+
const bobTime = crouched ? bobTimeRun * 4 : bobTimeRun;
|
|
868
|
+
return {
|
|
869
|
+
bobTime: bobTimeRun,
|
|
870
|
+
bobCycle: Math.floor(bobTime),
|
|
871
|
+
bobCycleRun: Math.floor(bobTimeRun),
|
|
872
|
+
bobFracSin: Math.abs(Math.sin(bobTime * Math.PI))
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
var ViewEffects = class {
|
|
876
|
+
constructor(settings = {}) {
|
|
877
|
+
this.bobTime = 0;
|
|
878
|
+
this.bobCycle = 0;
|
|
879
|
+
this.bobCycleRun = 0;
|
|
880
|
+
this.bobFracSin = 0;
|
|
881
|
+
this.settings = { ...DEFAULT_SETTINGS, ...settings };
|
|
882
|
+
}
|
|
883
|
+
addKick(kick) {
|
|
884
|
+
if (kick.durationMs <= 0) return;
|
|
885
|
+
this.kick = { ...kick, remainingMs: kick.durationMs };
|
|
886
|
+
}
|
|
887
|
+
get last() {
|
|
888
|
+
return this.lastSample;
|
|
889
|
+
}
|
|
890
|
+
sample(state, frameTimeMs) {
|
|
891
|
+
const { forward, right } = angleVectors(
|
|
892
|
+
clampViewAngles({ pmFlags: state.pmFlags, cmdAngles: state.viewAngles, deltaAngles: state.deltaAngles ?? ZERO_VEC3 }).viewangles
|
|
893
|
+
);
|
|
894
|
+
const xyspeed = Math.sqrt(state.velocity.x * state.velocity.x + state.velocity.y * state.velocity.y);
|
|
895
|
+
const onGround = hasPmFlag(state.pmFlags, PmFlag.OnGround);
|
|
896
|
+
const bobValues = computeBobValues(this.bobTime, xyspeed, state.pmFlags, onGround, frameTimeMs);
|
|
897
|
+
this.bobTime = bobValues.bobTime;
|
|
898
|
+
this.bobCycle = bobValues.bobCycle;
|
|
899
|
+
this.bobCycleRun = bobValues.bobCycleRun;
|
|
900
|
+
this.bobFracSin = bobValues.bobFracSin;
|
|
901
|
+
let pitchTilt = dotVec3(state.velocity, forward) * this.settings.runPitch;
|
|
902
|
+
const side = dotVec3(state.velocity, right);
|
|
903
|
+
const sign = side < 0 ? -1 : 1;
|
|
904
|
+
const absSide = Math.abs(side);
|
|
905
|
+
let rollTilt = absSide * this.settings.runRoll;
|
|
906
|
+
if (rollTilt > 2) {
|
|
907
|
+
rollTilt = 2;
|
|
908
|
+
}
|
|
909
|
+
rollTilt *= sign;
|
|
910
|
+
let pitchDelta = this.bobFracSin * this.settings.bobPitch * xyspeed;
|
|
911
|
+
let rollDelta = this.bobFracSin * this.settings.bobRoll * xyspeed;
|
|
912
|
+
if (hasPmFlag(state.pmFlags, PmFlag.Ducked) && onGround) {
|
|
913
|
+
pitchDelta *= 6;
|
|
914
|
+
rollDelta *= 6;
|
|
915
|
+
}
|
|
916
|
+
pitchTilt += Math.min(pitchDelta, this.settings.maxBobAngle);
|
|
917
|
+
rollDelta = Math.min(rollDelta, this.settings.maxBobAngle);
|
|
918
|
+
if (this.bobCycle & 1) rollDelta = -rollDelta;
|
|
919
|
+
rollTilt += rollDelta;
|
|
920
|
+
const bobHeight = Math.min(this.bobFracSin * xyspeed * this.settings.bobUp, this.settings.maxBobHeight);
|
|
921
|
+
let kickPitch = 0;
|
|
922
|
+
let kickRoll = 0;
|
|
923
|
+
let kickX = 0;
|
|
924
|
+
let kickY = 0;
|
|
925
|
+
let kickZ = 0;
|
|
926
|
+
if (this.kick && this.kick.remainingMs > 0) {
|
|
927
|
+
const ratio = Math.max(0, Math.min(1, this.kick.remainingMs / this.kick.durationMs));
|
|
928
|
+
kickPitch += ratio * this.kick.pitch;
|
|
929
|
+
kickRoll += ratio * this.kick.roll;
|
|
930
|
+
if (this.kick.origin) {
|
|
931
|
+
kickX += ratio * this.kick.origin.x;
|
|
932
|
+
kickY += ratio * this.kick.origin.y;
|
|
933
|
+
kickZ += ratio * this.kick.origin.z;
|
|
934
|
+
}
|
|
935
|
+
this.kick.remainingMs = Math.max(0, this.kick.remainingMs - frameTimeMs);
|
|
936
|
+
if (this.kick.remainingMs === 0) this.kick = void 0;
|
|
937
|
+
}
|
|
938
|
+
const angles = { x: pitchTilt + kickPitch, y: 0, z: rollTilt + kickRoll };
|
|
939
|
+
const offset = { x: kickX, y: kickY, z: bobHeight + kickZ };
|
|
940
|
+
const sample = {
|
|
941
|
+
angles,
|
|
942
|
+
offset: clampViewOffset(offset),
|
|
943
|
+
bobCycle: this.bobCycle,
|
|
944
|
+
bobCycleRun: this.bobCycleRun,
|
|
945
|
+
bobFracSin: this.bobFracSin,
|
|
946
|
+
xyspeed
|
|
947
|
+
};
|
|
948
|
+
this.lastSample = sample;
|
|
949
|
+
return sample;
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
var DEFAULTS = {
|
|
953
|
+
pmFriction: 6,
|
|
954
|
+
pmStopSpeed: 100,
|
|
955
|
+
pmAccelerate: 10,
|
|
956
|
+
pmAirAccelerate: 1,
|
|
957
|
+
pmWaterAccelerate: 4,
|
|
958
|
+
pmWaterFriction: 1,
|
|
959
|
+
pmMaxSpeed: 300,
|
|
960
|
+
pmDuckSpeed: 100,
|
|
961
|
+
pmWaterSpeed: 400,
|
|
962
|
+
groundIsSlick: false,
|
|
963
|
+
errorTolerance: 0.1,
|
|
964
|
+
errorSnapThreshold: 10
|
|
965
|
+
};
|
|
966
|
+
var DEFAULT_GRAVITY = 800;
|
|
967
|
+
var ZERO_VEC32 = { x: 0, y: 0, z: 0 };
|
|
968
|
+
var CMD_BACKUP = 64;
|
|
969
|
+
function defaultPredictionState() {
|
|
970
|
+
return {
|
|
971
|
+
origin: ZERO_VEC32,
|
|
972
|
+
velocity: ZERO_VEC32,
|
|
973
|
+
viewAngles: ZERO_VEC32,
|
|
974
|
+
onGround: false,
|
|
975
|
+
// Physics fields
|
|
976
|
+
pmFlags: PmFlag.OnGround,
|
|
977
|
+
pmType: PmType.Normal,
|
|
978
|
+
waterLevel: WaterLevel.None,
|
|
979
|
+
watertype: 0,
|
|
980
|
+
gravity: DEFAULT_GRAVITY,
|
|
981
|
+
deltaAngles: ZERO_VEC32,
|
|
982
|
+
// Bounds
|
|
983
|
+
mins: { x: -16, y: -16, z: -24 },
|
|
984
|
+
maxs: { x: 16, y: 16, z: 32 },
|
|
985
|
+
// Visual/Game fields
|
|
986
|
+
damageAlpha: 0,
|
|
987
|
+
damageIndicators: [],
|
|
988
|
+
blend: [0, 0, 0, 0],
|
|
989
|
+
stats: [],
|
|
990
|
+
kick_angles: ZERO_VEC32,
|
|
991
|
+
kick_origin: ZERO_VEC32,
|
|
992
|
+
gunoffset: ZERO_VEC32,
|
|
993
|
+
gunangles: ZERO_VEC32,
|
|
994
|
+
gunindex: 0,
|
|
995
|
+
// New fields
|
|
996
|
+
pm_time: 0,
|
|
997
|
+
pm_type: PmType.Normal,
|
|
998
|
+
pm_flags: PmFlag.OnGround,
|
|
999
|
+
gun_frame: 0,
|
|
1000
|
+
rdflags: 0,
|
|
1001
|
+
fov: 90,
|
|
1002
|
+
renderfx: 0,
|
|
1003
|
+
// Optional fields
|
|
1004
|
+
pickupIcon: void 0,
|
|
1005
|
+
centerPrint: void 0,
|
|
1006
|
+
notify: void 0,
|
|
1007
|
+
client: void 0,
|
|
1008
|
+
health: 0,
|
|
1009
|
+
armor: 0,
|
|
1010
|
+
ammo: 0
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
function normalizeState(state) {
|
|
1014
|
+
if (!state) return defaultPredictionState();
|
|
1015
|
+
return {
|
|
1016
|
+
...defaultPredictionState(),
|
|
1017
|
+
...state,
|
|
1018
|
+
origin: { ...state.origin },
|
|
1019
|
+
velocity: { ...state.velocity },
|
|
1020
|
+
viewAngles: { ...state.viewAngles },
|
|
1021
|
+
deltaAngles: state.deltaAngles ? { ...state.deltaAngles } : ZERO_VEC32,
|
|
1022
|
+
blend: state.blend ? [...state.blend] : [0, 0, 0, 0],
|
|
1023
|
+
damageIndicators: state.damageIndicators ? [...state.damageIndicators] : [],
|
|
1024
|
+
stats: state.stats ? [...state.stats] : []
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
function lerp2(a, b, t) {
|
|
1028
|
+
return a + (b - a) * t;
|
|
1029
|
+
}
|
|
1030
|
+
function lerpAngle(a, b, t) {
|
|
1031
|
+
let delta = angleMod(b - a);
|
|
1032
|
+
if (delta > 180) {
|
|
1033
|
+
delta -= 360;
|
|
1034
|
+
}
|
|
1035
|
+
return angleMod(a + delta * t);
|
|
1036
|
+
}
|
|
1037
|
+
function interpolatePredictionState(previous, latest, alpha) {
|
|
1038
|
+
const clamped = Math.max(0, Math.min(alpha, 1));
|
|
1039
|
+
return {
|
|
1040
|
+
...latest,
|
|
1041
|
+
// Default to latest for discrete fields
|
|
1042
|
+
origin: {
|
|
1043
|
+
x: lerp2(previous.origin.x, latest.origin.x, clamped),
|
|
1044
|
+
y: lerp2(previous.origin.y, latest.origin.y, clamped),
|
|
1045
|
+
z: lerp2(previous.origin.z, latest.origin.z, clamped)
|
|
1046
|
+
},
|
|
1047
|
+
velocity: {
|
|
1048
|
+
x: lerp2(previous.velocity.x, latest.velocity.x, clamped),
|
|
1049
|
+
y: lerp2(previous.velocity.y, latest.velocity.y, clamped),
|
|
1050
|
+
z: lerp2(previous.velocity.z, latest.velocity.z, clamped)
|
|
1051
|
+
},
|
|
1052
|
+
viewAngles: {
|
|
1053
|
+
x: lerpAngle(previous.viewAngles.x, latest.viewAngles.x, clamped),
|
|
1054
|
+
y: lerpAngle(previous.viewAngles.y, latest.viewAngles.y, clamped),
|
|
1055
|
+
z: lerpAngle(previous.viewAngles.z, latest.viewAngles.z, clamped)
|
|
1056
|
+
},
|
|
1057
|
+
damageAlpha: lerp2(previous.damageAlpha, latest.damageAlpha, clamped),
|
|
1058
|
+
blend: [
|
|
1059
|
+
lerp2(previous.blend[0], latest.blend[0], clamped),
|
|
1060
|
+
lerp2(previous.blend[1], latest.blend[1], clamped),
|
|
1061
|
+
lerp2(previous.blend[2], latest.blend[2], clamped),
|
|
1062
|
+
lerp2(previous.blend[3], latest.blend[3], clamped)
|
|
1063
|
+
],
|
|
1064
|
+
// Interpolate health/armor for smooth HUD? Usually step.
|
|
1065
|
+
health: lerp2(previous.health || 0, latest.health || 0, clamped),
|
|
1066
|
+
armor: lerp2(previous.armor || 0, latest.armor || 0, clamped),
|
|
1067
|
+
ammo: lerp2(previous.ammo || 0, latest.ammo || 0, clamped)
|
|
1068
|
+
};
|
|
1069
|
+
}
|
|
1070
|
+
function simulateCommand(state, cmd, settings, trace, pointContents) {
|
|
1071
|
+
const pmoveCmd = {
|
|
1072
|
+
forwardmove: cmd.forwardmove,
|
|
1073
|
+
sidemove: cmd.sidemove,
|
|
1074
|
+
upmove: cmd.upmove,
|
|
1075
|
+
buttons: cmd.buttons,
|
|
1076
|
+
angles: cmd.angles
|
|
1077
|
+
// Added missing property
|
|
1078
|
+
};
|
|
1079
|
+
const newState = applyPmove(state, pmoveCmd, trace, pointContents);
|
|
1080
|
+
const { viewangles } = clampViewAngles({
|
|
1081
|
+
pmFlags: state.pmFlags,
|
|
1082
|
+
cmdAngles: cmd.angles,
|
|
1083
|
+
deltaAngles: state.deltaAngles ?? ZERO_VEC32
|
|
1084
|
+
});
|
|
1085
|
+
return {
|
|
1086
|
+
...newState,
|
|
1087
|
+
viewAngles: viewangles
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
var ClientPrediction = class {
|
|
1091
|
+
constructor(physics, settings = {}) {
|
|
1092
|
+
this.enabled = true;
|
|
1093
|
+
this.baseFrame = {
|
|
1094
|
+
frame: 0,
|
|
1095
|
+
timeMs: 0,
|
|
1096
|
+
state: defaultPredictionState()
|
|
1097
|
+
};
|
|
1098
|
+
this.commands = [];
|
|
1099
|
+
this.predicted = defaultPredictionState();
|
|
1100
|
+
this.predictionError = ZERO_VEC32;
|
|
1101
|
+
this.settings = { ...DEFAULTS, ...settings };
|
|
1102
|
+
this.physics = physics;
|
|
1103
|
+
this.predicted = this.baseFrame.state ?? defaultPredictionState();
|
|
1104
|
+
}
|
|
1105
|
+
setPredictionEnabled(enabled) {
|
|
1106
|
+
this.enabled = enabled;
|
|
1107
|
+
}
|
|
1108
|
+
setAuthoritative(frame) {
|
|
1109
|
+
const normalized = normalizeState(frame.state);
|
|
1110
|
+
if (frame.frame <= this.baseFrame.frame) {
|
|
1111
|
+
return this.predicted;
|
|
1112
|
+
}
|
|
1113
|
+
if (this.enabled) {
|
|
1114
|
+
let predictedAtFrame;
|
|
1115
|
+
const relevantCommands = this.commands.filter((c) => c.sequence <= frame.frame && c.sequence > this.baseFrame.frame);
|
|
1116
|
+
if (relevantCommands.length > 0 || this.baseFrame.frame === frame.frame) {
|
|
1117
|
+
let tempState = normalizeState(this.baseFrame.state);
|
|
1118
|
+
for (const cmd of relevantCommands) {
|
|
1119
|
+
tempState = simulateCommand(tempState, cmd, this.settings, this.physics.trace, this.physics.pointContents);
|
|
1120
|
+
}
|
|
1121
|
+
predictedAtFrame = tempState;
|
|
1122
|
+
}
|
|
1123
|
+
if (predictedAtFrame) {
|
|
1124
|
+
const error = subtractVec3(predictedAtFrame.origin, normalized.origin);
|
|
1125
|
+
const errorLen = lengthVec3(error);
|
|
1126
|
+
if (errorLen > this.settings.errorSnapThreshold) {
|
|
1127
|
+
this.predictionError = ZERO_VEC32;
|
|
1128
|
+
} else if (errorLen > this.settings.errorTolerance) {
|
|
1129
|
+
this.predictionError = error;
|
|
1130
|
+
} else {
|
|
1131
|
+
this.predictionError = ZERO_VEC32;
|
|
1132
|
+
}
|
|
1133
|
+
} else {
|
|
1134
|
+
this.predictionError = ZERO_VEC32;
|
|
1135
|
+
}
|
|
1136
|
+
} else {
|
|
1137
|
+
this.predictionError = ZERO_VEC32;
|
|
1138
|
+
}
|
|
1139
|
+
this.baseFrame = { ...frame, state: normalized };
|
|
1140
|
+
this.commands = this.commands.filter((cmd) => cmd.sequence > frame.frame);
|
|
1141
|
+
return this.recompute();
|
|
1142
|
+
}
|
|
1143
|
+
getPredictionError() {
|
|
1144
|
+
return this.predictionError;
|
|
1145
|
+
}
|
|
1146
|
+
// Decay error over time - usually called once per client frame
|
|
1147
|
+
decayError(frametime) {
|
|
1148
|
+
const len2 = lengthVec3(this.predictionError);
|
|
1149
|
+
if (len2 > 0) {
|
|
1150
|
+
const decay = len2 * 10 * frametime;
|
|
1151
|
+
const scale2 = Math.max(0, len2 - decay) / len2;
|
|
1152
|
+
this.predictionError = scaleVec3(this.predictionError, scale2);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
enqueueCommand(cmd) {
|
|
1156
|
+
this.commands.push(cmd);
|
|
1157
|
+
if (this.commands.length > CMD_BACKUP) {
|
|
1158
|
+
this.commands.shift();
|
|
1159
|
+
}
|
|
1160
|
+
return this.recompute();
|
|
1161
|
+
}
|
|
1162
|
+
getCommand(sequence) {
|
|
1163
|
+
return this.commands.find((c) => c.sequence === sequence);
|
|
1164
|
+
}
|
|
1165
|
+
getPredictedState() {
|
|
1166
|
+
return this.predicted;
|
|
1167
|
+
}
|
|
1168
|
+
recompute() {
|
|
1169
|
+
let state = normalizeState(this.baseFrame.state);
|
|
1170
|
+
if (this.enabled) {
|
|
1171
|
+
for (const cmd of this.commands) {
|
|
1172
|
+
state = simulateCommand(state, cmd, this.settings, this.physics.trace, this.physics.pointContents);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
this.predicted = state;
|
|
1176
|
+
return state;
|
|
1177
|
+
}
|
|
1178
|
+
};
|
|
1179
|
+
|
|
1180
|
+
// src/index.ts
|
|
1181
|
+
var cgi2 = null;
|
|
1182
|
+
var cg_predict = null;
|
|
1183
|
+
function Init() {
|
|
1184
|
+
if (!cgi2) {
|
|
1185
|
+
console.error("CGame Init: cgame imports not set");
|
|
1186
|
+
return;
|
|
1187
|
+
}
|
|
1188
|
+
cgi2.Com_Print("===== CGame Initialization =====\n");
|
|
1189
|
+
CG_InitScreen(cgi2);
|
|
1190
|
+
cg_predict = cgi2.Cvar_Get("cg_predict", "1", 0);
|
|
1191
|
+
cgi2.Cvar_Get("cg_showmiss", "0", 0);
|
|
1192
|
+
cgi2.Com_Print("CGame initialized\n");
|
|
1193
|
+
}
|
|
1194
|
+
function Shutdown() {
|
|
1195
|
+
if (cgi2) {
|
|
1196
|
+
cgi2.Com_Print("CGame shutdown\n");
|
|
1197
|
+
}
|
|
1198
|
+
cgi2 = null;
|
|
1199
|
+
}
|
|
1200
|
+
function DrawHUD(isplit, data, hud_vrect, hud_safe, scale2, playernum, ps) {
|
|
1201
|
+
CG_DrawHUD(isplit, data, hud_vrect, hud_safe, scale2, playernum, ps);
|
|
1202
|
+
}
|
|
1203
|
+
function TouchPics() {
|
|
1204
|
+
CG_TouchPics();
|
|
1205
|
+
}
|
|
1206
|
+
function GetLayoutFlags(ps) {
|
|
1207
|
+
return 0;
|
|
1208
|
+
}
|
|
1209
|
+
function GetActiveWeaponWheelWeapon(ps) {
|
|
1210
|
+
return ps.stats[PlayerStat.STAT_ACTIVE_WHEEL_WEAPON] ?? 0;
|
|
1211
|
+
}
|
|
1212
|
+
function GetOwnedWeaponWheelWeapons(ps) {
|
|
1213
|
+
const owned = [];
|
|
1214
|
+
const bits1 = ps.stats[PlayerStat.STAT_WEAPONS_OWNED_1] || 0;
|
|
1215
|
+
const bits2 = ps.stats[PlayerStat.STAT_WEAPONS_OWNED_2] || 0;
|
|
1216
|
+
const fullBits = bits1 | bits2 << 16;
|
|
1217
|
+
for (let i = 0; i < WEAPON_WHEEL_ORDER.length; i++) {
|
|
1218
|
+
if (fullBits & 1 << i) {
|
|
1219
|
+
owned.push(i);
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
return owned;
|
|
1223
|
+
}
|
|
1224
|
+
function GetWeaponWheelAmmoCount(ps, weapon) {
|
|
1225
|
+
if (weapon < 0 || weapon >= WEAPON_WHEEL_ORDER.length) {
|
|
1226
|
+
return 0;
|
|
1227
|
+
}
|
|
1228
|
+
const weaponId = WEAPON_WHEEL_ORDER[weapon];
|
|
1229
|
+
const ammoType = WEAPON_AMMO_MAP[weaponId];
|
|
1230
|
+
if (ammoType === null) {
|
|
1231
|
+
return -1;
|
|
1232
|
+
}
|
|
1233
|
+
return G_GetAmmoStat(ps.stats, ammoType);
|
|
1234
|
+
}
|
|
1235
|
+
function GetPowerupWheelCount(ps) {
|
|
1236
|
+
let count = 0;
|
|
1237
|
+
const powerups = Object.values(PowerupId);
|
|
1238
|
+
for (const id of powerups) {
|
|
1239
|
+
if (G_GetPowerupStat(ps.stats, id) > 0) {
|
|
1240
|
+
count++;
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
return count;
|
|
1244
|
+
}
|
|
1245
|
+
function GetHitMarkerDamage(ps) {
|
|
1246
|
+
return ps.stats[PlayerStat.STAT_HIT_MARKER] ?? 0;
|
|
1247
|
+
}
|
|
1248
|
+
function Pmove(pmove) {
|
|
1249
|
+
const pm = pmove;
|
|
1250
|
+
if (!pm || !pm.s || !pm.cmd || !cgi2) {
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
1253
|
+
if (cg_predict && cg_predict.value === 0) {
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
const traceAdapter = (start, end, mins, maxs) => {
|
|
1257
|
+
const zero2 = { x: 0, y: 0, z: 0 };
|
|
1258
|
+
return cgi2.PM_Trace(
|
|
1259
|
+
start,
|
|
1260
|
+
end,
|
|
1261
|
+
mins || zero2,
|
|
1262
|
+
maxs || zero2
|
|
1263
|
+
);
|
|
1264
|
+
};
|
|
1265
|
+
const pointContentsAdapter = (point) => {
|
|
1266
|
+
const zero2 = { x: 0, y: 0, z: 0 };
|
|
1267
|
+
const tr = cgi2.PM_Trace(point, point, zero2, zero2);
|
|
1268
|
+
return tr.contents || 0;
|
|
1269
|
+
};
|
|
1270
|
+
const newState = applyPmove(pm.s, pm.cmd, traceAdapter, pointContentsAdapter);
|
|
1271
|
+
pm.s.origin = newState.origin;
|
|
1272
|
+
pm.s.velocity = newState.velocity;
|
|
1273
|
+
pm.s.onGround = newState.onGround;
|
|
1274
|
+
pm.s.waterLevel = newState.waterLevel;
|
|
1275
|
+
}
|
|
1276
|
+
function ParseConfigString(i, s) {
|
|
1277
|
+
if (!cgi2) return;
|
|
1278
|
+
CG_ParseConfigString(cgi2, i, s);
|
|
1279
|
+
}
|
|
1280
|
+
function ParseCenterPrint(str2, isplit, instant) {
|
|
1281
|
+
if (!cgi2) return;
|
|
1282
|
+
const messageSystem2 = CG_GetMessageSystem();
|
|
1283
|
+
messageSystem2.setCenterPrint(str2, cgi2.CL_ClientTime());
|
|
1284
|
+
}
|
|
1285
|
+
function NotifyMessage(isplit, msg, is_chat) {
|
|
1286
|
+
if (!cgi2) return;
|
|
1287
|
+
const messageSystem2 = CG_GetMessageSystem();
|
|
1288
|
+
messageSystem2.addNotification(msg, is_chat, cgi2.CL_ClientTime());
|
|
1289
|
+
}
|
|
1290
|
+
function ClearNotify(isplit) {
|
|
1291
|
+
const messageSystem2 = CG_GetMessageSystem();
|
|
1292
|
+
messageSystem2.clearNotifications();
|
|
1293
|
+
}
|
|
1294
|
+
function ClearCenterprint(isplit) {
|
|
1295
|
+
const messageSystem2 = CG_GetMessageSystem();
|
|
1296
|
+
messageSystem2.clearCenterPrint();
|
|
1297
|
+
}
|
|
1298
|
+
function ShowSubtitle(text, soundName) {
|
|
1299
|
+
if (!cgi2) return;
|
|
1300
|
+
const subtitleSystem2 = CG_GetSubtitleSystem();
|
|
1301
|
+
subtitleSystem2.addSubtitle(text, cgi2.CL_ClientTime());
|
|
1302
|
+
}
|
|
1303
|
+
function GetMonsterFlashOffset(id) {
|
|
1304
|
+
return { x: 0, y: 0, z: 0 };
|
|
1305
|
+
}
|
|
1306
|
+
function GetExtension(name) {
|
|
1307
|
+
return null;
|
|
1308
|
+
}
|
|
1309
|
+
function GetCGameAPI(imports) {
|
|
1310
|
+
cgi2 = imports;
|
|
1311
|
+
return {
|
|
1312
|
+
// Lifecycle
|
|
1313
|
+
Init,
|
|
1314
|
+
Shutdown,
|
|
1315
|
+
// Rendering
|
|
1316
|
+
DrawHUD,
|
|
1317
|
+
TouchPics,
|
|
1318
|
+
// Layout
|
|
1319
|
+
LayoutFlags: GetLayoutFlags,
|
|
1320
|
+
// Weapon wheel
|
|
1321
|
+
GetActiveWeaponWheelWeapon,
|
|
1322
|
+
GetOwnedWeaponWheelWeapons,
|
|
1323
|
+
GetWeaponWheelAmmoCount,
|
|
1324
|
+
GetPowerupWheelCount,
|
|
1325
|
+
// Hit markers
|
|
1326
|
+
GetHitMarkerDamage,
|
|
1327
|
+
// Prediction
|
|
1328
|
+
Pmove,
|
|
1329
|
+
// Parsing
|
|
1330
|
+
ParseConfigString,
|
|
1331
|
+
ParseCenterPrint,
|
|
1332
|
+
NotifyMessage,
|
|
1333
|
+
ShowSubtitle,
|
|
1334
|
+
// State management
|
|
1335
|
+
ClearNotify,
|
|
1336
|
+
ClearCenterprint,
|
|
1337
|
+
// Effects
|
|
1338
|
+
GetMonsterFlashOffset,
|
|
1339
|
+
// Extension
|
|
1340
|
+
GetExtension
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
export { ClientPrediction, GetCGameAPI, ViewEffects, defaultPredictionState, interpolatePredictionState, updateCamera };
|
|
1345
|
+
//# sourceMappingURL=index.js.map
|
|
1346
|
+
//# sourceMappingURL=index.js.map
|