@bf6mods/cli 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/README.md +70 -0
  2. package/dist/cli/index.js +541 -76
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/resources/prepare/bf6.d.ts +2 -0
  5. package/dist/resources/prepare/tsconfig.json +14 -15
  6. package/dist/resources/prepare/types/config.ts +139 -4
  7. package/dist/resources/templates/All/package.json +1 -1
  8. package/dist/resources/templates/Basic/bf6.config.ts +5 -1
  9. package/package.json +48 -41
  10. package/dist/resources/templates/AcePursuit/src/index.ts +0 -3421
  11. package/dist/resources/templates/AcePursuit/src/levels.tscn +0 -6922
  12. package/dist/resources/templates/AcePursuit/src/strings.json +0 -191
  13. package/dist/resources/templates/All/bf6.config.ts +0 -6
  14. package/dist/resources/templates/BombSquad/src/index.ts +0 -3683
  15. package/dist/resources/templates/BombSquad/src/levels.tscn +0 -3212
  16. package/dist/resources/templates/BombSquad/src/strings.json +0 -123
  17. package/dist/resources/templates/Exfil/src/index.ts +0 -2393
  18. package/dist/resources/templates/Exfil/src/levels.tscn +0 -5600
  19. package/dist/resources/templates/Exfil/src/strings.json +0 -185
  20. package/dist/resources/templates/Vertigo/src/index.ts +0 -1948
  21. package/dist/resources/templates/Vertigo/src/levels.tscn +0 -6387
  22. package/dist/resources/templates/Vertigo/src/strings.json +0 -308
  23. /package/dist/resources/templates/{AcePursuit/src/config.json → AcePursuit.json} +0 -0
  24. /package/dist/resources/templates/{BombSquad/src/config.json → BombSquad.json} +0 -0
  25. /package/dist/resources/templates/{Exfil/src/config.json → Exfil.json} +0 -0
  26. /package/dist/resources/templates/{Vertigo/src/config.json → Vertigo.json} +0 -0
@@ -1,3683 +0,0 @@
1
- const VERSION = [1, 4, 59];
2
- const debugJSPlayer = true;
3
- const debugSkipBuyPhase = false;
4
- const debugSwitchTeamsEachRound = false;
5
- const AIBackfill = false;
6
- const INSTANT_START = false;
7
-
8
-
9
- let gameOver = false;
10
-
11
- let initialPlayerCount: number = 0;
12
- let combatCountdownStarted = false;
13
- let combatStartDelayRemaining = 60;
14
- let combatStarted = false;
15
- let roundEnded: boolean = false;
16
-
17
- let bombPickupDistance = 3.0;
18
- let bombInteractDistance = 3.0;
19
-
20
- let messageTime: number = 0;
21
-
22
- let initialCash = 800;
23
-
24
- let teamSwitchOccurred: boolean = false;
25
-
26
- let team1Score: number = 0;
27
- let team2Score: number = 0;
28
- let attackingTeam: mod.Team = mod.GetTeam(1);
29
- let defendingTeam: mod.Team = mod.GetTeam(2);
30
- let roundNum: number = 0;
31
- let roundTime: number = 300; // Max time for round in seconds (extended when bomb is planted)
32
- // This is the amount of time remaining until the round begins (buy/setup phases)
33
- let buyPhaseTimeRemaining: number = 60;
34
-
35
- let interactPointA: mod.InteractPoint = mod.GetInteractPoint(1);
36
- let interactPointB: mod.InteractPoint = mod.GetInteractPoint(2);
37
- let worldIconA: mod.WorldIcon = mod.GetWorldIcon(20);
38
- let worldIconB: mod.WorldIcon = mod.GetWorldIcon(21);
39
- let bombExplodesSFX_A: mod.SFX;
40
- let bombExplodesSFX_B: mod.SFX;
41
- let bombExplodesVFX_A: mod.VFX;
42
- let bombExplodesVFX_B: mod.VFX;
43
- let alarmSFX_A: mod.SFX;
44
- let alarmSFX_B: mod.SFX;
45
-
46
- let attackersStoreInteractPoint = mod.GetInteractPoint(500);
47
- let defendersStoreInteractPoint = mod.GetInteractPoint(501);
48
- let attackersStoreWI = mod.GetWorldIcon(500);
49
- let defendersStoreWI = mod.GetWorldIcon(501);
50
-
51
- const pointAAreaID: number = 1;
52
- const pointBAreaID: number = 2;
53
-
54
- const storeID_attackers: number = 500;
55
- const storeID_defenders: number = 501;
56
-
57
-
58
- const MCOMPositionA: mod.Vector = mod.CreateVector(128.70, 184.04, 137.26);
59
- const MCOMPositionB: mod.Vector = mod.CreateVector(213.2, 182.12, 128.51);
60
-
61
- const SpawnWallPos1: mod.Vector = mod.CreateVector(136.2, 174.24, 134.51);
62
- const SpawnWallPos2: mod.Vector = mod.CreateVector(169.7, 174.24, 129.51);
63
- const SpawnWallPos3: mod.Vector = mod.CreateVector(161.7, 184.24, 41.519);
64
- const SpawnWallPos4: mod.Vector = mod.CreateVector(182.2, 184.24, 38.519);
65
- const SpawnWall1ID: number = 100;
66
- const SpawnWall2ID: number = 101;
67
- const SpawnWall3ID: number = 102;
68
- const SpawnWall4ID: number = 103;
69
- const loserBox1Pos: mod.Vector = mod.CreateVector(171, 235.5, 16);
70
- const loserBox2Pos: mod.Vector = mod.CreateVector(171, 235.5, 160);
71
- const wallMoveDelta: number = -20;
72
-
73
- const attackersHQID: number = 1;
74
- const defendersHQID: number = 2;
75
-
76
- let attackersHQ: mod.HQ = mod.GetHQ(attackersHQID);
77
- let defendersHQ: mod.HQ = mod.GetHQ(defendersHQID);
78
-
79
- const defendersSpawnID: number = 1000;
80
- const attackersSpawnID: number = 2000;
81
-
82
- // Attackers will have their ability to interact removed within this distance of either MCOM
83
- const disabledInteractDistance: number = 5;
84
-
85
- // Money Rewards
86
- const roundWinReward: number = 2400;
87
- const roundLoseReward: number = 1200; // Might want to make scales for these
88
- const killReward: number = 300;
89
- const defuseReward: number = 1000;
90
- const plantReward: number = 800;
91
-
92
- let roundStarted: boolean = false;
93
- let buyPhase: boolean = false;
94
- const buyPhaseLength: number = 35;
95
- const roundEndBuffer: number = 10;
96
-
97
- // UI
98
- type Widget = mod.UIWidget;
99
-
100
- const minimumInitialPlayerCount: number = 2;
101
- const BLACKCOLOR: number[] = [1, 1, 1];
102
- const REDCOLOR: number[] = [1, 0, 0];
103
- const WHITECOLOR: number[] = [0, 0, 0];
104
- const maxRounds: number = 14;
105
- const deathYPos: number = 160;
106
- const ZEROVEC: mod.Vector = mod.CreateVector(0, 0, 0);
107
- const ONEVEC: mod.Vector = mod.CreateVector(1, 1, 1);
108
-
109
-
110
- const MCOMFuseTime: number = 60;
111
- const armTime: number = 3;
112
- const disarmTime: number = 3;
113
-
114
- const messageRemainTime: number = 5;
115
- const maxRoundTime: number = 300;
116
- type Dict = { [key: string]: any };
117
-
118
- let vfxidx = 0;
119
-
120
-
121
- // Use this as your "ready"/game startup function
122
- export async function OnGameModeStarted() {
123
- console.log("Bomb Defusal v", VERSION[0], ".", VERSION[1], ".", VERSION[2], " Game Mode Started");
124
- combatStartDelayRemaining = 60; // Reset in case the game is restarted ig
125
-
126
- mod.SetSpawnMode(mod.SpawnModes.AutoSpawn)
127
-
128
- gameOver = false;
129
- mod.SetWorldIconText(worldIconA, MakeMessage(mod.stringkeys.a));
130
- mod.SetWorldIconText(worldIconB, MakeMessage(mod.stringkeys.b));
131
- mod.SetWorldIconText(attackersStoreWI, MakeMessage(mod.stringkeys.shop));
132
- mod.SetWorldIconText(defendersStoreWI, MakeMessage(mod.stringkeys.shop));
133
- mod.SetWorldIconOwner(attackersStoreWI, attackingTeam);
134
- mod.SetWorldIconOwner(defendersStoreWI, defendingTeam);
135
-
136
- BombData.Initialize();
137
-
138
- bombExplodesSFX_A = mod.SpawnObject(mod.RuntimeSpawn_Common.SFX_Gadgets_C4_Activate_OneShot3D, MCOMPositionA, ZEROVEC);
139
- bombExplodesSFX_B = mod.SpawnObject(mod.RuntimeSpawn_Common.SFX_Gadgets_C4_Activate_OneShot3D, MCOMPositionB, ZEROVEC);
140
- bombExplodesVFX_A = mod.SpawnObject(mod.RuntimeSpawn_Common.FX_ArtilleryStrike_Explosion_GS, MCOMPositionA, ZEROVEC);
141
- bombExplodesVFX_B = mod.SpawnObject(mod.RuntimeSpawn_Common.FX_ArtilleryStrike_Explosion_GS, MCOMPositionB, ZEROVEC);
142
- alarmSFX_A = mod.SpawnObject(mod.RuntimeSpawn_Common.SFX_Alarm, MCOMPositionA, ZEROVEC);
143
- alarmSFX_B = mod.SpawnObject(mod.RuntimeSpawn_Common.SFX_Alarm, MCOMPositionB, ZEROVEC);
144
- mod.EnableSFX(alarmSFX_A, false);
145
- mod.EnableSFX(alarmSFX_B, false);
146
-
147
- if (!INSTANT_START) {
148
- // wait for required number of players to join the game.
149
- while (initialPlayerCount < minimumInitialPlayerCount) {
150
- await mod.Wait(1);
151
- //console.log("initial player count is ", initialPlayerCount);
152
- }
153
- }
154
-
155
- // console.log("Adequate players have entered lobby. Begin the game.");
156
-
157
- await CombatCountdown();
158
-
159
- SetupRound();
160
-
161
- TickUpdate();
162
- ThrottledUpdate();
163
- }
164
-
165
- async function TickUpdate() {
166
- let tickRate: number = 0.016;
167
- while (true) {
168
- await mod.Wait(tickRate);
169
-
170
- BombData.ItemProximityCheck();
171
- BombData.ItemHeld();
172
-
173
- if (BombData.carryingPlayer && mod.GetSoldierState(BombData.carryingPlayer, mod.SoldierStateBool.IsAlive)) {
174
- let jsPlayer = JsPlayer.get(BombData.carryingPlayer);
175
-
176
- // Invalid check
177
- if (!jsPlayer)
178
- return;
179
-
180
- if (!BombData.isPlanting && mod.IsInventorySlotActive(BombData.carryingPlayer, mod.InventorySlots.MeleeWeapon)) {
181
-
182
- if (mod.GetSoldierState(BombData.carryingPlayer, mod.SoldierStateBool.IsProne)) {
183
- BombData.ItemDropped(BombData.carryingPlayer);
184
- }
185
- }
186
-
187
- // Extra sanity check.
188
- if (buyPhase)
189
- continue;
190
-
191
- if (BombData.isPlanting) {
192
- if (BombData.carryingPlayer != null) {
193
- if (BombData.isAtA) {
194
- if (mod.DistanceBetween(mod.GetSoldierState(BombData.carryingPlayer, mod.SoldierStateVector.GetPosition), MCOMPositionA) > bombInteractDistance) {
195
- BombData.CancelPlant();
196
- }
197
- }
198
- else if (BombData.isAtB) {
199
- if (mod.DistanceBetween(mod.GetSoldierState(BombData.carryingPlayer, mod.SoldierStateVector.GetPosition), MCOMPositionB) > bombInteractDistance) {
200
- BombData.CancelPlant();
201
- }
202
- }
203
- }
204
- else {
205
- BombData.CancelPlant();
206
- }
207
-
208
- // Might have just been cancelled, so check again
209
- if (BombData.isPlanting && (BombData.isAtA || BombData.isAtB)) {
210
- BombData.plantProgress += tickRate / armTime;
211
- console.log("Update Plant Progress: ", BombData.plantProgress);
212
- jsPlayer.progressBarUI?.refresh(BombData.plantProgress);
213
- if (BombData.plantProgress >= 1) {
214
- BombData.PlantBomb();
215
- }
216
- }
217
-
218
- }
219
-
220
- }
221
-
222
- // Extra sanity check.
223
- if (buyPhase)
224
- continue;
225
-
226
- if (BombData.isPlanted && BombData.defusingPlayer != null) {
227
- let jsPlayer = JsPlayer.get(BombData.defusingPlayer);
228
- if (!jsPlayer) {
229
- return;
230
- }
231
-
232
- if (BombData.isAtA) {
233
- if (mod.DistanceBetween(mod.GetSoldierState(BombData.defusingPlayer, mod.SoldierStateVector.GetPosition), MCOMPositionA) > bombInteractDistance) {
234
- BombData.CancelDefuse();
235
- }
236
- }
237
- else if (BombData.isAtB) {
238
- if (mod.DistanceBetween(mod.GetSoldierState(BombData.defusingPlayer, mod.SoldierStateVector.GetPosition), MCOMPositionB) > bombInteractDistance) {
239
- BombData.CancelDefuse();
240
- }
241
- }
242
-
243
- // May have just been cancelled, so check again
244
- if (BombData.defusingPlayer != null) {
245
- BombData.defusingProgress += tickRate / disarmTime;
246
- jsPlayer.progressBarUI?.refresh(BombData.defusingProgress);
247
- if (BombData.defusingProgress >= 1) {
248
- BombData.DefuseBomb();
249
- }
250
- }
251
-
252
- }
253
- }
254
- }
255
-
256
- // Updates every 1 second
257
- async function ThrottledUpdate() {
258
- while (true) {
259
- if (!gameOver) {
260
- if (roundStarted && !roundEnded) {
261
- roundTime--;
262
-
263
- if (roundTime <= 0 && !BombData.isPlanted) {
264
- EndRound(defendingTeam);
265
- }
266
-
267
- }
268
- else {
269
- buyPhaseTimeRemaining--;
270
- }
271
-
272
- UpdateMessages();
273
-
274
- BombData.BombPlanted(); // Will simply return if the bomb is not currently planted
275
-
276
- JsPlayer.playerInstances.forEach(player => {
277
- // IDK why, but AI soldiers keep returning low ypositions despite standing alongside human players that are at acceptable y positions
278
- if (player && mod.GetObjId(player) >= 0) {
279
- if (!gameOver)
280
- UpdateScoreUI(player);
281
-
282
- if (mod.GetSoldierState(player, mod.SoldierStateBool.IsAlive)) {
283
- UpdateInteracts(player);
284
- let yPos = mod.YComponentOf(mod.GetSoldierState(player, mod.SoldierStateVector.GetPosition));
285
- if (yPos < deathYPos) {
286
- mod.Kill(player);
287
- }
288
- }
289
- }
290
- });
291
- }
292
- await mod.Wait(1);
293
- }
294
- }
295
-
296
- // Check the player, and if they are on the attacking team, and not carrying the bomb,
297
- // disable/enable interact input restriction based on their distance to either MCOM
298
- function UpdateInteracts(player: mod.Player) {
299
- if (!roundStarted || buyPhase)
300
- return;
301
-
302
- let onAttackingTeam = mod.GetObjId(mod.GetTeam(player)) == mod.GetObjId(attackingTeam)
303
- if (onAttackingTeam) {
304
- if (BombData.carryingPlayer != null && mod.GetObjId(player) == mod.GetObjId(BombData.carryingPlayer)) {
305
- mod.EnableInputRestriction(player, mod.RestrictedInputs.Interact, false)
306
- }
307
- else {
308
- let playerPos = mod.GetSoldierState(player, mod.SoldierStateVector.GetPosition);
309
- let mcomADist = mod.DistanceBetween(playerPos, MCOMPositionA);
310
- let mcomBDist = mod.DistanceBetween(playerPos, MCOMPositionB);
311
- if (mcomADist < disabledInteractDistance || mcomBDist < disabledInteractDistance)
312
- mod.EnableInputRestriction(player, mod.RestrictedInputs.Interact, true);
313
- }
314
- }
315
- else {
316
- mod.EnableInputRestriction(player, mod.RestrictedInputs.Interact, false);
317
- }
318
-
319
- }
320
-
321
- function UpdateScoreUI(player: mod.Player) {
322
- let jsPlayer = JsPlayer.get(player);
323
-
324
- if (jsPlayer)
325
- jsPlayer.scoreUI?.refresh();
326
- }
327
-
328
- //-----------------------------------------------------------------------------------------------//
329
- //-----------------------------------------------------------------------------------------------//
330
- //-----------------------------------------------------------------------------------------------//
331
- //-----------------------------------------------------------------------------------------------//
332
- // Player Functions:
333
- //-----------------------------------------------------------------------------------------------//
334
- export async function OnPlayerJoinGame(player: mod.Player) {
335
-
336
- let jsPlayer = JsPlayer.get(player);
337
- if (!jsPlayer)
338
- return;
339
-
340
- // Check if this is a human player or not.
341
- if (mod.GetSoldierState(player, mod.SoldierStateBool.IsAISoldier) == false) {
342
-
343
- // Show the pre-game lobby window, assuming combat hasn't started.
344
- if (!combatStarted) {
345
- jsPlayer.lobbyUI?.open();
346
- initialPlayerCount++;
347
- console.log("There are now ", initialPlayerCount, " players in the lobby.");
348
- UpdateAllLobbyUI();
349
- }
350
-
351
- }
352
- else {
353
- // The player is not a human so we will ignore them.
354
- }
355
-
356
- let teamID = mod.GetObjId(mod.GetTeam(player));
357
-
358
-
359
- if (roundStarted) {
360
- console.log("player ID(", mod.GetObjId(player), ") joined mid-round on team", teamID);
361
- //mod.EnablePlayerDeploy(player, false);
362
- }
363
- }
364
-
365
- export async function OnPlayerLeaveGame(playerId: number) {
366
- try {
367
- if ((!BombData.carryingPlayer || !mod.IsPlayerValid(BombData.carryingPlayer)) && BombData.isBeingCarried) {
368
- BombData.ItemDropped();
369
- }
370
- } catch {
371
- if (BombData.isBeingCarried) {
372
- BombData.ItemDropped();
373
- }
374
- }
375
-
376
- // reduce player count.
377
- JsPlayer.removeInvalidJSPlayers(playerId);
378
-
379
- // Updated valid combatants count
380
-
381
- if (combatCountdownStarted && !gameOver) {
382
- //validCombatants = GetNumberOfPlayersOnTeam(combatTeam);
383
- //UpdateValidCombatantsUI();
384
- //CheckVictoryState();
385
- } else if (!combatCountdownStarted) {
386
- if (!gameOver) {
387
- initialPlayerCount--;
388
- UpdateAllLobbyUI();
389
- }
390
- }
391
- }
392
-
393
- export function OnPlayerDeployed(eventPlayer: mod.Player): void {
394
- let jsPlayer = JsPlayer.get(eventPlayer);
395
- let teamID = mod.GetObjId(mod.GetTeam(eventPlayer));
396
- let attackingTeamID = mod.GetObjId(attackingTeam);
397
-
398
- if (jsPlayer) {
399
-
400
- jsPlayer.isDeployed = true;
401
-
402
- if (roundStarted && !roundEnded) {
403
- // this is redundant with death, but it covers late joiners and I need to mark players out of round immediately on death so I can count "living" team members
404
- jsPlayer.outOfRound = true;
405
- }
406
- else {
407
- jsPlayer.outOfRound = false;
408
- }
409
-
410
- if (!jsPlayer.outOfRound) {
411
- if (teamID == attackingTeamID) {
412
- let hqPos: mod.Vector = mod.GetObjectPosition(attackersHQ);
413
- console.log("Player is deploying on team ", teamID, ". Teleport them to HQ ", mod.GetObjId(attackersHQ), " at position: ", mod.XComponentOf(hqPos), ", ", mod.YComponentOf(hqPos), ", ", mod.ZComponentOf(hqPos));
414
- mod.Teleport(eventPlayer, hqPos, 0);
415
- }
416
- else {
417
- let hqPos: mod.Vector = mod.GetObjectPosition(defendersHQ);
418
- console.log("Player is deploying on team ", teamID, ". Teleport them to HQ ", mod.GetObjId(defendersHQ), " at position: ", mod.XComponentOf(hqPos), ", ", mod.YComponentOf(hqPos), ", ", mod.ZComponentOf(hqPos));
419
- mod.Teleport(eventPlayer, hqPos, 0);
420
- }
421
- }
422
-
423
-
424
- if (buyPhase == true) {
425
- if (!mod.GetSoldierState(eventPlayer, mod.SoldierStateBool.IsAISoldier)) {
426
- jsPlayer.store?.open();
427
- jsPlayer.updateWalletUI();
428
- }
429
- }
430
- else {
431
- if (jsPlayer.outOfRound) {
432
- if (teamID == attackingTeamID) {
433
- mod.Teleport(eventPlayer, loserBox1Pos, 0);
434
- }
435
- else {
436
- mod.Teleport(eventPlayer, loserBox2Pos, 0);
437
- }
438
-
439
- ResetPlayerLoadout(eventPlayer, true);
440
- return;
441
- }
442
- }
443
-
444
- }
445
- else {
446
- console.log("Player deploying with invalid jsPlayer!");
447
- }
448
-
449
- ResetPlayerLoadout(eventPlayer, false);
450
-
451
- }
452
-
453
- function EnableStores(enable: boolean) {
454
- mod.EnableInteractPoint(attackersStoreInteractPoint, enable);
455
- mod.EnableInteractPoint(defendersStoreInteractPoint, enable);
456
-
457
- mod.EnableWorldIconImage(attackersStoreWI, enable);
458
- mod.EnableWorldIconText(attackersStoreWI, enable);
459
- mod.EnableWorldIconImage(defendersStoreWI, enable);
460
- mod.EnableWorldIconText(defendersStoreWI, enable);
461
- }
462
-
463
- async function SetupRound() {
464
- roundNum++;
465
- console.log("Set up Round ", roundNum);
466
- roundEnded = false;
467
- buyPhase = true;
468
- RefillAmmo();
469
-
470
- EnableStores(true);
471
-
472
-
473
- if (BombData.isBeingCarried) {
474
- if (BombData.carryingPlayer != null)
475
- BombData.ItemDropped(BombData.carryingPlayer);
476
- else
477
- BombData.ItemDropped();
478
- }
479
-
480
-
481
- let teamsSwitched: boolean = roundNum == maxRounds / 2 + 1 || (debugSwitchTeamsEachRound && roundNum != 1);
482
-
483
- if (teamsSwitched) {
484
- SwitchTeams();
485
- }
486
-
487
- let attackers: mod.Player[] = [];
488
- let attackingTeamID: number = mod.GetObjId(attackingTeam);
489
- let defendingTeamID: number = mod.GetObjId(defendingTeam);
490
-
491
- // Reset Bomb data here? This is where MCOMs were reset.
492
- mod.EnableInteractPoint(interactPointA, true);
493
- mod.EnableInteractPoint(interactPointB, true);
494
- mod.EnableWorldIconImage(worldIconA, true);
495
- mod.EnableWorldIconText(worldIconA, true);
496
- mod.EnableWorldIconImage(worldIconB, true);
497
- mod.EnableWorldIconText(worldIconB, true);
498
-
499
- JsPlayer.playerInstances.forEach(player => {
500
- let teamID = mod.GetObjId(mod.GetTeam(player));
501
- let jsPlayer = JsPlayer.get(player);
502
- let isAI = mod.GetSoldierState(player, mod.SoldierStateBool.IsAISoldier);
503
-
504
- if (isAI) {
505
- mod.Kill(player);
506
- }
507
- else {
508
- // Return to base / respawn
509
- if (jsPlayer && jsPlayer.isDeployed) {
510
- if (teamID == attackingTeamID) {
511
- let hqPos: mod.Vector = mod.GetObjectPosition(attackersHQ);
512
- console.log("Player is on team ", teamID, ". Teleport them to HQ ", mod.GetObjId(attackersHQ), " at position: ", mod.XComponentOf(hqPos), ", ", mod.YComponentOf(hqPos), ", ", mod.ZComponentOf(hqPos));
513
- mod.Teleport(player, hqPos, 0);
514
- }
515
- else {
516
- let hqPos: mod.Vector = mod.GetObjectPosition(defendersHQ);
517
- console.log("Player is on team ", teamID, ". Teleport them to HQ ", mod.GetObjId(defendersHQ), " at position: ", mod.XComponentOf(hqPos), ", ", mod.YComponentOf(hqPos), ", ", mod.ZComponentOf(hqPos));
518
- mod.Teleport(player, hqPos, 0);
519
- }
520
- }
521
-
522
- if (teamID == attackingTeamID) {
523
- attackers.push(player)
524
- }
525
- }
526
-
527
- if (jsPlayer) {
528
- if (jsPlayer.outOfRound && mod.GetSoldierState(player, mod.SoldierStateBool.IsAlive))
529
- ResetPlayerLoadout(player, false);
530
-
531
- jsPlayer.outOfRound = false;
532
- }
533
-
534
- });
535
-
536
- // Another await after spawning before opening the shop up
537
- await mod.Wait(0.5);
538
-
539
- JsPlayer.playerInstances.forEach(player => {
540
- // There should not be any AI at this point, but just for extreme sanity....
541
- let isAI = mod.GetSoldierState(player, mod.SoldierStateBool.IsAISoldier);
542
-
543
- let jsPlayer = JsPlayer.get(player)
544
- if (jsPlayer) {
545
-
546
- // Reset cash to starting value
547
- if (teamsSwitched)
548
- jsPlayer.cash = initialCash;
549
-
550
-
551
- if (!isAI) {
552
- if (jsPlayer.isDeployed && mod.GetSoldierState(player, mod.SoldierStateBool.IsAlive))
553
- jsPlayer.store?.open();
554
-
555
- jsPlayer.updateWalletUI();
556
- }
557
- }
558
- });
559
-
560
- // Pick a random attacker and give them the bomb
561
- if (attackers.length == 0) {
562
- console.log("THERE ARE NO ATTACKERS!!!!");
563
- BombData.currentWorldIconPos = mod.GetObjectPosition(attackersHQ);
564
- mod.SetWorldIconPosition(BombData.bombPositionWorldIcon, BombData.currentWorldIconPos);
565
- }
566
- else {
567
- let playerAttackers: mod.Player[] = []
568
- attackers.forEach(attacker => {
569
- if (!mod.GetSoldierState(attacker, mod.SoldierStateBool.IsAISoldier) && mod.GetSoldierState(attacker, mod.SoldierStateBool.IsAlive))
570
- playerAttackers.push(attacker);
571
- });
572
-
573
- // Only allow for players to begin with the bomb, unless there are no players on the attacking team
574
- let arr = playerAttackers
575
- if (playerAttackers.length == 0)
576
- arr = attackers;
577
-
578
- let rand = GetRandomInt(arr.length - 1);
579
- BombData.ItemPickedUp(arr[rand]);
580
- console.log("Give bomb to ", arr[rand], " on team ", mod.GetObjId(mod.GetTeam(arr[rand])));
581
- }
582
-
583
- if (!debugSkipBuyPhase) {
584
- console.log("Start Buy Phase Timer")
585
- buyPhaseTimeRemaining = buyPhaseLength;
586
- while (buyPhaseTimeRemaining > 0) {
587
- await mod.Wait(1);
588
- }
589
- }
590
-
591
- roundTime = maxRoundTime;
592
-
593
- let attackingTeamSize: number = 0;
594
- let defendingTeamSize: number = 0;
595
-
596
- JsPlayer.playerInstances.forEach(player => {
597
- // Close the shops
598
- let jsPlayer = JsPlayer.get(player);
599
- if (jsPlayer)
600
- jsPlayer.store?.close();
601
-
602
- // Return AI players to default pathfinding behavior
603
- if (AIBackfill && mod.GetSoldierState(player, mod.SoldierStateBool.IsAISoldier)) {
604
- mod.AIBattlefieldBehavior(player);
605
- }
606
-
607
- if (mod.GetObjId(mod.GetTeam(player)) == attackingTeamID) {
608
- attackingTeamSize++;
609
- }
610
- else {
611
- defendingTeamSize++;
612
- }
613
-
614
- // Make extra sure this is disabled for all players when Round Setup ends
615
- mod.EnableUIInputMode(false, player);
616
- });
617
-
618
- let tWall1 = mod.GetSpatialObject(SpawnWall1ID);
619
- let tWall2 = mod.GetSpatialObject(SpawnWall2ID);
620
- let tWall3 = mod.GetSpatialObject(SpawnWall3ID);
621
- let tWall4 = mod.GetSpatialObject(SpawnWall4ID);
622
- mod.MoveObjectOverTime(tWall1, mod.CreateVector(0, wallMoveDelta, 0), mod.CreateVector(0, 0, 0), 3, false, false);
623
- mod.MoveObjectOverTime(tWall2, mod.CreateVector(0, wallMoveDelta, 0), mod.CreateVector(0, 0, 0), 3, false, false);
624
- mod.MoveObjectOverTime(tWall3, mod.CreateVector(0, wallMoveDelta, 0), mod.CreateVector(0, 0, 0), 3, false, false);
625
- mod.MoveObjectOverTime(tWall4, mod.CreateVector(0, wallMoveDelta, 0), mod.CreateVector(0, 0, 0), 3, false, false);
626
-
627
- RefillAmmo();
628
- EnableStores(false);
629
-
630
- if (AIBackfill) {
631
- console.log("There are ", attackingTeamSize, " members of attacking team");
632
- console.log("spawn ", (5 - attackingTeamSize), " AI to attacking team");
633
- console.log("There are ", defendingTeamSize, " members of defending team");
634
- console.log("spawn ", (5 - defendingTeamSize), " AI to defending team");
635
-
636
-
637
- // Spawn AI characters to backfill
638
- for (let i = 0; i < 5 - attackingTeamSize; i++) {
639
- console.log("Spawn AI from spawner ID: ", mod.GetObjId(mod.GetSpawner(i + 10)), " to Team ID ", attackingTeamID);
640
- mod.SpawnAIFromAISpawner(mod.GetSpawner(i + 10), mod.SoldierClass.Assault, attackingTeam);
641
- await mod.Wait(0.1);
642
- }
643
-
644
- for (let i = 0; i < 5 - defendingTeamSize; i++) {
645
- console.log("Spawn AI from spawner ID: ", mod.GetObjId(mod.GetSpawner(i + 15)), " to Team ID ", defendingTeamID);
646
- mod.SpawnAIFromAISpawner(mod.GetSpawner(i + 15), mod.SoldierClass.Assault, defendingTeam);
647
- await mod.Wait(0.1);
648
- }
649
- }
650
-
651
-
652
- buyPhase = false;
653
- roundStarted = true;
654
-
655
- //mod.EnableAllPlayerDeploy(false);
656
- await mod.Wait(8);
657
-
658
- JsPlayer.playerInstances.forEach(player => {
659
- if (mod.GetSoldierState(player, mod.SoldierStateBool.IsAISoldier)) {
660
- mod.AIBattlefieldBehavior(player);
661
- }
662
- });
663
-
664
-
665
- }
666
-
667
- function RefillAmmo() {
668
- JsPlayer.playerInstances.forEach(player => {
669
- let jsPlayer = JsPlayer.get(player);
670
- if (jsPlayer) {
671
- if (mod.GetSoldierState(player, mod.SoldierStateBool.IsAlive) && jsPlayer.isDeployed) {
672
- RefillPlayersAmmo(player);
673
- console.log("Refill Ammo")
674
- }
675
- }
676
- });
677
- }
678
-
679
- function RefillPlayersAmmo(player: mod.Player) {
680
- mod.SetInventoryAmmo(player, mod.InventorySlots.PrimaryWeapon, 1000);
681
- mod.SetInventoryMagazineAmmo(player, mod.InventorySlots.PrimaryWeapon, 1000);
682
-
683
- mod.SetInventoryAmmo(player, mod.InventorySlots.SecondaryWeapon, 1000);
684
- mod.SetInventoryMagazineAmmo(player, mod.InventorySlots.SecondaryWeapon, 1000);
685
- }
686
-
687
- function IsPrimarySlotFilled(player: mod.Player): boolean {
688
- for (var enumMember in mod.Weapons) {
689
- var isValueProperty = Number(enumMember) >= 0
690
- if (isValueProperty) {
691
- let em = mod.Weapons[enumMember];
692
- if (em.includes("AssaultRifle") || em.includes("Carbine") || em.includes("DMR") ||
693
- em.includes("LMG") || em.includes("Shotgun") || em.includes("SMG") ||
694
- em.includes("Sniper")) {
695
- if (mod.HasEquipment(player, Number(enumMember))) {
696
- return true;
697
- }
698
- }
699
- }
700
- }
701
- return false;
702
- }
703
-
704
- function IsSecondarySlotFilled(player: mod.Player): boolean {
705
- for (let enumMember in mod.Weapons) {
706
- let isValueProperty = Number(enumMember) >= 0;
707
- if (isValueProperty) {
708
- let em = mod.Weapons[enumMember];
709
- if (em.includes("Sidearm")) {
710
- if (mod.HasEquipment(player, Number(enumMember))) {
711
- return true;
712
- }
713
- }
714
- }
715
- }
716
- return false;
717
- }
718
-
719
- // NO WAY TO CHECK WHICH SLOT A GADGET IS IN!!!
720
- // function IsGadget1Filled(player: mod.Player): boolean {
721
- // for (let enumMember in mod.Gadgets) {
722
- // let isValueProperty = Number(enumMember) >= 0;
723
- // if (isValueProperty) {
724
- // let em = mod.Gadgets[enumMember];
725
- // if (mod.HasEquipment(player, Number(enumMember))) {
726
- // return true;
727
- // }
728
- // }
729
- // }
730
- // return false;
731
- // }
732
-
733
- function ExplodeFeedback(pos: mod.Vector): void {
734
- let vfx: mod.VFX = mod.SpawnObject(mod.RuntimeSpawn_Common.FX_ArtilleryStrike_Explosion_GS, pos, ZEROVEC);
735
- mod.EnableVFX(vfx, true);
736
- let sfx: mod.SFX = mod.SpawnObject(mod.RuntimeSpawn_Common.FX_Gadget_C4_Explosives_Detonation, pos, ZEROVEC);
737
- mod.EnableSFX(sfx, true);
738
- mod.PlaySound(sfx, 100);
739
- }
740
-
741
-
742
- async function EndRound(winners: mod.Team): Promise<void> {
743
- let winningTeamID: number = mod.GetObjId(winners);
744
- console.log("End Round, Winning Team ID is: ", winningTeamID);
745
- console.log("Attacking Team ID is currently: ", mod.GetObjId(attackingTeam));
746
- console.log("Defending Team ID is currently: ", mod.GetObjId(defendingTeam));
747
- roundEnded = true;
748
-
749
- BombData.Reset();
750
-
751
- if (winningTeamID == mod.GetObjId(attackingTeam)) {
752
- MessageAllUI(MakeMessage(mod.stringkeys.AttackersWin), REDCOLOR);
753
- if (teamSwitchOccurred) {
754
- team2Score++;
755
- }
756
- else {
757
- team1Score++;
758
- }
759
- }
760
- else {
761
- MessageAllUI(MakeMessage(mod.stringkeys.DefendersWin), REDCOLOR);
762
- if (teamSwitchOccurred) {
763
- team1Score++;
764
- }
765
- else {
766
- team2Score++;
767
- }
768
- }
769
-
770
- await mod.Wait(roundEndBuffer);
771
-
772
- roundStarted = false;
773
-
774
- console.log("Team 1 score is: ", team1Score);
775
- console.log("Team 2 score is: ", team2Score);
776
-
777
- if (CheckVictoryState()) {
778
- return;
779
- }
780
-
781
- JsPlayer.playerInstances.forEach(player => {
782
- let jsPlayer = JsPlayer.get(player);
783
- if (jsPlayer) {
784
- if (mod.GetObjId(mod.GetTeam(player)) == winningTeamID) {
785
- jsPlayer.cash += roundWinReward;
786
- }
787
- else {
788
- jsPlayer.cash += roundLoseReward;
789
- }
790
-
791
- jsPlayer.updateWalletUI();
792
-
793
- // Kill downed players (might be causing bugs if they're downed going into the next round)
794
- if (jsPlayer.isDeployed && mod.GetSoldierState(player, mod.SoldierStateBool.IsManDown)) {
795
- mod.DealDamage(player, 100);
796
- }
797
- }
798
- });
799
-
800
- let tWall1 = mod.GetSpatialObject(SpawnWall1ID);
801
- let tWall2 = mod.GetSpatialObject(SpawnWall2ID);
802
- let tWall3 = mod.GetSpatialObject(SpawnWall3ID);
803
- let tWall4 = mod.GetSpatialObject(SpawnWall4ID);
804
- mod.MoveObject(tWall1, mod.Subtract(SpawnWallPos1, mod.GetObjectPosition(tWall1)), mod.CreateVector(0, 0, 0));
805
- mod.MoveObject(tWall2, mod.Subtract(SpawnWallPos2, mod.GetObjectPosition(tWall2)), mod.CreateVector(0, 0, 0));
806
- mod.MoveObject(tWall3, mod.Subtract(SpawnWallPos3, mod.GetObjectPosition(tWall3)), mod.CreateVector(0, 0, 0));
807
- mod.MoveObject(tWall4, mod.Subtract(SpawnWallPos4, mod.GetObjectPosition(tWall4)), mod.CreateVector(0, 0, 0));
808
-
809
- // If neither team won, reset the round
810
- SetupRound();
811
- }
812
-
813
- function SwitchTeams(): void {
814
- console.log("SWITCH TEAMS");
815
-
816
- if (mod.GetObjId(attackingTeam) == mod.GetObjId(mod.GetTeam(1))) {
817
- defendingTeam = mod.GetTeam(1);
818
- attackingTeam = mod.GetTeam(2);
819
- teamSwitchOccurred = true;
820
- }
821
- else {
822
- defendingTeam = mod.GetTeam(2);
823
- attackingTeam = mod.GetTeam(1);
824
- teamSwitchOccurred = false; // Teams switched back
825
- }
826
-
827
- console.log("Attacking Team ID is currently: ", mod.GetObjId(attackingTeam));
828
- console.log("Defending Team ID is currently: ", mod.GetObjId(defendingTeam));
829
-
830
- mod.SetWorldIconOwner(attackersStoreWI, attackingTeam);
831
- mod.SetWorldIconOwner(defendersStoreWI, defendingTeam);
832
-
833
- mod.UndeployAllPlayers();
834
- }
835
-
836
-
837
- function ResetPlayerLoadout(player: mod.Player, isOutOfRound: boolean) {
838
- if (mod.GetSoldierState(player, mod.SoldierStateBool.IsAlive)) {
839
- if (isOutOfRound)
840
- mod.RemoveEquipment(player, mod.InventorySlots.SecondaryWeapon);
841
- else
842
- mod.AddEquipment(player, mod.Weapons.Sidearm_P18, SidearmPackage_Standard_P18);
843
-
844
- mod.AddEquipment(player, mod.Gadgets.Melee_Combat_Knife);
845
- mod.RemoveEquipment(player, mod.InventorySlots.PrimaryWeapon);
846
-
847
- try {
848
- mod.RemoveEquipment(player, mod.InventorySlots.GadgetOne);
849
- }
850
- catch(e) {
851
-
852
- }
853
- try {
854
- mod.RemoveEquipment(player, mod.InventorySlots.GadgetTwo);
855
- }
856
- catch(e) {
857
-
858
- }
859
- }
860
- }
861
-
862
- function CheckVictoryState(): boolean {
863
- let scoreToWin = maxRounds / 2 + 1;
864
-
865
- // This is stupid, but winning will always occur after the team switch, so team 1 would be defending and team 2 would be attacking
866
- if (team1Score >= scoreToWin) {
867
- mod.EndGameMode(defendingTeam);
868
- return true;
869
- }
870
- else if (team2Score >= scoreToWin) {
871
- mod.EndGameMode(attackingTeam);
872
- return true;
873
- }
874
- return false;
875
- }
876
-
877
- function CleanUp() {
878
- JsPlayer.playerInstances.forEach(player => {
879
- let jsPlayer = JsPlayer.get(player);
880
- if (jsPlayer) {
881
- jsPlayer.destroyUI();
882
- }
883
- });
884
- }
885
-
886
-
887
- async function UpdateMessages() {
888
- if (messageTime > 0) {
889
- messageTime--;
890
- if (messageTime <= 0) {
891
- HideAllMessageUI();
892
- messageTime = 0;
893
- }
894
- }
895
- }
896
-
897
-
898
- export function OnPlayerEarnedKill(
899
- eventPlayer: mod.Player,
900
- eventOtherPlayer: mod.Player,
901
- eventDeathType: mod.DeathType,
902
- eventWeaponUnlock: mod.WeaponUnlock
903
- ): void {
904
-
905
- if (mod.EventDeathTypeCompare(eventDeathType, mod.PlayerDeathTypes.Redeploy))
906
- return;
907
-
908
- let jsPlayer = JsPlayer.get(eventPlayer);
909
-
910
- if (!jsPlayer)
911
- return;
912
-
913
- let playerTeamID: number = mod.GetObjId(mod.GetTeam(eventPlayer));
914
- let otherPlayerTeamID: number = -1;
915
- if (eventOtherPlayer != null) {
916
- otherPlayerTeamID = mod.GetObjId(mod.GetTeam(eventOtherPlayer));
917
- }
918
-
919
- if (playerTeamID != otherPlayerTeamID) {
920
- jsPlayer.cash += killReward;
921
- }
922
-
923
- jsPlayer.updateWalletUI();
924
- }
925
-
926
- export function OnPlayerDied(
927
- eventPlayer: mod.Player,
928
- eventOtherPlayer: mod.Player,
929
- eventDeathType: mod.DeathType,
930
- eventWeaponUnlock: mod.WeaponUnlock
931
- ): void {
932
-
933
- if (BombData.carryingPlayer && mod.IsPlayerValid(BombData.carryingPlayer) && mod.GetObjId(eventPlayer) == mod.GetObjId(BombData.carryingPlayer)) {
934
- BombData.ItemDropped(BombData.carryingPlayer);
935
- console.log("ObjectiveItemData.currentWorldIconPos: ", mod.XComponentOf(BombData.currentWorldIconPos), mod.YComponentOf(BombData.currentWorldIconPos), mod.ZComponentOf(BombData.currentWorldIconPos));
936
- }
937
-
938
- if (roundEnded) {
939
- return;
940
- }
941
-
942
- let jsPlayer = JsPlayer.get(eventPlayer);
943
- if (jsPlayer) {
944
- jsPlayer.progressBarUI?.close();
945
-
946
- if (roundStarted && !roundEnded && !buyPhase) {
947
- jsPlayer.outOfRound = true;
948
- }
949
- }
950
-
951
- if (BombData.defusingPlayer != null && mod.GetObjId(BombData.defusingPlayer) == mod.GetObjId(eventPlayer)) {
952
- console.log("Defusing player killed mid-defuse");
953
- BombData.CancelDefuse();
954
- }
955
-
956
- // Check for any remaining surviving players on the team.
957
- // When playing with a team full of bots, this often gets triggered during team assignment!
958
- if (combatStarted && !roundEnded && !buyPhase) {
959
- let deadPlayerTeamID: number = mod.GetObjId(mod.GetTeam(eventPlayer));
960
- let survivingTeamMembers: mod.Player[] = GetLivingPlayersOnTeam(mod.GetTeam(eventPlayer));
961
-
962
-
963
- console.log("Player on team ", deadPlayerTeamID, " Died. They have ", survivingTeamMembers.length, " remaining teammates.");
964
- if (survivingTeamMembers.length == 0) {
965
- if (mod.GetSoldierState(eventPlayer, mod.SoldierStateBool.IsManDown)) {
966
- console.log("Player that died is still in man down state. FINISH THEM!");
967
- mod.DealDamage(eventPlayer, 100);
968
- }
969
-
970
- // Defending team all dying is always a win for the attackers
971
- if (deadPlayerTeamID == mod.GetObjId(defendingTeam)) {
972
- console.log("All defenders have died.");
973
- EndRound(attackingTeam);
974
- }
975
- // Bomb isn't planted and attacking team is all dead
976
- if (!BombData.isPlanted && mod.GetObjId(attackingTeam) == deadPlayerTeamID) {
977
- console.log("All attackers are dead and the bomb is not planted.");
978
- EndRound(defendingTeam);
979
- }
980
- else if (BombData.isPlanted && mod.GetObjId(attackingTeam) == deadPlayerTeamID) {
981
- console.log("Player on attacking team is killed. Bomb is currently planted, so must be defused before round can end.");
982
- }
983
- }
984
-
985
- }
986
- }
987
-
988
- function GetLivingPlayersOnTeam(team: mod.Team): mod.Player[] {
989
- let teamArr: mod.Player[] = [];
990
- let teamID = mod.GetObjId(team);
991
- JsPlayer.playerInstances.forEach(player => {
992
- let jsPlayer = JsPlayer.get(player);
993
- if (mod.GetObjId(mod.GetTeam(player)) == teamID && !jsPlayer?.outOfRound) {
994
- teamArr.push(player);
995
- }
996
- });
997
-
998
- return teamArr;
999
- }
1000
-
1001
- export function OnPlayerUndeploy(eventPlayer: mod.Player): void {
1002
- let jsPlayer = JsPlayer.get(eventPlayer);
1003
- if (jsPlayer)
1004
- jsPlayer.isDeployed = false;
1005
- }
1006
-
1007
-
1008
- // Called whenever a player interacts with an object
1009
- export async function OnPlayerInteract(player: mod.Player, interactPoint: any) {
1010
- // ObjIds are assigned IN GODOT. I recommend assigning them to const numbers in the global scope
1011
- let id = mod.GetObjId(interactPoint);
1012
- let jsPlayer = JsPlayer.get(player);
1013
-
1014
- if (!jsPlayer) {
1015
- console.log("Interaction attempted with invalid JSPlayer! Interact Point ID is: ", id);
1016
- return;
1017
- }
1018
-
1019
- if (buyPhase && (id == storeID_attackers || storeID_defenders)) {
1020
- jsPlayer.store?.open();
1021
- }
1022
-
1023
- if (BombData.carryingPlayer != null && mod.GetObjId(player) == mod.GetObjId(BombData.carryingPlayer)) {
1024
- if (id == pointAAreaID) {
1025
- console.log("Begin planting at A");
1026
- BombData.isAtA = true;
1027
- jsPlayer.progressBarUI?.open(MakeMessage(mod.stringkeys.planting));
1028
- BombData.isPlanting = true;
1029
- }
1030
- else if (id == pointBAreaID) {
1031
- console.log("Begin planting at B");
1032
- BombData.isAtB = true;
1033
- jsPlayer.progressBarUI?.open(MakeMessage(mod.stringkeys.planting));
1034
- BombData.isPlanting = true;
1035
- }
1036
- }
1037
-
1038
- if (BombData.isPlanted && mod.GetObjId(mod.GetTeam(player)) == mod.GetObjId(defendingTeam)) {
1039
- if (id == pointAAreaID || id == pointBAreaID) {
1040
- BombData.defusingPlayer = player;
1041
- let jsPlayer = JsPlayer.get(player);
1042
- if (!jsPlayer) {
1043
- console.log("Attempting bomb defuse with invalid JSPlayer!!!!");
1044
- return;
1045
- }
1046
- jsPlayer.progressBarUI?.open(MakeMessage(mod.stringkeys.defusing));
1047
- }
1048
- }
1049
- }
1050
-
1051
-
1052
- async function CombatCountdown(): Promise<void> {
1053
- combatCountdownStarted = true;
1054
- console.log("Combat Countdown Started")
1055
-
1056
- // INSTANT_START debug flag will skip the countdown delay
1057
- while (combatStartDelayRemaining > -1 && !INSTANT_START) {
1058
- UpdateAllLobbyUI();
1059
- await mod.Wait(1);
1060
- combatStartDelayRemaining--;
1061
- }
1062
-
1063
- combatStarted = true;
1064
- HideAllLobbyUI();
1065
- return Promise.resolve();
1066
-
1067
- }
1068
-
1069
-
1070
- function UpdateAllLobbyUI() {
1071
-
1072
- JsPlayer.playerInstances.forEach(player => {
1073
- let jsPlayer = JsPlayer.get(player);
1074
- if (!jsPlayer)
1075
- return;
1076
- jsPlayer.lobbyUI?.refresh();
1077
- });
1078
- }
1079
-
1080
- function MessageAllUI(message: mod.Message, textColor: number[]) {
1081
- JsPlayer.playerInstances.forEach(player => {
1082
- let jsPlayer = JsPlayer.get(player);
1083
- if (!jsPlayer)
1084
- return;
1085
- if (jsPlayer.messageUI?.isOpen()) {
1086
- jsPlayer.messageUI.refresh(message);
1087
- }
1088
- else {
1089
- jsPlayer.messageUI?.open(message, textColor);
1090
- }
1091
- });
1092
- messageTime = messageRemainTime;
1093
- }
1094
-
1095
- function MessagePlayer(player: JsPlayer, message: mod.Message, textColor: number[]) {
1096
- if (player.messageUI?.isOpen()) {
1097
- player.messageUI?.refresh(message);
1098
- }
1099
- else {
1100
- player.messageUI?.open(message, textColor);
1101
- }
1102
-
1103
- mod.Wait(3);
1104
- player.messageUI?.close();
1105
- }
1106
-
1107
- function HideAllMessageUI() {
1108
- console.log("Hide all message UI");
1109
- JsPlayer.playerInstances.forEach(player => {
1110
- let jsPlayer = JsPlayer.get(player);
1111
- if (!jsPlayer)
1112
- return;
1113
- jsPlayer.messageUI?.close();
1114
- });
1115
- }
1116
-
1117
- function HideAllLobbyUI() {
1118
- console.log("Hide lobby UI");
1119
- JsPlayer.playerInstances.forEach((player) => {
1120
- let jsPlayer = JsPlayer.get(player);
1121
- if (!jsPlayer)
1122
- return;
1123
- jsPlayer.lobbyUI?.close();
1124
- });
1125
- }
1126
-
1127
- function MakeMessage(message: string, ...args: any[]) {
1128
- switch (args.length) {
1129
- case 0:
1130
- return mod.Message(message);
1131
- case 1:
1132
- return mod.Message(message, args[0]);
1133
- case 2:
1134
- return mod.Message(message, args[0], args[1]);
1135
- default:
1136
- return mod.Message(message, args[0], args[1], args[2]);
1137
- }
1138
- }
1139
-
1140
-
1141
- export function OnCapturePointCapturing(eventCapturePoint: mod.CapturePoint): void {
1142
- mod.DisplayNotificationMessage(MakeMessage(mod.stringkeys.teamCapture));
1143
- }
1144
-
1145
- export function OnGameModeEnding(): void {
1146
- HideAllMessageUI();
1147
- CleanUp();
1148
- }
1149
-
1150
-
1151
-
1152
-
1153
- //-----------------------------------------------------------------------------------------------//
1154
- //-----------------------------------------------------------------------------------------------//
1155
- //-------------------------------------- RYAN W STORE -------------------------------------------//
1156
- //-----------------------------------------------------------------------------------------------//
1157
- //-----------------------------------------------------------------------------------------------//
1158
-
1159
-
1160
- export function OnPlayerUIButtonEvent(player: mod.Player, widget: any, event: any) {
1161
- //console.log("got button event for widget: " + mod.GetUIWidgetName(widget));
1162
-
1163
- // send to the store?
1164
- let jsPlayer = JsPlayer.get(player);
1165
- if (!jsPlayer)
1166
- return;
1167
- jsPlayer.store.onUIButtonEvent(widget as mod.UIWidget, event);
1168
- }
1169
-
1170
-
1171
- //-----------------------------------------------------------------------------------------------//
1172
- //-----------------------------------------------------------------------------------------------//
1173
- //-----------------------------------------------------------------------------------------------//
1174
- //-----------------------------------------------------------------------------------------------//
1175
- // Helper Functions:
1176
- //-----------------------------------------------------------------------------------------------//
1177
-
1178
- function GetRandomFloatInRange(max: number, min: number) {
1179
- return Math.random() * (max - min) + min;
1180
- }
1181
-
1182
- function GetRandomInt(max: number): number {
1183
- return Math.floor(Math.random() * max);
1184
- }
1185
-
1186
- /// ----------------------------------- JS PLAYER --------------------------------------------------------------
1187
-
1188
- class JsPlayer {
1189
- player: mod.Player;
1190
- playerId: number;
1191
- store: any;
1192
- cash = initialCash
1193
- maxHealth = 100;
1194
- currentHealth = 100;
1195
- bonusDamage = 0;
1196
-
1197
- // stats:
1198
- kills: number = 0;
1199
- deaths: number = 0;
1200
- totalCashEarned: number = 0;
1201
-
1202
-
1203
- isDeployed = false;
1204
- hasDeployed = false;
1205
-
1206
- outOfRound: boolean = false;
1207
-
1208
- playerwalletWidget: mod.UIWidget|undefined;
1209
- playerNotificationWidget: mod.UIWidget|undefined;
1210
- playerhealthWidget: mod.UIWidget|undefined;
1211
- itemBuysPerRound: any = {}; // a count of each item bought this round, keyed by itemDatas.id
1212
-
1213
-
1214
- lobbyUI;
1215
- messageUI;
1216
- scoreUI;
1217
- dropBombIndicator;
1218
- hasBombIndicator;
1219
- versionUI;
1220
- progressBarUI;
1221
-
1222
- static playerInstances: mod.Player[] = [];
1223
-
1224
- constructor(player: mod.Player) {
1225
- this.player = player;
1226
- this.playerId = mod.GetObjId(player);
1227
- JsPlayer.playerInstances.push(this.player);
1228
- if (debugJSPlayer) {console.log("Bomb Defusal Adding Player [", mod.GetObjId(this.player), "] Creating JS Player: ", JsPlayer.playerInstances.length)};
1229
-
1230
- // Never create UI elements for AI soldiers, because late joining players will inherit their Object IDs, and thus their UI
1231
- if (!mod.GetSoldierState(player, mod.SoldierStateBool.IsAISoldier)) {
1232
- this.createWalletUI();
1233
- this.openWalletUI();
1234
-
1235
- this.store = new Store(this, cStoreData);
1236
- this.lobbyUI = new LobbyUI(this);
1237
- this.scoreUI = new ScoreUI(this);
1238
- this.messageUI = new MessageUI(this);
1239
- this.dropBombIndicator = new DropBombIndicator(this);
1240
- this.hasBombIndicator = new HasBombIndicator(this);
1241
- this.versionUI = new VersionUI(this);
1242
- this.progressBarUI = new ProgressBar(this);
1243
- }
1244
- }
1245
-
1246
- // declare dictionary with int keys
1247
- static #allJsPlayers: { [key: number] : JsPlayer } = {};
1248
-
1249
- static get(player: mod.Player) {
1250
- if (!gameOver && mod.GetObjId(player) > -1) {
1251
- let index = mod.GetObjId(player);
1252
-
1253
- let jsPlayer = this.#allJsPlayers[index];
1254
- if (!jsPlayer) {
1255
- jsPlayer = new JsPlayer(player);
1256
- this.#allJsPlayers[index] = jsPlayer;
1257
- }
1258
-
1259
- return jsPlayer;
1260
- }
1261
- return undefined;
1262
- }
1263
-
1264
- static removeInvalidJSPlayers(invalidPlayerId: number){
1265
- if (!gameOver){
1266
- if (debugJSPlayer) {console.log("Removing Invalid JSPlayers currently: ", JsPlayer.playerInstances.length)}
1267
- let allPlayersLength = Object.keys((JsPlayer.#allJsPlayers)).length;
1268
- if (debugJSPlayer) {console.log("#allJsPlayers Length: ", JsPlayer.playerInstances.length)}
1269
- let n = 0;
1270
- let indexToRemove = -1;
1271
- JsPlayer.playerInstances.forEach((indexPlayer) => {
1272
- if (mod.GetObjId(JsPlayer.playerInstances[n]) < 0){
1273
- indexToRemove = n;
1274
- }
1275
- n++
1276
- })
1277
-
1278
- this.#allJsPlayers[invalidPlayerId].destroyUI(); // Brute force disallow the double UI bug
1279
- delete this.#allJsPlayers[invalidPlayerId];
1280
-
1281
- if (indexToRemove > -1){
1282
- JsPlayer.playerInstances.splice(indexToRemove, 1)
1283
- }
1284
-
1285
- if (debugJSPlayer) {console.log("Player [", invalidPlayerId, "] removed. JSPlayers Remaining: ", JsPlayer.playerInstances.length)}
1286
- allPlayersLength = Object.keys((JsPlayer.#allJsPlayers)).length;
1287
- if (debugJSPlayer) {console.log("#allJsPlayers New Length: ", JsPlayer.playerInstances.length)}
1288
-
1289
- }
1290
- }
1291
-
1292
- static getAllAsArray() {
1293
- return Object.values(this.#allJsPlayers);
1294
- }
1295
-
1296
- static IsPlayer(id: number) {
1297
- if (!this.#allJsPlayers[id]) {
1298
- return false;
1299
- }
1300
- return true;
1301
- }
1302
-
1303
- static getRandomJsPlayer() {
1304
- let i = GetRandomInt(JsPlayer.playerInstances.length);
1305
- return JsPlayer.playerInstances[i];
1306
- }
1307
-
1308
- static getValidJsPlayer() {
1309
-
1310
- //console.log("M12 getValidJsPlayer: ")
1311
-
1312
- let aliveAndFreeJSPlayers: mod.Player[] = [];
1313
-
1314
- let n = JsPlayer.playerInstances.length;
1315
- //console.log("M12 getValidJsPlayer length: ", n)
1316
- for (let i = 0; i < n; i++) {
1317
- //console.log("M12 candidate player = ", JsPlayer.get(JsPlayer.playerInstances[i]))
1318
- let candidateJsPlayer = JsPlayer.get(JsPlayer.playerInstances[i]);
1319
- if (!candidateJsPlayer)
1320
- continue;
1321
- }
1322
-
1323
- if (aliveAndFreeJSPlayers.length > 0) {
1324
- let i = GetRandomInt(aliveAndFreeJSPlayers.length);
1325
- let validJsPlayer = aliveAndFreeJSPlayers[i];
1326
- //console.log("M12 Returning Valid JS Player: ", validJsPlayer)
1327
- return validJsPlayer as mod.Player
1328
- } else {
1329
- //console.log("M12 There are no Free & Alive JS Players")
1330
- return null;
1331
- }
1332
- }
1333
-
1334
- static anyJsPlayersAlive() {
1335
- let anyPlayersStillAlive = false;
1336
-
1337
- JsPlayer.playerInstances.forEach((player) => {
1338
- let jsPlayer = JsPlayer.get(player);
1339
- if (!jsPlayer)
1340
- return;
1341
- });
1342
-
1343
- if (anyPlayersStillAlive) {
1344
- return true;
1345
- } else {
1346
- return false;
1347
- }
1348
-
1349
- }
1350
-
1351
- destroyUI() {
1352
- console.log("Destroy UI");
1353
- this.closeWalletUI();
1354
- this.store?.close();
1355
- this.lobbyUI?.close();
1356
- this.scoreUI?.close();
1357
- this.messageUI?.close();
1358
- this.dropBombIndicator?.close();
1359
- this.hasBombIndicator?.close();
1360
- this.versionUI?.close();
1361
- this.progressBarUI?.close();
1362
- }
1363
-
1364
-
1365
- createWalletUI() {
1366
- this.playerwalletWidget = ParseUI({
1367
- type: "Text",
1368
- position: [50, 50],
1369
- size: [200, 40],
1370
- anchor: mod.UIAnchor.TopLeft,
1371
- textLabel: MakeMessage(mod.stringkeys.playerwallet, this.cash),
1372
- playerId: this.player,
1373
- visible: false,
1374
- })
1375
- }
1376
-
1377
- openWalletUI() {
1378
- if (!this.playerwalletWidget)
1379
- return;
1380
- mod.SetUIWidgetVisible(this.playerwalletWidget, true);
1381
- }
1382
-
1383
- updateWalletUI() {
1384
- if (!this.playerwalletWidget)
1385
- return;
1386
- mod.SetUITextLabel(this.playerwalletWidget, MakeMessage(mod.stringkeys.playerwallet, this.cash));
1387
- }
1388
-
1389
- closeWalletUI() {
1390
- if (this.playerwalletWidget) {
1391
- mod.SetUIWidgetVisible(this.playerwalletWidget, false);
1392
- }
1393
- }
1394
- }
1395
-
1396
-
1397
- //-----------------------------------------------------------------------------------------------//
1398
-
1399
- class ScoreUI {
1400
- #jsPlayer;
1401
- #rootWidget: mod.UIWidget|undefined;
1402
-
1403
- #containerWidth = 150;
1404
- #containerHeight = 60;
1405
- #isIndicatorVisible = false;
1406
-
1407
- #roundTime: mod.UIWidget|undefined;
1408
- #allyTeamScore: mod.UIWidget|undefined;
1409
- #enemyTeamScore: mod.UIWidget|undefined;
1410
- #teamDesignation: mod.UIWidget|undefined;
1411
-
1412
-
1413
- constructor(jsPlayer: JsPlayer) {
1414
- this.#jsPlayer = jsPlayer;
1415
- console.log("Create score UI for ", jsPlayer.player, " with ID: ", jsPlayer.playerId)
1416
- this.#create();
1417
- if (!this.#rootWidget)
1418
- return;
1419
-
1420
- mod.SetUIWidgetVisible(this.#rootWidget, true);
1421
- }
1422
-
1423
-
1424
- refresh() {
1425
- if (!this.#roundTime || !this.#allyTeamScore || !this.#enemyTeamScore || !this.#teamDesignation)
1426
- {
1427
- return;
1428
- }
1429
-
1430
- // refresh the lobby status text:
1431
- let time: number; // Either display setup/buy time or round time remaining
1432
- if (roundStarted) {
1433
- time = roundTime;
1434
- if (mod.GetObjId(attackingTeam) == mod.GetObjId(mod.GetTeam(this.#jsPlayer.player))) {
1435
- mod.SetUITextLabel(this.#teamDesignation, MakeMessage(mod.stringkeys.attackingTeam));
1436
- }
1437
- else {
1438
- mod.SetUITextLabel(this.#teamDesignation, MakeMessage(mod.stringkeys.defendingTeam));
1439
- }
1440
- }
1441
- else {
1442
- time = buyPhaseTimeRemaining;
1443
- mod.SetUITextLabel(this.#teamDesignation, MakeMessage(mod.stringkeys.buyPhase));
1444
- //console.log("there is ", time, " time remaining in the buy phase");
1445
- }
1446
-
1447
-
1448
- let minutes = Math.max(Math.floor(time / 60), 0);
1449
- let seconds = Math.max(Math.ceil(time % 60), 0);
1450
- let seconds1 = Math.max(Math.floor(seconds / 10), 0);
1451
- let seconds2 = Math.max(Math.floor(seconds % 10), 0);
1452
- mod.SetUITextLabel(this.#roundTime, MakeMessage(mod.stringkeys.roundTime, minutes, seconds1, seconds2));
1453
-
1454
- // #allyTeamScore is just the score on the left, and #enemyTeamScore is the one on the right
1455
- // so really #allyTeamScore is "allied team" score and #enemyTeamScore is "enemy team score"
1456
- if (mod.GetObjId(mod.GetTeam(this.#jsPlayer.player)) == 1) {
1457
- mod.SetUITextLabel(this.#allyTeamScore, MakeMessage(mod.stringkeys.score, team1Score));
1458
- mod.SetUITextLabel(this.#enemyTeamScore, MakeMessage(mod.stringkeys.score, team2Score));
1459
- }
1460
- else {
1461
- mod.SetUITextLabel(this.#allyTeamScore, MakeMessage(mod.stringkeys.score, team2Score));
1462
- mod.SetUITextLabel(this.#enemyTeamScore, MakeMessage(mod.stringkeys.score, team1Score));
1463
- }
1464
-
1465
- mod.SetUITextColor(this.#allyTeamScore, mod.CreateVector(0, .2, 1));
1466
- mod.SetUITextColor(this.#enemyTeamScore, mod.CreateVector(1, 0, 0));
1467
- }
1468
-
1469
- #create() {
1470
- this.#isIndicatorVisible = true;
1471
- // background:
1472
- this.#rootWidget = ParseUI({
1473
- type: "Container",
1474
- size: [this.#containerWidth, this.#containerHeight],
1475
- position: [0, 30],
1476
- anchor: mod.UIAnchor.TopCenter,
1477
- bgFill: mod.UIBgFill.Blur,
1478
- //bgColor: this.#activeTabBgColor,
1479
- bgAlpha: 1,
1480
- playerId: this.#jsPlayer.player,
1481
- });
1482
- this.#roundTime = ParseUI({
1483
- type: "Text",
1484
- parent: this.#rootWidget,
1485
- textSize: 24,
1486
- position: [0, 10, 0],
1487
- size: [this.#containerWidth / 3, 50],
1488
- anchor: mod.UIAnchor.TopCenter,
1489
- textAnchor: mod.UIAnchor.Center,
1490
- bgAlpha: 0,
1491
- bgColor: [0, 0, 0],
1492
- textLabel: MakeMessage(mod.stringkeys.roundTime, "05", "00"),
1493
- });
1494
- this.#allyTeamScore = ParseUI({
1495
- type: "Text",
1496
- parent: this.#rootWidget,
1497
- textSize: 24,
1498
- position: [4, 20, 0],
1499
- size: [this.#containerWidth / 4, 50],
1500
- anchor: mod.UIAnchor.TopLeft,
1501
- textAnchor: mod.UIAnchor.TopLeft,
1502
- bgAlpha: 0,
1503
- bgColor: [0, 0, 0],
1504
- textLabel: MakeMessage(mod.stringkeys.score, 0),
1505
- });
1506
- this.#enemyTeamScore = ParseUI({
1507
- type: "Text",
1508
- parent: this.#rootWidget,
1509
- textSize: 24,
1510
- position: [4, 20, 0],
1511
- size: [this.#containerWidth / 4, 50],
1512
- anchor: mod.UIAnchor.TopRight,
1513
- textAnchor: mod.UIAnchor.TopRight,
1514
- bgAlpha: 0,
1515
- bgColor: [0, 0, 0],
1516
- textLabel: MakeMessage(mod.stringkeys.score, 0),
1517
- });
1518
- this.#teamDesignation = ParseUI({
1519
- type: "Text",
1520
- parent: this.#rootWidget,
1521
- textSize: 24,
1522
- position: [0, -50, 0],
1523
- size: [this.#containerWidth * 2 / 3, 50],
1524
- anchor: mod.UIAnchor.BottomCenter,
1525
- textAnchor: mod.UIAnchor.Center,
1526
- bgAlpha: 0.5,
1527
- bgColor: [0, 0, 1],
1528
- textColor: [1, 1, 1],
1529
- textLabel: MakeMessage(mod.stringkeys.waiting, 0),
1530
- });
1531
- }
1532
-
1533
- close() {
1534
- if (this.#rootWidget) {
1535
- mod.SetUIWidgetVisible(this.#rootWidget, false);
1536
- this.#isIndicatorVisible = false;
1537
- }
1538
- }
1539
-
1540
- isOpen() {
1541
- return this.#isIndicatorVisible;
1542
- }
1543
- }
1544
-
1545
- class VersionUI {
1546
- #jsPlayer: JsPlayer;
1547
- #rootWidget: mod.UIWidget|undefined;
1548
-
1549
- #containerWidth = 180;
1550
- #containerHeight = 40;
1551
- #backgroundSpacing = 4;
1552
- #isIndicatorVisible = false;
1553
-
1554
- constructor(jsPlayer: JsPlayer) {
1555
- this.#jsPlayer = jsPlayer;
1556
-
1557
- if (!this.#rootWidget)
1558
- this.#create();
1559
- if (!this.#rootWidget)
1560
- return;
1561
-
1562
- mod.SetUIWidgetVisible(this.#rootWidget, true);
1563
- }
1564
-
1565
- #create() {
1566
- console.log("Create VersionUI")
1567
- this.#isIndicatorVisible = true;
1568
- this.#rootWidget = ParseUI({
1569
- type: "Container",
1570
- size: [this.#containerWidth, this.#containerHeight],
1571
- position: [0, 20],
1572
- anchor: mod.UIAnchor.TopRight,
1573
- bgFill: mod.UIBgFill.Blur,
1574
- bgColor: [0,0,0],
1575
- bgAlpha: 0,
1576
- playerId: this.#jsPlayer.player,
1577
- children: [{
1578
- type: "Text",
1579
- textSize: 18,
1580
- position: [0, 0, 0],
1581
- size: [this.#containerWidth - this.#backgroundSpacing * 2, this.#containerHeight],
1582
- anchor: mod.UIAnchor.Center,
1583
- textAnchor: mod.UIAnchor.Center,
1584
- bgAlpha: 0,
1585
- textLabel: MakeMessage(mod.stringkeys.version, VERSION[0], VERSION[1], VERSION[2]),
1586
- }]
1587
- })
1588
- }
1589
-
1590
- close() {
1591
- if (this.#rootWidget) {
1592
- mod.SetUIWidgetVisible(this.#rootWidget, false);
1593
- this.#isIndicatorVisible = false;
1594
- }
1595
- }
1596
-
1597
- isOpen() {
1598
- return this.#isIndicatorVisible;
1599
- }
1600
- }
1601
-
1602
- class ProgressBar {
1603
- #jsPlayer;
1604
- #rootWidget: mod.UIWidget|undefined;
1605
- #fillWidget: mod.UIWidget|undefined;
1606
- #labelWidget: mod.UIWidget|undefined;
1607
- #currentProgress: number = 0; // 0-1
1608
- #isIndicatorVisible = false;
1609
- #containerWidth = 180;
1610
- #containerHeight = 50;
1611
-
1612
- constructor(jsPlayer: JsPlayer) {
1613
- this.#jsPlayer = jsPlayer;
1614
- }
1615
-
1616
- open(label: mod.Message) {
1617
- if (!this.#rootWidget)
1618
- this.#create(label);
1619
- if (!this.#rootWidget)
1620
- return;
1621
-
1622
- mod.SetUIWidgetVisible(this.#rootWidget, true);
1623
- this.#isIndicatorVisible = true;
1624
- }
1625
-
1626
- close() {
1627
- if (this.#rootWidget) {
1628
- mod.SetUIWidgetVisible(this.#rootWidget, false);
1629
- this.#isIndicatorVisible = false;
1630
- }
1631
- }
1632
-
1633
- refresh(progress: number) {
1634
- this.#currentProgress = progress;
1635
-
1636
- if (this.#fillWidget)
1637
- mod.SetUIWidgetSize(this.#fillWidget, mod.CreateVector(progress * this.#containerWidth, this.#containerHeight, 1));
1638
- else
1639
- console.log("fill widget is null!");
1640
- }
1641
-
1642
- isOpen() {
1643
- return this.#isIndicatorVisible;
1644
- }
1645
-
1646
- #create(label: mod.Message) {
1647
- console.log("Create has bomb indicator UI");
1648
- // background:
1649
- this.#rootWidget = ParseUI({
1650
- type: "Container",
1651
- size: [this.#containerWidth, this.#containerHeight],
1652
- position: [0, 150],
1653
- anchor: mod.UIAnchor.BottomCenter,
1654
- bgFill: mod.UIBgFill.None,
1655
- bgColor: [0, 0, 0],
1656
- bgAlpha: 1,
1657
- playerId: this.#jsPlayer.player,
1658
- children: [{
1659
- // Background
1660
- type: "Container",
1661
- position: [0, 0],
1662
- size: [this.#containerWidth, this.#containerHeight],
1663
- anchor: mod.UIAnchor.Center,
1664
- bgFill: mod.UIBgFill.Blur,
1665
- bgColor: BLACKCOLOR,
1666
- bgAlpha: 1,
1667
- }, ]
1668
- });
1669
-
1670
- this.#fillWidget = ParseUI({
1671
- type: "Container",
1672
- parent: this.#rootWidget,
1673
- size: [0, this.#containerHeight],
1674
- position: [0, 0],
1675
- anchor: mod.UIAnchor.CenterLeft,
1676
- bgFill: mod.UIBgFill.GradientLeft,
1677
- bgColor: [0, 1, 0.3],
1678
- bgAlpha: 1,
1679
- });
1680
-
1681
- this.#labelWidget = ParseUI({
1682
- type: "Text",
1683
- parent: this.#rootWidget,
1684
- textSize: 18,
1685
- position: [-this.#containerWidth, 0, 0],
1686
- size: [this.#containerWidth, this.#containerHeight],
1687
- anchor: mod.UIAnchor.CenterLeft,
1688
- textAnchor: mod.UIAnchor.Center,
1689
- bgAlpha: 0,
1690
- textLabel: label,
1691
- });
1692
- }
1693
- }
1694
-
1695
-
1696
- class HasBombIndicator {
1697
- #jsPlayer: JsPlayer;
1698
- #rootWidget: mod.UIWidget|undefined;
1699
-
1700
- #containerWidth = 180;
1701
- #containerHeight = 80;
1702
- #backgroundSpacing = 4;
1703
-
1704
-
1705
- #isIndicatorVisible = false;
1706
-
1707
- constructor(jsPlayer: JsPlayer) {
1708
- this.#jsPlayer = jsPlayer;
1709
- }
1710
-
1711
- open() {
1712
- if (!this.#rootWidget)
1713
- this.#create();
1714
- if (!this.#rootWidget)
1715
- return;
1716
-
1717
- mod.SetUIWidgetVisible(this.#rootWidget, true);
1718
- this.#isIndicatorVisible = true;
1719
- }
1720
-
1721
- close() {
1722
- if (this.#rootWidget) {
1723
- mod.SetUIWidgetVisible(this.#rootWidget, false);
1724
- this.#isIndicatorVisible = false;
1725
- }
1726
- }
1727
-
1728
- isOpen() {
1729
- return this.#isIndicatorVisible;
1730
- }
1731
-
1732
- #create() {
1733
- console.log("Create has bomb indicator UI");
1734
- // background:
1735
- this.#rootWidget = ParseUI({
1736
- type: "Container",
1737
- size: [this.#containerWidth, this.#containerHeight],
1738
- position: [200, 30],
1739
- anchor: mod.UIAnchor.BottomCenter,
1740
- bgFill: mod.UIBgFill.Blur,
1741
- bgColor: [0, 0, 0],
1742
- bgAlpha: 1,
1743
- playerId: this.#jsPlayer.player,
1744
- children: [{
1745
- // Black Background
1746
- type: "Container",
1747
- position: [0, 0],
1748
- size: [this.#containerWidth - this.#backgroundSpacing, this.#containerHeight - this.#backgroundSpacing],
1749
- anchor: mod.UIAnchor.Center,
1750
- bgFill: mod.UIBgFill.Blur,
1751
- bgColor: BLACKCOLOR,
1752
- bgAlpha: 1,
1753
- }, {
1754
- type: "Text",
1755
- textSize: 18,
1756
- position: [0, 0, 0],
1757
- size: [this.#containerWidth - this.#backgroundSpacing * 2, this.#containerHeight],
1758
- anchor: mod.UIAnchor.Center,
1759
- textAnchor: mod.UIAnchor.Center,
1760
- bgAlpha: 0,
1761
- textLabel: MakeMessage(mod.stringkeys.bombCarrier),
1762
- }, ]
1763
- });
1764
- }
1765
- }
1766
-
1767
-
1768
- //-----------------------------------------------------------------------------------------------//
1769
-
1770
-
1771
- class DropBombIndicator {
1772
- #jsPlayer: JsPlayer;
1773
- #rootWidget: mod.UIWidget|undefined;
1774
-
1775
-
1776
- #containerWidth = 180;
1777
- #containerHeight = 80;
1778
- #backgroundSpacing = 4;
1779
-
1780
-
1781
- #isIndicatorVisible = false;
1782
-
1783
- constructor(jsPlayer: JsPlayer) {
1784
- this.#jsPlayer = jsPlayer;
1785
- }
1786
-
1787
- open() {
1788
- if (!this.#rootWidget)
1789
- this.#create();
1790
- if (!this.#rootWidget)
1791
- return;
1792
-
1793
- mod.SetUIWidgetVisible(this.#rootWidget, true);
1794
- this.#isIndicatorVisible = true;
1795
- }
1796
-
1797
- close() {
1798
- if (this.#rootWidget) {
1799
- mod.SetUIWidgetVisible(this.#rootWidget, false);
1800
- this.#isIndicatorVisible = false;
1801
- }
1802
- }
1803
-
1804
- isOpen() {
1805
- return this.#isIndicatorVisible;
1806
- }
1807
-
1808
- #create() {
1809
- // background:
1810
- this.#rootWidget = ParseUI({
1811
- type: "Container",
1812
- size: [this.#containerWidth, this.#containerHeight],
1813
- position: [0, 30],
1814
- anchor: mod.UIAnchor.BottomCenter,
1815
- bgFill: mod.UIBgFill.Blur,
1816
- bgColor: [0, 0, 0],
1817
- bgAlpha: 1,
1818
- playerId: this.#jsPlayer.player,
1819
- children: [{
1820
- // Black Background
1821
- type: "Container",
1822
- position: [0, 0],
1823
- size: [this.#containerWidth - this.#backgroundSpacing, this.#containerHeight - this.#backgroundSpacing],
1824
- anchor: mod.UIAnchor.Center,
1825
- bgFill: mod.UIBgFill.Blur,
1826
- bgColor: BLACKCOLOR,
1827
- bgAlpha: 1,
1828
- }, {
1829
- type: "Text",
1830
- textSize: 18,
1831
- position: [0, 0, 0],
1832
- size: [this.#containerWidth - this.#backgroundSpacing * 2, this.#containerHeight],
1833
- anchor: mod.UIAnchor.Center,
1834
- textAnchor: mod.UIAnchor.Center,
1835
- bgAlpha: 0,
1836
- textLabel: MakeMessage(mod.stringkeys.dropBombTip),
1837
- }]
1838
- });
1839
- }
1840
- }
1841
-
1842
- //-----------------------------------------------------------------------------------------------//
1843
-
1844
- class LobbyUI {
1845
- #jsPlayer;
1846
- #rootWidget: mod.UIWidget|undefined;
1847
-
1848
- #containerWidth = 700;
1849
- #containerHeight = 300;
1850
- #lineBreakHeight = 3;
1851
- #backgroundSpacing = 4;
1852
- #activeTabBgColor = BLACKCOLOR;
1853
-
1854
- #lobbyStatusText: mod.UIWidget|undefined;
1855
-
1856
- #isUIVisible = false;
1857
-
1858
- constructor(jsPlayer: JsPlayer) {
1859
- this.#jsPlayer = jsPlayer;
1860
- }
1861
-
1862
- open() {
1863
- if (!this.#rootWidget)
1864
- this.#create();
1865
- if (!this.#rootWidget)
1866
- return;
1867
- // this.refresh();
1868
- mod.SetUIWidgetVisible(this.#rootWidget, true);
1869
- this.#isUIVisible = true;
1870
- }
1871
-
1872
- close() {
1873
- if (this.#rootWidget) {
1874
- mod.SetUIWidgetVisible(this.#rootWidget, false);
1875
- this.#isUIVisible = false;
1876
- }
1877
- }
1878
-
1879
- isOpen() {
1880
- return this.#isUIVisible;
1881
- }
1882
-
1883
- refresh() {
1884
- if (!this.#lobbyStatusText)
1885
- {
1886
- console.log("No lobby status text");
1887
- return;
1888
- }
1889
- // refresh the lobby status text:
1890
- if (combatCountdownStarted) {
1891
- mod.SetUITextLabel(this.#lobbyStatusText, MakeMessage(mod.stringkeys.combatStartDelayCountdown, combatStartDelayRemaining));
1892
- }
1893
- else {
1894
- mod.SetUITextLabel(this.#lobbyStatusText, MakeMessage(mod.stringkeys.waitingforplayersX, initialPlayerCount, 10, minimumInitialPlayerCount));
1895
- }
1896
- }
1897
-
1898
- #create() {
1899
- // background:
1900
- this.#rootWidget = ParseUI({
1901
- type: "Container",
1902
- size: [this.#containerWidth, this.#containerHeight],
1903
- position: [0, 100],
1904
- anchor: mod.UIAnchor.TopCenter,
1905
- bgFill: mod.UIBgFill.Solid,
1906
- bgColor: this.#activeTabBgColor,
1907
- bgAlpha: 1,
1908
- playerId: this.#jsPlayer.player,
1909
- children: [{
1910
- // Black Background
1911
- type: "Container",
1912
- position: [0, 0],
1913
- size: [this.#containerWidth - this.#backgroundSpacing, this.#containerHeight - this.#backgroundSpacing],
1914
- anchor: mod.UIAnchor.Center,
1915
- bgFill: mod.UIBgFill.Solid,
1916
- bgColor: [0.1, 0.1, 0.1],
1917
- bgAlpha: 1
1918
- }, {
1919
- // Line Break Line
1920
- type: "Container",
1921
- position: [0, 100],
1922
- size: [this.#containerWidth - 50, this.#lineBreakHeight],
1923
- anchor: mod.UIAnchor.BottomCenter,
1924
- bgFill: mod.UIBgFill.Solid,
1925
- bgColor: BLACKCOLOR,
1926
- bgAlpha: 1
1927
- }, {
1928
- // Experience Title Text:
1929
- type: "Text",
1930
- textSize: 72,
1931
- position: [0, 25, 0],
1932
- size: [this.#containerWidth, 150],
1933
- anchor: mod.UIAnchor.TopCenter,
1934
- textAnchor: mod.UIAnchor.TopCenter,
1935
- bgAlpha: 0,
1936
- //bgColor: REDCOLOR,
1937
- textLabel: MakeMessage(mod.stringkeys.titleLineOne),
1938
- },
1939
- {
1940
- // Experience Title Text:
1941
- type: "Text",
1942
- textSize: 72,
1943
- position: [0, 90, 0],
1944
- size: [this.#containerWidth, 150],
1945
- anchor: mod.UIAnchor.TopCenter,
1946
- textAnchor: mod.UIAnchor.TopCenter,
1947
- bgAlpha: 0,
1948
- //bgColor: REDCOLOR,
1949
- textLabel: MakeMessage(mod.stringkeys.titleLineTwo),
1950
- }]
1951
- });
1952
- // lobby status text:
1953
- this.#lobbyStatusText = ParseUI({
1954
- type: "Text",
1955
- parent: this.#rootWidget,
1956
- textSize: 36,
1957
- position: [0, 30, 0],
1958
- size: [this.#containerWidth, 50],
1959
- anchor: mod.UIAnchor.BottomCenter,
1960
- textAnchor: mod.UIAnchor.Center,
1961
- bgAlpha: 0,
1962
- //bgColor: REDCOLOR,
1963
- textLabel: MakeMessage(mod.stringkeys.waitingforplayersX, initialPlayerCount, 12),
1964
- });
1965
- }
1966
- }
1967
-
1968
- class MessageUI {
1969
- #jsPlayer;
1970
- #rootWidget: mod.UIWidget|undefined;
1971
-
1972
- #containerWidth = 700;
1973
- #containerHeight = 100;
1974
- #lineBreakHeight = 3;
1975
- #backgroundSpacing = 4;
1976
- #activeTabBgColor = [0, 0, 0];
1977
-
1978
- #messageText: mod.UIWidget|undefined;
1979
-
1980
- #isUIVisible = false;
1981
-
1982
- constructor(jsPlayer: JsPlayer) {
1983
- this.#jsPlayer = jsPlayer;
1984
- }
1985
-
1986
- open(message: mod.Message, textColor: number[]) {
1987
- //console.log("Open message UI");
1988
- if (!this.#rootWidget)
1989
- this.#create(message, textColor);
1990
- else {
1991
- this.refresh(message);
1992
- if (this.#messageText && textColor.length >= 3)
1993
- mod.SetUITextColor(this.#messageText, mod.CreateVector(textColor[0], textColor[1], textColor[2]));
1994
- }
1995
-
1996
- if (!this.#rootWidget)
1997
- return;
1998
-
1999
- mod.SetUIWidgetVisible(this.#rootWidget, true);
2000
- this.#isUIVisible = true;
2001
- }
2002
-
2003
- close() {
2004
- if (this.#rootWidget) {
2005
- mod.SetUIWidgetVisible(this.#rootWidget, false);
2006
- this.#isUIVisible = false;
2007
- }
2008
- }
2009
-
2010
- isOpen() {
2011
- return this.#isUIVisible;
2012
- }
2013
-
2014
- refresh(message: mod.Message) {
2015
- //console.log("refresh message text");
2016
- if (!this.#messageText) {
2017
- console.log("Missing Message Text!");
2018
- return;
2019
- }
2020
- mod.SetUITextLabel(this.#messageText, message);
2021
-
2022
- }
2023
-
2024
- #create(message: mod.Message, textColor: number[]) {
2025
- // background:
2026
- this.#rootWidget = ParseUI({
2027
- type: "Container",
2028
- size: [this.#containerWidth, this.#containerHeight],
2029
- position: [0, 100],
2030
- anchor: mod.UIAnchor.BottomCenter,
2031
- bgFill: mod.UIBgFill.Blur,
2032
- bgColor: this.#activeTabBgColor,
2033
- bgAlpha: 1,
2034
- playerId: this.#jsPlayer.player,
2035
- children: [{
2036
- // Black Background
2037
- type: "Container",
2038
- position: [0, 0],
2039
- size: [this.#containerWidth - this.#backgroundSpacing, this.#containerHeight - this.#backgroundSpacing],
2040
- anchor: mod.UIAnchor.Center,
2041
- bgFill: mod.UIBgFill.Blur,
2042
- bgColor: BLACKCOLOR,
2043
- bgAlpha: 1,
2044
- },
2045
- ]});
2046
- // message
2047
- this.#messageText = ParseUI({
2048
- type: "Text",
2049
- parent: this.#rootWidget,
2050
- textSize: 36,
2051
- position: [0, 30, 0],
2052
- size: [this.#containerWidth, 50],
2053
- anchor: mod.UIAnchor.BottomCenter,
2054
- textAnchor: mod.UIAnchor.Center,
2055
- bgAlpha: 0,
2056
- textColor: textColor,
2057
- textLabel: message,
2058
- });
2059
- }
2060
- }
2061
-
2062
- //-----------------------------------------------------------------------------------------------//
2063
- class BombData {
2064
- static currentWorldIconPos: mod.Vector = mod.CreateVector(0, 0, 0);
2065
- static lastCarryingPlayerPos: mod.Vector = mod.CreateVector(0, 0, 0);
2066
- static bombPositionWorldIcon: mod.WorldIcon;// For when the bomb is dropped
2067
- static isAtA: boolean = false;
2068
- static isAtB: boolean = false;
2069
- static isPlanting: boolean = false;
2070
- static plantProgress: number = 0;
2071
-
2072
- static countDown: number = 60;
2073
-
2074
- static defusingPlayer: mod.Player | null;
2075
- static defusingProgress: number = 0;
2076
-
2077
- static isBeingCarried: boolean = false;
2078
- static isPlanted: boolean = false;
2079
- static carryingPlayer: mod.Player | null;
2080
-
2081
- static canBePickedUp: boolean = true;
2082
- static bombModel: mod.SpatialObject | null = null;
2083
-
2084
- static Initialize() {
2085
- // Init things here
2086
- this.bombPositionWorldIcon = mod.GetWorldIcon(1502);
2087
-
2088
- mod.SetWorldIconText(this.bombPositionWorldIcon, MakeMessage(mod.stringkeys.bomb));
2089
-
2090
- mod.SetWorldIconColor(this.bombPositionWorldIcon, mod.CreateVector(1, 0, 0));
2091
-
2092
- mod.EnableWorldIconImage(this.bombPositionWorldIcon, false);
2093
- mod.EnableWorldIconText(this.bombPositionWorldIcon, false);
2094
- }
2095
-
2096
- static Reset() {
2097
- mod.EnableSFX(alarmSFX_A, false);
2098
- mod.EnableSFX(alarmSFX_B, false);
2099
-
2100
- this.isPlanted = false;
2101
- this.isPlanting = false;
2102
-
2103
- this.isAtA = false;
2104
- this.isAtB = false;
2105
-
2106
- this.defusingProgress = 0;
2107
- this.plantProgress = 0;
2108
- this.defusingPlayer = null;
2109
-
2110
- if (this.isBeingCarried) {
2111
- if (this.carryingPlayer != null)
2112
- this.ItemDropped(this.carryingPlayer);
2113
- else
2114
- this.ItemDropped();
2115
- }
2116
- }
2117
-
2118
- static ItemProximityCheck(){
2119
- // this implementation will potentially mess up when multiple players enter the pickup range in quicker succession than the tick, should probably have a failsafe
2120
- if (!this.isBeingCarried && this.canBePickedUp) {
2121
- const player = mod.ClosestPlayerTo(this.currentWorldIconPos, attackingTeam);
2122
- let pos;
2123
- if (mod.IsPlayerValid(player) && !mod.GetSoldierState(player, mod.SoldierStateBool.IsAISoldier) && mod.GetSoldierState(player, mod.SoldierStateBool.IsAlive)){
2124
- pos = mod.GetSoldierState(player, mod.SoldierStateVector.GetPosition);
2125
- const playerPos = pos;
2126
- const distance = mod.DistanceBetween(this.currentWorldIconPos, playerPos);
2127
-
2128
- if (distance <= bombPickupDistance) {
2129
- this.ItemPickedUp(player);
2130
- }
2131
- }
2132
- }
2133
- }
2134
-
2135
- static ItemPickedUp(player: mod.Player) {
2136
- this.isBeingCarried = true;
2137
- this.isAtA = false;
2138
- this.isAtB = false;
2139
- this.carryingPlayer = player;
2140
- mod.AddUIIcon(this.carryingPlayer, mod.WorldIconImages.Bomb, 2.0, mod.CreateVector(0, 1, 0.1), mod.Message("Bomb"), mod.GetTeam(this.carryingPlayer));
2141
- mod.EnableWorldIconImage(this.bombPositionWorldIcon, false);
2142
- mod.EnableWorldIconText(this.bombPositionWorldIcon, false);
2143
-
2144
- console.log("Bomb model ID is ", this.bombModel);
2145
-
2146
- if (this.bombModel != null) {
2147
- mod.UnspawnObject(this.bombModel);
2148
- }
2149
-
2150
- console.log("Bomb has been picked up");
2151
-
2152
- mod.EnableInputRestriction(player, mod.RestrictedInputs.Interact, false);
2153
-
2154
- // Message all Teammates
2155
- JsPlayer.playerInstances.forEach(playerInst => {
2156
- if (mod.GetObjId(mod.GetTeam(player)) == mod.GetObjId(mod.GetTeam(playerInst))) {
2157
- let jsPlayer = JsPlayer.get(playerInst);
2158
- if (jsPlayer) {
2159
- MessagePlayer(jsPlayer, MakeMessage(mod.stringkeys.bombPickedUp), WHITECOLOR);
2160
- if (mod.GetObjId(player) == mod.GetObjId(playerInst)) {
2161
- jsPlayer.hasBombIndicator?.open();
2162
- jsPlayer.dropBombIndicator?.open();
2163
- }
2164
- }
2165
- }
2166
- });
2167
- }
2168
-
2169
- static ItemHeld() {
2170
- if (!this.isBeingCarried || this.isPlanted)
2171
- return;
2172
-
2173
- if (this.carryingPlayer && mod.IsPlayerValid(this.carryingPlayer) && mod.GetSoldierState(this.carryingPlayer, mod.SoldierStateBool.IsAlive)) {
2174
- this.lastCarryingPlayerPos = mod.GetSoldierState(this.carryingPlayer, mod.SoldierStateVector.GetPosition);
2175
- }
2176
- }
2177
-
2178
- static BombPlanted() {
2179
- if (!this.isPlanted || roundEnded || !roundStarted)
2180
- return;
2181
-
2182
- this.countDown -= 1;
2183
-
2184
- if (this.countDown <= 0) {
2185
-
2186
- if (this.isAtA) {
2187
- mod.EnableSFX(alarmSFX_A, false);
2188
- ExplodeFeedback(MCOMPositionA);
2189
- }
2190
- else {
2191
- mod.EnableSFX(alarmSFX_B, false);
2192
- ExplodeFeedback(MCOMPositionB);
2193
- }
2194
-
2195
- console.log("Explode Bomb!");
2196
- MessageAllUI(MakeMessage(mod.stringkeys.bombExploded), WHITECOLOR);
2197
- EndRound(attackingTeam);
2198
- }
2199
- }
2200
-
2201
- static ItemDropped(player?: mod.Player) {
2202
- this.isBeingCarried = false;
2203
- this.isAtA = false;
2204
- this.isAtB = false;
2205
- this.currentWorldIconPos = mod.Add(this.lastCarryingPlayerPos, mod.CreateVector(0, 1.5, 0));
2206
-
2207
- this.carryingPlayer = null;
2208
- mod.EnableWorldIconImage(this.bombPositionWorldIcon, true);
2209
- mod.EnableWorldIconText(this.bombPositionWorldIcon, true);
2210
-
2211
- if (player) {
2212
- mod.EnableInputRestriction(player, mod.RestrictedInputs.Interact, true);
2213
- let jsPlayer = JsPlayer.get(player);
2214
- if (jsPlayer) {
2215
- jsPlayer.dropBombIndicator?.close();
2216
- jsPlayer.hasBombIndicator?.close();
2217
- }
2218
-
2219
- mod.RemoveUIIcon(player);
2220
- }
2221
-
2222
- mod.SetWorldIconPosition(this.bombPositionWorldIcon, this.currentWorldIconPos);
2223
-
2224
- if (this.bombModel != null) {
2225
- mod.UnspawnObject(this.bombModel);
2226
- }
2227
-
2228
- this.bombModel = mod.SpawnObject(mod.RuntimeSpawn_Capstone.RetroBoomBox_01, mod.Add(this.lastCarryingPlayerPos, mod.CreateVector(0, 0.25, 0)), ZEROVEC);
2229
-
2230
- console.log("Bomb Dropped")
2231
- MessageAllUI(MakeMessage(mod.stringkeys.bombDropped, player), REDCOLOR);
2232
- console.log("Bomb World Icon should be at position: ", mod.XComponentOf(this.currentWorldIconPos), " ", mod.YComponentOf(this.currentWorldIconPos), " ", mod.ZComponentOf(this.currentWorldIconPos));
2233
- BombDropTimer();
2234
- }
2235
-
2236
- static PlantBomb() {
2237
- console.log("Bomb is planted")
2238
- roundTime = MCOMFuseTime;
2239
- this.plantProgress = 0;
2240
- this.isPlanting = false;
2241
-
2242
- if (this.carryingPlayer)
2243
- mod.RemoveUIIcon(this.carryingPlayer);
2244
-
2245
- if (this.carryingPlayer != null) {
2246
- mod.EnableInputRestriction(this.carryingPlayer, mod.RestrictedInputs.Interact, true);
2247
- let jsPlayer = JsPlayer.get(this.carryingPlayer);
2248
- if (jsPlayer) {
2249
- jsPlayer.dropBombIndicator?.close();
2250
- jsPlayer.hasBombIndicator?.close();
2251
- jsPlayer.progressBarUI?.close();
2252
- }
2253
- }
2254
- else
2255
- console.log("Bomb was Planted but had no carrying player. This should not be possible.");
2256
-
2257
- HideAllMessageUI();
2258
- if (BombData.isAtA) {
2259
- console.log("Bomb planted at B feedback");
2260
- MessageAllUI(MakeMessage(mod.stringkeys.aArmed), REDCOLOR);
2261
- mod.EnableInteractPoint(interactPointB, false);
2262
- mod.EnableWorldIconImage(worldIconB, false);
2263
- mod.EnableWorldIconText(worldIconB, false);
2264
- mod.EnableSFX(alarmSFX_A, true);
2265
- mod.PlaySound(alarmSFX_A, 100, MCOMPositionA, 1);
2266
- }
2267
- else if (BombData.isAtB) {
2268
- console.log("Bomb planted at A feedback");
2269
- MessageAllUI(MakeMessage(mod.stringkeys.bArmed), REDCOLOR);
2270
- mod.EnableInteractPoint(interactPointA, false);
2271
- mod.EnableWorldIconImage(worldIconA, false);
2272
- mod.EnableWorldIconText(worldIconA, false);
2273
- mod.EnableSFX(alarmSFX_B, true);
2274
- mod.PlaySound(alarmSFX_B, 100, MCOMPositionB, 1);
2275
- }
2276
- else {
2277
- console.log("Bomb is at neither A nor B when planted! This should not be possible.");
2278
- }
2279
-
2280
- this.countDown = MCOMFuseTime;
2281
- this.isBeingCarried = false;
2282
- this.isPlanted = true;
2283
- this.carryingPlayer = null;
2284
- this.canBePickedUp = false;
2285
- mod.EnableWorldIconImage(this.bombPositionWorldIcon, false);
2286
- mod.EnableWorldIconText(this.bombPositionWorldIcon, false);
2287
-
2288
- // Reward the team
2289
- JsPlayer.playerInstances.forEach(player => {
2290
- if (mod.GetObjId(mod.GetTeam(player)) == mod.GetObjId(attackingTeam)) {
2291
- let jsPlayer = JsPlayer.get(player);
2292
- if (jsPlayer) {
2293
- jsPlayer.cash += plantReward;
2294
- jsPlayer.updateWalletUI();
2295
- }
2296
- }
2297
- });
2298
- }
2299
-
2300
- static DefuseBomb() {
2301
- MessageAllUI(MakeMessage(mod.stringkeys.bombDefused), WHITECOLOR);
2302
- console.log("Bomb is defused!");
2303
-
2304
- // Reward the team
2305
- JsPlayer.playerInstances.forEach(player => {
2306
- if (mod.GetObjId(mod.GetTeam(player)) == mod.GetObjId(defendingTeam)) {
2307
- let jsPlayer = JsPlayer.get(player);
2308
- if (jsPlayer)
2309
- {
2310
- jsPlayer.cash += defuseReward;
2311
- jsPlayer.updateWalletUI();
2312
- }
2313
- }
2314
- });
2315
-
2316
- if (this.defusingPlayer) {
2317
- let jsPlayer = JsPlayer.get(this.defusingPlayer);
2318
- if (jsPlayer) {
2319
- jsPlayer.progressBarUI?.close();
2320
- }
2321
- }
2322
-
2323
- if (this.isAtA) {
2324
- mod.EnableSFX(alarmSFX_A, false);
2325
- }
2326
- else {
2327
- mod.EnableSFX(alarmSFX_B, false);
2328
- }
2329
-
2330
- this.defusingPlayer = null;
2331
- this.isPlanted = false;
2332
- this.defusingProgress = 0;
2333
-
2334
- EndRound(defendingTeam);
2335
- }
2336
-
2337
- static CancelDefuse() {
2338
- console.log("Bomb Defusing Cancelled");
2339
- if (this.defusingPlayer != null) {
2340
- let jsPlayer = JsPlayer.get(this.defusingPlayer);
2341
- if (jsPlayer) {
2342
- jsPlayer.progressBarUI?.close();
2343
- }
2344
- }
2345
-
2346
- this.defusingPlayer = null;
2347
- this.defusingProgress = 0;
2348
- }
2349
-
2350
- static CancelPlant() {
2351
- console.log("Bomb Planting Cancelled");
2352
- BombData.isAtA = false;
2353
- BombData.isAtB = false;
2354
- BombData.plantProgress = 0;
2355
- BombData.isPlanting = false;
2356
-
2357
- if (this.carryingPlayer != null) {
2358
- let jsPlayer = JsPlayer.get(this.carryingPlayer);
2359
- if (jsPlayer) {
2360
- jsPlayer.progressBarUI?.close();
2361
- }
2362
- }
2363
- }
2364
- }
2365
-
2366
- async function BombDropTimer() {
2367
- BombData.canBePickedUp = false;
2368
- await mod.Wait(3)
2369
- BombData.canBePickedUp = true;
2370
- }
2371
-
2372
-
2373
- //-----------------------------------------------------------------------------------------------//
2374
-
2375
- class StoreItemData {
2376
- id: any;
2377
- name: any; // string or mod.Message
2378
- cost = 1;
2379
- bonusDamage = 0;
2380
- bonusHealth = 0;
2381
- weapon: any;
2382
-
2383
- constructor(params: { [key: string]: any }) {
2384
- const fields: { [key: string]: any } = this;
2385
- for (const id in params)
2386
- fields[id] = params[id];
2387
- }
2388
-
2389
- canAffordIt(jsPlayer: JsPlayer, itemData: any) {
2390
- return jsPlayer.cash >= itemData.cost;
2391
- }
2392
-
2393
- // return null if unlocked, or a String or mod.Message with the locked reason
2394
- getDisabledMessageCallback(jsPlayer: JsPlayer, itemData: any) {
2395
- if (itemData.inventoryPerRound > 0) {
2396
- let buysThisRound = jsPlayer.itemBuysPerRound[itemData.id];
2397
- if (buysThisRound >= itemData.inventoryPerRound)
2398
- return mod.stringkeys.outOfInventory;
2399
- }
2400
- return null;
2401
- }
2402
-
2403
- onBuyCallback(jsPlayer: JsPlayer, itemData: any) {
2404
- jsPlayer.cash -= itemData.cost;
2405
- jsPlayer.updateWalletUI();
2406
- //console.log("Make Player " + mod.GetObjId(jsPlayer.player) + " buy: " + itemData.id);
2407
- }
2408
- }
2409
-
2410
- class StoreItemDataWeapon extends StoreItemData {
2411
-
2412
- onBuyCallback(jsPlayer: JsPlayer, itemData: any) {
2413
- jsPlayer.cash -= itemData.cost;
2414
- jsPlayer.updateWalletUI();
2415
-
2416
- ////////// Can't do any of this for launch because of the Loot Spawner //////////
2417
-
2418
- // if (itemData.weapon in mod.Weapons && mod.IsInventorySlotActive(jsPlayer.player, mod.InventorySlots.PrimaryWeapon)) {
2419
- // for (let i = 0; i < Object.keys(mod.PrimaryWeapons).length; ++i) {
2420
- // if (mod.HasInventory(jsPlayer.player, i)) {
2421
- // let lootSpawner: mod.LootSpawner = mod.SpawnObject(mod.RuntimeSpawn_Common.LootSpawner, mod.GetSoldierState(jsPlayer.player, mod.SoldierStateVector.GetPosition), ZEROVEC, ONEVEC);
2422
- // mod.SpawnLoot(lootSpawner, i);
2423
- // mod.UnspawnObject(lootSpawner);
2424
- // break;
2425
- // }
2426
- // }
2427
- // }
2428
- // else if (itemData.weapon in mod.SecondaryWeapons && mod.IsInventorySlotActive(jsPlayer.player, mod.InventorySlots.SecondaryWeapon)) {
2429
- // for (let i = 0; i < Object.keys(mod.SecondaryWeapons).length; ++i) {
2430
- // if (mod.HasInventory(jsPlayer.player, i)) {
2431
- // let lootSpawner: mod.LootSpawner = mod.SpawnObject(mod.RuntimeSpawn_Common.LootSpawner, mod.GetSoldierState(jsPlayer.player, mod.SoldierStateVector.GetPosition), ZEROVEC, ONEVEC);
2432
- // mod.SpawnLoot(lootSpawner, i);
2433
- // mod.UnspawnObject(lootSpawner);
2434
- // break;
2435
- // }
2436
- // }
2437
- // }
2438
-
2439
- if (itemData.weaponPackage != null){
2440
- console.log("removing and adding new equipment");
2441
- //mod.RemoveEquipment(jsPlayer.player, mod.InventorySlots.PrimaryWeapon)
2442
-
2443
- mod.AddEquipment(jsPlayer.player, itemData.weapon, itemData.weaponPackage);
2444
- }
2445
- else {
2446
- mod.AddEquipment(jsPlayer.player, itemData.weapon);
2447
- }
2448
-
2449
- }
2450
- }
2451
-
2452
- class StoreItemDataGadget extends StoreItemData {
2453
-
2454
- onBuyCallback(jsPlayer: JsPlayer, itemData: any) {
2455
- jsPlayer.cash -= itemData.cost;
2456
- jsPlayer.updateWalletUI();
2457
-
2458
- // if (mod.IsInventorySlotActive(jsPlayer.player, mod.InventorySlots.GadgetOne)) {
2459
- // if (mod.IsInventorySlotActive(jsPlayer.player, mod.InventorySlots.GadgetTwo)) {
2460
- // ////////// Can't do any of this for launch because of the Loot Spawner //////////
2461
- // // No open gadget slots, drop gadget 2
2462
- // // for (let i = 0; i < Object.keys(mod.Gadgets).length; ++i) {
2463
- // // if (mod.HasInventory(jsPlayer.player, i)) {
2464
- // // let lootSpawner: mod.LootSpawner = mod.SpawnObject(mod.RuntimeSpawn_Common.LootSpawner, mod.GetSoldierState(jsPlayer.player, mod.SoldierStateVector.GetPosition), ZEROVEC, ONEVEC);
2465
- // // mod.SpawnLoot(lootSpawner, i);
2466
- // // mod.UnspawnObject(lootSpawner);
2467
- // // break;
2468
- // // }
2469
- // // }
2470
- // mod.AddEquipment(jsPlayer.player, itemData.weapon, mod.InventorySlots.GadgetTwo);
2471
- // }
2472
- // else {
2473
- // // Gadget slot 2 is clear
2474
- // mod.AddEquipment(jsPlayer.player, itemData.weapon, mod.InventorySlots.GadgetTwo);
2475
- // }
2476
- // }
2477
- // else {
2478
- // // Gadget slots are clear
2479
- // mod.AddEquipment(jsPlayer.player, itemData.weapon, mod.InventorySlots.GadgetOne);
2480
-
2481
- // }
2482
- mod.AddEquipment(jsPlayer.player, itemData.weapon);
2483
-
2484
-
2485
- }
2486
- }
2487
-
2488
- //// - Assault Rifle Weapon Packages - ////
2489
-
2490
- let assaultRiflePackage_Basic = mod.CreateNewWeaponPackage()
2491
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_30rnd_Magazine, assaultRiflePackage_Basic)
2492
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_Iron_Sights, assaultRiflePackage_Basic)
2493
-
2494
-
2495
- let assaultRiflePackage_Standard = mod.CreateNewWeaponPackage()
2496
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_30rnd_Magazine, assaultRiflePackage_Standard)
2497
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_1p87_150x, assaultRiflePackage_Standard)
2498
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Classic_Grip_Pod, assaultRiflePackage_Standard)
2499
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_Compensated_Brake, assaultRiflePackage_Standard)
2500
-
2501
-
2502
- let assaultRiflePackage_Elite = mod.CreateNewWeaponPackage()
2503
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_30rnd_Fast_Mag, assaultRiflePackage_Elite)
2504
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_R4T_200x, assaultRiflePackage_Elite)
2505
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Full_Angled, assaultRiflePackage_Elite)
2506
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_Tungsten_Core, assaultRiflePackage_Elite)
2507
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_Standard_Suppressor, assaultRiflePackage_Elite)
2508
-
2509
-
2510
- let assaultRiflePackage_Basic_B36A4 = mod.CreateNewWeaponPackage()
2511
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_30rnd_Magazine, assaultRiflePackage_Basic_B36A4)
2512
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_Iron_Sights, assaultRiflePackage_Basic_B36A4)
2513
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_480mm_Factory, assaultRiflePackage_Basic_B36A4)
2514
-
2515
- let assaultRiflePackage_Standard_B36A4 = mod.CreateNewWeaponPackage()
2516
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_30rnd_Magazine, assaultRiflePackage_Standard_B36A4)
2517
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_1p87_150x, assaultRiflePackage_Standard_B36A4)
2518
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Classic_Grip_Pod, assaultRiflePackage_Standard_B36A4)
2519
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_Compensated_Brake, assaultRiflePackage_Standard_B36A4)
2520
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_480mm_Factory, assaultRiflePackage_Standard_B36A4)
2521
-
2522
- let assaultRiflePackage_Elite_B36A4 = mod.CreateNewWeaponPackage()
2523
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_30rnd_Fast_Mag, assaultRiflePackage_Elite_B36A4)
2524
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_R4T_200x, assaultRiflePackage_Elite_B36A4)
2525
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Full_Angled, assaultRiflePackage_Elite_B36A4)
2526
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_Tungsten_Core, assaultRiflePackage_Elite_B36A4)
2527
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_Standard_Suppressor, assaultRiflePackage_Elite_B36A4)
2528
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_480mm_Factory, assaultRiflePackage_Elite_B36A4)
2529
-
2530
- //// - Carbine Weapon Packages - ////
2531
-
2532
- let carbinePackage_Basic = mod.CreateNewWeaponPackage()
2533
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_20rnd_Magazine, carbinePackage_Basic)
2534
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_Iron_Sights, carbinePackage_Basic)
2535
-
2536
-
2537
- let carbinePackage_Standard = mod.CreateNewWeaponPackage()
2538
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_20rnd_Magazine, carbinePackage_Standard)
2539
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_CCO_200x, carbinePackage_Standard)
2540
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Classic_Vertical, carbinePackage_Standard)
2541
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_Compensated_Brake, carbinePackage_Standard)
2542
-
2543
-
2544
- let carbinePackage_Elite = mod.CreateNewWeaponPackage()
2545
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_20rnd_Fast_Mag, carbinePackage_Elite)
2546
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_ST_Prisim_500x, carbinePackage_Elite)
2547
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Ribbed_Vertical, carbinePackage_Elite)
2548
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_Tungsten_Core, carbinePackage_Elite)
2549
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_Standard_Suppressor, carbinePackage_Elite)
2550
-
2551
- let carbinePackage_Basic_M4A1 = mod.CreateNewWeaponPackage()
2552
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_30rnd_Magazine, carbinePackage_Basic_M4A1)
2553
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_Iron_Sights, carbinePackage_Basic_M4A1)
2554
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_145_Carbine, carbinePackage_Basic_M4A1)
2555
-
2556
- let carbinePackage_Standard_M4A1 = mod.CreateNewWeaponPackage()
2557
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_30rnd_Fast_Mag, carbinePackage_Standard_M4A1)
2558
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_1p87_150x, carbinePackage_Standard_M4A1)
2559
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Classic_Grip_Pod, carbinePackage_Standard_M4A1)
2560
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_Compensated_Brake, carbinePackage_Standard_M4A1)
2561
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_145_Carbine, carbinePackage_Standard_M4A1)
2562
-
2563
- let carbinePackage_Elite_M4A1 = mod.CreateNewWeaponPackage()
2564
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_40rnd_Fast_Mag, carbinePackage_Elite_M4A1)
2565
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_R4T_200x, carbinePackage_Elite_M4A1)
2566
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Ribbed_Vertical, carbinePackage_Elite_M4A1)
2567
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_Tungsten_Core, carbinePackage_Elite_M4A1)
2568
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_Lightened_Suppressor, carbinePackage_Elite_M4A1)
2569
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_115_Commando, carbinePackage_Elite_M4A1)
2570
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ergonomic_Improved_Mag_Catch, carbinePackage_Elite_M4A1)
2571
-
2572
-
2573
- //// - PDW Weapon Packages - ////
2574
-
2575
- let PDWPackage_Basic_SMG_PW7A2 = mod.CreateNewWeaponPackage()
2576
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_20rnd_Magazine, PDWPackage_Basic_SMG_PW7A2)
2577
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_Iron_Sights, PDWPackage_Basic_SMG_PW7A2)
2578
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_180mm_Standard, PDWPackage_Basic_SMG_PW7A2)
2579
-
2580
- let PDWPackage_Standard_SMG_PW7A2 = mod.CreateNewWeaponPackage()
2581
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_30rnd_Magazine, PDWPackage_Standard_SMG_PW7A2)
2582
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_Mini_Flex_100x, PDWPackage_Standard_SMG_PW7A2)
2583
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Compact_Handstop, PDWPackage_Standard_SMG_PW7A2)
2584
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_180mm_Standard, PDWPackage_Standard_SMG_PW7A2)
2585
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Right_5_mW_Red, PDWPackage_Standard_SMG_PW7A2)
2586
-
2587
- let PDWPackage_Elite_SMG_PW7A2 = mod.CreateNewWeaponPackage()
2588
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_40rnd_Magazine, PDWPackage_Elite_SMG_PW7A2)
2589
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_SU_123_150x, PDWPackage_Elite_SMG_PW7A2)
2590
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Folding_Vertical, PDWPackage_Elite_SMG_PW7A2)
2591
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_FMJ, PDWPackage_Elite_SMG_PW7A2)
2592
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_CQB_Suppressor, PDWPackage_Elite_SMG_PW7A2)
2593
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_180mm_Prototype, PDWPackage_Elite_SMG_PW7A2)
2594
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Right_5_mW_Red, PDWPackage_Elite_SMG_PW7A2)
2595
-
2596
-
2597
- //// - DMR Weapon Packages - ////
2598
-
2599
- let DMRPackage_Basic_SVDM = mod.CreateNewWeaponPackage()
2600
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_10rnd_Magazine, DMRPackage_Basic_SVDM)
2601
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_Baker_300x, DMRPackage_Basic_SVDM)
2602
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_550mm_Factory, DMRPackage_Basic_SVDM)
2603
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_Flash_Hider, DMRPackage_Basic_SVDM)
2604
-
2605
- let DMRPackage_Standard_SVDM = mod.CreateNewWeaponPackage()
2606
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_10rnd_Fast_Mag, DMRPackage_Standard_SVDM)
2607
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_LDS_450x, DMRPackage_Standard_SVDM)
2608
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_6H64_Vertical, DMRPackage_Standard_SVDM)
2609
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_550mm_Factory, DMRPackage_Standard_SVDM)
2610
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_Flash_Hider, DMRPackage_Standard_SVDM)
2611
-
2612
-
2613
- let DMRPackage_Elite_SVDM = mod.CreateNewWeaponPackage()
2614
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_20rnd_Magazine, DMRPackage_Elite_SVDM)
2615
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_PAS_35_300x, DMRPackage_Elite_SVDM)
2616
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Bipod, DMRPackage_Elite_SVDM)
2617
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_FMJ, DMRPackage_Elite_SVDM)
2618
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_Long_Suppressor, DMRPackage_Elite_SVDM)
2619
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_620mm_Classic, DMRPackage_Elite_SVDM)
2620
-
2621
- //// - Sniper Weapon Packages - ////
2622
-
2623
- let SniperPackage_Basic_M2010ESR = mod.CreateNewWeaponPackage()
2624
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_5rnd_Magazine, SniperPackage_Basic_M2010ESR)
2625
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_LDS_450x, SniperPackage_Basic_M2010ESR)
2626
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Classic_Grip_Pod, SniperPackage_Basic_M2010ESR)
2627
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_24_Full, SniperPackage_Basic_M2010ESR)
2628
-
2629
- let SniperPackage_Standard_SV_98 = mod.CreateNewWeaponPackage();
2630
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_FMJ, SniperPackage_Standard_SV_98);
2631
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_LDS_450x, SniperPackage_Standard_SV_98);
2632
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_650mm_Factory, SniperPackage_Standard_SV_98);
2633
-
2634
- let SniperPackage_Standard_M2010ESR = mod.CreateNewWeaponPackage()
2635
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_5rnd_Fast_Mag, SniperPackage_Standard_M2010ESR)
2636
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_SSDS_600x, SniperPackage_Standard_M2010ESR)
2637
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Bipod, SniperPackage_Standard_M2010ESR)
2638
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_24_Full, SniperPackage_Standard_M2010ESR)
2639
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_Flash_Hider, SniperPackage_Standard_M2010ESR)
2640
-
2641
- let SniperPackage_Elite_M2010ESR = mod.CreateNewWeaponPackage()
2642
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_8rnd_Magazine, SniperPackage_Elite_M2010ESR)
2643
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_NFX_800x, SniperPackage_Elite_M2010ESR)
2644
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Bipod, SniperPackage_Elite_M2010ESR)
2645
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_Match_Grade, SniperPackage_Elite_M2010ESR)
2646
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_Long_Suppressor, SniperPackage_Elite_M2010ESR)
2647
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_26_Carbon, SniperPackage_Elite_M2010ESR)
2648
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Left_Range_Finder, SniperPackage_Elite_M2010ESR)
2649
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ergonomic_DLC_Bolt, SniperPackage_Elite_M2010ESR)
2650
-
2651
-
2652
- //// - LMG Weapon Packages - ////
2653
-
2654
- let LMGPackage_Basic = mod.CreateNewWeaponPackage();
2655
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_Iron_Sights, LMGPackage_Basic)
2656
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Classic_Grip_Pod, LMGPackage_Basic)
2657
-
2658
- let LMGPackage_Basic_M240L = mod.CreateNewWeaponPackage()
2659
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_50rnd_Loose_Belt, LMGPackage_Basic_M240L)
2660
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_Iron_Sights, LMGPackage_Basic_M240L)
2661
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Classic_Grip_Pod, LMGPackage_Basic_M240L)
2662
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_20_Lima, LMGPackage_Basic_M240L)
2663
-
2664
- let LMGPackage_Standard_M240L = mod.CreateNewWeaponPackage()
2665
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_75rnd_Belt_Box, LMGPackage_Standard_M240L)
2666
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_BF_2M_250x, LMGPackage_Standard_M240L)
2667
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Ribbed_Vertical, LMGPackage_Standard_M240L)
2668
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_20_Lima, LMGPackage_Standard_M240L)
2669
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_Flash_Hider, LMGPackage_Standard_M240L)
2670
-
2671
- let LMGPackage_Elite_M240L = mod.CreateNewWeaponPackage()
2672
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_100rnd_Belt_Box, LMGPackage_Elite_M240L)
2673
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_LDS_450x, LMGPackage_Elite_M240L)
2674
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Bipod, LMGPackage_Elite_M240L)
2675
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_Tungsten_Core, LMGPackage_Elite_M240L)
2676
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_Linear_Comp, LMGPackage_Elite_M240L)
2677
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_24_Bravo, LMGPackage_Elite_M240L)
2678
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Right_120_mW_Blue, LMGPackage_Elite_M240L)
2679
-
2680
- //// - Shotgun Weapon Packages - ////
2681
-
2682
- let ShotgunPackage_Basic = mod.CreateNewWeaponPackage();
2683
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_Iron_Sights, ShotgunPackage_Basic);
2684
-
2685
- let ShotgunPackage_Basic_185KS_K = mod.CreateNewWeaponPackage()
2686
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_4rnd_Magazine, ShotgunPackage_Basic_185KS_K)
2687
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_Iron_Sights, ShotgunPackage_Basic_185KS_K)
2688
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_430mm_Factory, ShotgunPackage_Basic_185KS_K)
2689
-
2690
- let ShotgunPackage_Standard_185KS_K = mod.CreateNewWeaponPackage()
2691
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_4rnd_Fast_Mag, ShotgunPackage_Standard_185KS_K)
2692
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_Mini_Flex_100x, ShotgunPackage_Standard_185KS_K)
2693
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_Flechette, ShotgunPackage_Standard_185KS_K)
2694
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Folding_Stubby, ShotgunPackage_Standard_185KS_K)
2695
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_430mm_Factory, ShotgunPackage_Standard_185KS_K)
2696
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Right_5_mW_Red, ShotgunPackage_Standard_185KS_K)
2697
-
2698
- let ShotgunPackage_Elite_185KS_K = mod.CreateNewWeaponPackage()
2699
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_8rnd_Fast_Mag, ShotgunPackage_Elite_185KS_K)
2700
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_SU_123_150x, ShotgunPackage_Elite_185KS_K)
2701
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Bottom_Ribbed_Vertical, ShotgunPackage_Elite_185KS_K)
2702
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_Slugs, ShotgunPackage_Elite_185KS_K)
2703
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Muzzle_CQB_Suppressor, ShotgunPackage_Elite_185KS_K)
2704
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_430mm_Cut, ShotgunPackage_Elite_185KS_K)
2705
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Right_120_mW_Blue, ShotgunPackage_Elite_185KS_K)
2706
-
2707
- //// - Pistol Weapon Packages - ////
2708
-
2709
- let SidearmPackage_Standard_ES_57 = mod.CreateNewWeaponPackage();
2710
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_FMJ, SidearmPackage_Standard_ES_57);
2711
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_122mm_Factory, SidearmPackage_Standard_ES_57);
2712
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_20rnd_Magazine, SidearmPackage_Standard_ES_57);
2713
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_Iron_Sights, SidearmPackage_Standard_ES_57);
2714
-
2715
- let SidearmPackage_Standard_M44 = mod.CreateNewWeaponPackage();
2716
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_FMJ, SidearmPackage_Standard_M44);
2717
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_Iron_Sights, SidearmPackage_Standard_M44);
2718
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_675_Factory, SidearmPackage_Standard_M44);
2719
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_6rnd_Speedloader, SidearmPackage_Standard_M44);
2720
-
2721
- let SidearmPackage_Standard_M45A1 = mod.CreateNewWeaponPackage();
2722
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_FMJ, SidearmPackage_Standard_M45A1);
2723
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Scope_Iron_Sights, SidearmPackage_Standard_M45A1);
2724
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_5_Factory, SidearmPackage_Standard_M45A1);
2725
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_11rnd_Magazine, SidearmPackage_Standard_M45A1);
2726
-
2727
- let SidearmPackage_Standard_P18 = mod.CreateNewWeaponPackage();
2728
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_FMJ, SidearmPackage_Standard_P18);
2729
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Ammo_FMJ, SidearmPackage_Standard_P18);
2730
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Magazine_17rnd_Magazine, SidearmPackage_Standard_P18);
2731
- mod.AddAttachmentToWeaponPackage(mod.WeaponAttachments.Barrel_39_Factory, SidearmPackage_Standard_P18);
2732
-
2733
- //-----------------------------------------------------------------------------------------------//
2734
-
2735
- const cStoreData = [
2736
- {
2737
- tabName: mod.stringkeys.store.riflestab,
2738
- tabRandomized: false,
2739
- itemDatas: [
2740
- new StoreItemDataWeapon({
2741
- id: "gun_M4A1",
2742
- name: mod.stringkeys.store.rifle1_1,
2743
- cost: 2400,
2744
- weapon: mod.Weapons.Carbine_M4A1,
2745
- weaponPackage: carbinePackage_Basic_M4A1
2746
- }),
2747
- new StoreItemDataWeapon({
2748
- id: "gun_AK4D",
2749
- name: mod.stringkeys.store.rifle1_2,
2750
- cost: 2400,
2751
- weapon: mod.Weapons.Carbine_AK_205,
2752
- weaponPackage: carbinePackage_Basic
2753
- }),
2754
- new StoreItemDataWeapon({
2755
- id: "gun_KORD_6P67",
2756
- name: mod.stringkeys.store.rifle3,
2757
- cost: 2000,
2758
- weapon: mod.Weapons.AssaultRifle_KORD_6P67,
2759
- weaponPackage: assaultRiflePackage_Basic
2760
- }),
2761
- new StoreItemDataWeapon({
2762
- id: "gun_TR-7",
2763
- name: mod.stringkeys.store.rifle4,
2764
- cost: 3000,
2765
- weapon: mod.Weapons.AssaultRifle_TR_7,
2766
- weaponPackage: assaultRiflePackage_Basic
2767
- }),
2768
- new StoreItemDataWeapon({
2769
- id: "gun_M2010",
2770
- name: mod.stringkeys.store.rifle5,
2771
- cost: 3500,
2772
- weapon: mod.Weapons.Sniper_M2010_ESR,
2773
- weaponPackage: SniperPackage_Elite_M2010ESR
2774
- }),
2775
- new StoreItemDataWeapon({
2776
- id: "gun_SV98",
2777
- name: mod.stringkeys.store.rifle6,
2778
- cost: 4000,
2779
- weapon: mod.Weapons.Sniper_SV_98,
2780
- weaponPackage: SniperPackage_Standard_SV_98
2781
- })
2782
- ]
2783
- }, {
2784
- tabName: mod.stringkeys.store.pistolstab,
2785
- tabRandomized: false,
2786
- itemDatas: [
2787
- new StoreItemDataWeapon({
2788
- id: "gun_P18",
2789
- name: mod.stringkeys.store.pistol1_1,
2790
- cost: 200,
2791
- weapon: mod.Weapons.Sidearm_P18,
2792
- weaponPackage: SidearmPackage_Standard_P18
2793
- }),
2794
- new StoreItemDataWeapon({
2795
- id: "gun_m45a1",
2796
- name: mod.stringkeys.store.pistol2,
2797
- cost: 300,
2798
- weapon: mod.Weapons.Sidearm_M45A1,
2799
- weaponPackage: SidearmPackage_Standard_M45A1
2800
- }),
2801
- new StoreItemDataWeapon({
2802
- id: "gun_es5.7",
2803
- name: mod.stringkeys.store.pistol3,
2804
- cost: 500,
2805
- weapon: mod.Weapons.Sidearm_ES_57,
2806
- weaponPackage: SidearmPackage_Standard_ES_57
2807
- }),
2808
- new StoreItemDataWeapon({
2809
- id: "gun_m44",
2810
- name: mod.stringkeys.store.pistol4,
2811
- cost: 800,
2812
- weapon: mod.Weapons.Sidearm_M44,
2813
- weaponPackage: SidearmPackage_Standard_M44
2814
- })
2815
- ]
2816
- }, {
2817
- tabName: mod.stringkeys.store.shotgunstab,
2818
- tabRandomized: false,
2819
- itemDatas: [
2820
- new StoreItemDataWeapon({
2821
- id: "gun_m7a1",
2822
- name: mod.stringkeys.store.shotgun1,
2823
- cost: 1100,
2824
- weapon: mod.Weapons.Shotgun_M87A1,
2825
- weaponPackage: ShotgunPackage_Basic
2826
- }),
2827
- new StoreItemDataWeapon({
2828
- id: "gun_m1014",
2829
- name: mod.stringkeys.store.shotgun3,
2830
- cost: 1800,
2831
- weapon: mod.Weapons.Shotgun_M1014,
2832
- weaponPackage: ShotgunPackage_Basic
2833
- })
2834
- ]
2835
- }, {
2836
- tabName: mod.stringkeys.store.grenadestab,
2837
- tabRandomized: false,
2838
- itemDatas: [
2839
- new StoreItemDataGadget({
2840
- id: "grenade_exlosive",
2841
- name: mod.stringkeys.store.grenade1,
2842
- cost: 1000,
2843
- weapon: mod.Gadgets.Throwable_Mini_Frag_Grenade
2844
- }),
2845
- new StoreItemDataGadget({
2846
- id: "grenade_incendiary",
2847
- name: mod.stringkeys.store.grenade2,
2848
- cost: 500,
2849
- weapon: mod.Gadgets.Throwable_Incendiary_Grenade
2850
- }),
2851
- new StoreItemDataGadget({
2852
- id: "grenade_smoke",
2853
- name: mod.stringkeys.store.grenade3,
2854
- cost: 200,
2855
- weapon: mod.Gadgets.Throwable_Smoke_Grenade
2856
- }),
2857
- new StoreItemDataGadget({
2858
- id: "grenade_flash",
2859
- name: mod.stringkeys.store.grenade4,
2860
- cost: 150,
2861
- weapon: mod.Gadgets.Throwable_Flash_Grenade
2862
- }),
2863
- ]
2864
- }, {
2865
- tabName: mod.stringkeys.store.specialstab,
2866
- tabRandomized: false,
2867
- itemDatas: [
2868
- new StoreItemDataWeapon({
2869
- id: "gun_l110",
2870
- name: mod.stringkeys.store.special1,
2871
- cost: 3000,
2872
- weapon: mod.Weapons.LMG_L110,
2873
- weaponPackage: LMGPackage_Basic
2874
- }),
2875
- new StoreItemDataWeapon({
2876
- id: "gun_kts100_mk8",
2877
- name: mod.stringkeys.store.special2,
2878
- cost: 3600,
2879
- weapon: mod.Weapons.LMG_KTS100_MK8,
2880
- weaponPackage: LMGPackage_Basic
2881
- }),
2882
- new StoreItemDataGadget({
2883
- id: "special_rpg7",
2884
- name: mod.stringkeys.store.special4,
2885
- cost: 2000,
2886
- weapon: mod.Gadgets.Launcher_Unguided_Rocket
2887
- }),
2888
- new StoreItemDataGadget({
2889
- id: "special_defibrillator",
2890
- name: mod.stringkeys.store.special5,
2891
- cost: 1000,
2892
- weapon: mod.Gadgets.Misc_Defibrillator
2893
- }),
2894
- ]
2895
- }
2896
- ];
2897
-
2898
- function getTabIndexForItemData(itemData: any) {
2899
- for (let i = 0; i < cStoreData.length; i++) {
2900
- for (let j = 0; j < cStoreData[i].itemDatas.length; j++) {
2901
- if (cStoreData[i].itemDatas[j] == itemData)
2902
- return i;
2903
- }
2904
- }
2905
- return -1;
2906
- }
2907
-
2908
-
2909
-
2910
-
2911
- //-----------------------------------------------------------------------------------------------//
2912
-
2913
- class Store {
2914
- #jsPlayer: JsPlayer;
2915
- #storeData: Dict;
2916
- #rootWidget: mod.UIWidget|undefined;
2917
-
2918
-
2919
- #storeWidth = 1200;
2920
- #storeHeight = 600;
2921
- #headerHeight = 60;
2922
- #tabHeight = 50;
2923
- #tabSpacing = 10;
2924
- #tabNamePrefix = "__tab";
2925
- #currentTabIndex = 0;
2926
- #activeTabBgColor = [0.44, 0.42, 0.4];
2927
- #inactiveTabBgColor = [0.34, 0.32, 0.3];
2928
- #itemSize = 250;
2929
- #itemSizeH = 250;
2930
- #itemSizeV = 166;
2931
- #itemSpacingHorizontal = 20;
2932
- #itemSpacingVertical = 20;
2933
- #closeButtonName = "__close";
2934
-
2935
- #tabWidgets: Widget[] = []; // UIWidgets, in order by cStoreData[]
2936
- #itemButtons: { [key: string] : any } = {}; // ItemButton objects, keyed by itemDatas.id
2937
-
2938
- #isStoreVisible = false;
2939
-
2940
- constructor(jsPlayer: JsPlayer, storeData: any) {
2941
- this.#jsPlayer = jsPlayer;
2942
- this.#storeData = storeData;
2943
- }
2944
-
2945
- open() {
2946
- if (!this.#rootWidget) {
2947
- console.log("Open shop UI for ", this.#jsPlayer.player, " with ID: ", this.#jsPlayer.playerId);
2948
- this.#create();
2949
- }
2950
- if (!this.#rootWidget)
2951
- return;
2952
- this.refresh();
2953
- mod.EnableUIInputMode(true, this.#jsPlayer.player);
2954
- mod.SetUIWidgetVisible(this.#rootWidget, true);
2955
- this.#isStoreVisible = true;
2956
- this.#jsPlayer.updateWalletUI();
2957
- }
2958
-
2959
- close() {
2960
- mod.EnableUIInputMode(false, this.#jsPlayer.player);
2961
- if (this.#rootWidget) {
2962
- mod.SetUIWidgetVisible(this.#rootWidget, false);
2963
- this.#isStoreVisible = false;
2964
-
2965
- } else {
2966
- console.log("Store not yet opened for this player.")
2967
- }
2968
- }
2969
-
2970
- isOpen() {
2971
- return this.#isStoreVisible;
2972
- }
2973
-
2974
- onUIButtonEvent(widget: Widget, event: any) {
2975
-
2976
- let widgetName = mod.GetUIWidgetName(widget);
2977
- //console.log("Clicked on ", widgetName);
2978
- // click on a tab?
2979
- if (widgetName.slice(0, this.#tabNamePrefix.length) == this.#tabNamePrefix) {
2980
- //mod.TriggerAudio( mod.SoundEvents2D.ShowObjective, this.#jsPlayer.player);
2981
- let tabIndex = parseInt(widgetName.slice(this.#tabNamePrefix.length));
2982
- this.selectTab(tabIndex);
2983
- }
2984
- // close button?
2985
- if (widgetName == this.#closeButtonName) {
2986
- //mod.TriggerAudio( mod.SoundEvents2D.ObjectiveCappingStop, this.#jsPlayer.player);
2987
- this.close();
2988
- //tell everyone you closed your store.
2989
- }
2990
- // click on a store item:
2991
- if (this.#itemButtons.hasOwnProperty(widgetName)) {
2992
- //mod.TriggerAudio( mod.SoundEvents2D.ObjectiveCappingComplete, this.#jsPlayer.player);
2993
- // call the buy callback:
2994
- let itemData = this.#itemButtons[widgetName].itemData;
2995
- itemData.onBuyCallback?.(this.#jsPlayer, itemData);
2996
- this.#jsPlayer.itemBuysPerRound[itemData.id] = (this.#jsPlayer.itemBuysPerRound[itemData.id] || 0) + 1;
2997
- this.refresh();
2998
- this.#jsPlayer.player
2999
- mod.SetScoreboardPlayerValues(this.#jsPlayer.player, this.#jsPlayer.kills, this.#jsPlayer.deaths, this.#jsPlayer.totalCashEarned, this.#jsPlayer.totalCashEarned - this.#jsPlayer.cash + initialCash, 0)
3000
- }
3001
-
3002
-
3003
- }
3004
-
3005
- selectTab(tabIndex: number) {
3006
-
3007
-
3008
- if (tabIndex < 0 || tabIndex >= this.#tabWidgets.length || tabIndex == this.#currentTabIndex) {
3009
- console.log("TabIndex is invalid ", tabIndex, " There are ", this.#tabWidgets, " tabs");
3010
- return;
3011
- }
3012
-
3013
- // turn off the old one:
3014
- mod.SetUIWidgetVisible(this.#tabWidgets[this.#currentTabIndex], false);
3015
- // turn on the new one:
3016
- this.#currentTabIndex = tabIndex;
3017
- mod.SetUIWidgetVisible(this.#tabWidgets[this.#currentTabIndex], true);
3018
-
3019
-
3020
- }
3021
-
3022
- refresh() {
3023
- if (this.#rootWidget) {
3024
- // refresh all store items:
3025
- for (const id in this.#itemButtons) {
3026
- this.#itemButtons[id].refresh();
3027
- }
3028
- } else {
3029
- console.log("Store not yet opened for this player.")
3030
- }
3031
- }
3032
-
3033
- #create() {
3034
- // background:
3035
- this.#rootWidget = ParseUI({
3036
- type: "Container",
3037
- size: [this.#storeWidth, this.#storeHeight],
3038
- position: [0, 40],
3039
- anchor: mod.UIAnchor.Center,
3040
- bgFill: mod.UIBgFill.Solid,
3041
- bgColor: this.#activeTabBgColor,
3042
- bgAlpha: 1,
3043
- playerId: this.#jsPlayer.player,
3044
- children: [{
3045
- type: "Container",
3046
- position: [0, -this.#headerHeight],
3047
- size: [this.#storeWidth, this.#headerHeight],
3048
- anchor: mod.UIAnchor.TopLeft,
3049
- bgFill: mod.UIBgFill.Solid,
3050
- bgColor: [0.1, 0.1, 0.1],
3051
- bgAlpha: 1
3052
- }, {
3053
- // close button:
3054
- type: "Button",
3055
- name: this.#closeButtonName,
3056
- size: [this.#headerHeight - 16, this.#headerHeight - 16],
3057
- position: [8, 8 - this.#headerHeight],
3058
- anchor: mod.UIAnchor.TopRight,
3059
- bgFill: mod.UIBgFill.Solid,
3060
- bgColor: [1, 0.3, 0.3],
3061
- bgAlpha: 1
3062
- }, {
3063
- // close button X:
3064
- type: "Text",
3065
- parent: this.#closeButtonName,
3066
- size: [this.#headerHeight - 16, this.#headerHeight - 16],
3067
- position: [8, 8 - this.#headerHeight],
3068
- anchor: mod.UIAnchor.TopRight,
3069
- bgFill: mod.UIBgFill.None,
3070
- textAnchor: mod.UIAnchor.Center,
3071
- textLabel: MakeMessage(mod.stringkeys.store.closeStore),
3072
- textSize: 50
3073
- }]
3074
- });
3075
-
3076
- // tabs:
3077
- this.#createTabs();
3078
- }
3079
-
3080
- #createTabs() {
3081
- // how many tabs are there?
3082
- let tabDatas = this.#storeData;
3083
- let tabCnt = tabDatas.length;
3084
- // tab size, clamped if there's only a few tabs:
3085
- let widthForTabs = this.#storeWidth - this.#tabSpacing * 2 - this.#headerHeight;
3086
- let tabWidth = Math.min(250, widthForTabs / (tabCnt + 1));
3087
- for (let a = 0; a < tabCnt; a++)
3088
- this.#createTab(a, tabWidth, tabDatas[a]);
3089
- }
3090
-
3091
- #createTab(tabIndex: number, tabWidth: number, tabData: any) {
3092
- //console.log("Create Tab ", tabIndex);
3093
- let headerPosition = [this.#tabSpacing + tabIndex * tabWidth, -this.#tabHeight];
3094
- let headerSize = [tabWidth - 10, this.#tabHeight];
3095
- // tab header bg. not part of the tab / always shown:
3096
- ParseUI({
3097
- type: "Button",
3098
- name: this.#tabNamePrefix + tabIndex,
3099
- parent: this.#rootWidget,
3100
- position: headerPosition,
3101
- size: headerSize,
3102
- anchor: mod.UIAnchor.TopLeft,
3103
- bgFill: mod.UIBgFill.OutlineThick,
3104
- bgColor: this.#inactiveTabBgColor,
3105
- //bgColor: [1,0,0],
3106
- bgAlpha: 1
3107
- });
3108
-
3109
- // tab container. this is the part that turns on and off:
3110
- let tabWidget = ParseUI({
3111
- type: "Container",
3112
- visible: (tabIndex == 0),
3113
- parent: this.#rootWidget,
3114
- size: [this.#storeWidth, this.#headerHeight],
3115
- bgFill: mod.UIBgFill.None,
3116
- children: [
3117
- { // selected header outline if active:
3118
- type: "Container",
3119
- position: headerPosition,
3120
- size: headerSize,
3121
- bgFill: mod.UIBgFill.Solid,
3122
- bgColor: this.#activeTabBgColor,
3123
- bgAlpha: 0.25
3124
- }
3125
- ]
3126
- });
3127
- if (!tabWidget)
3128
- return;
3129
- this.#tabWidgets.push(tabWidget);
3130
- this.#createItems(tabIndex, tabData.itemDatas, tabData.tabRandomized);
3131
-
3132
- // header label. not part of the tab / always shown. after the tab so it gets drawn on top.
3133
- ParseUI({
3134
- type: "Text",
3135
- parent: this.#rootWidget,
3136
- position: headerPosition,
3137
- size: headerSize,
3138
- bgFill: mod.UIBgFill.None,
3139
- textLabel: tabData.tabName,
3140
- textSize: 30,
3141
- textAnchor: mod.UIAnchor.Center,
3142
- textColor: [1, 0.9, 0.8]
3143
- });
3144
- }
3145
-
3146
- #createItems(tabIndex: number, itemDatas: any[], randomize: boolean) {
3147
- let itemCount = itemDatas.length;
3148
- let maxItems = 12;
3149
- let selectedItems: any[] = [];
3150
-
3151
- if (itemCount < maxItems) {
3152
- maxItems = itemCount;
3153
- }
3154
-
3155
- let isItemFiltered = function (jsPlayer: JsPlayer, itemData: any) {
3156
- if (jsPlayer.isDeployed == false)
3157
- return true;
3158
-
3159
- try {
3160
- return itemData.hasOwnProperty("filter_weapon") && !mod.HasEquipment(jsPlayer.player, itemData.filter_weapon);
3161
- } catch (e) {
3162
- console.log("HasInventory exception: " + e);
3163
- return true;
3164
- }
3165
- return false;
3166
- }
3167
-
3168
- if (randomize == true) {
3169
- let isItemRandomized = function (itemData: any) {
3170
- return !itemData.hasOwnProperty("itemRandomized") || itemData.itemRandomized == true;
3171
- }
3172
- // get all the non-randomized items first:
3173
- let nonRandomCount = 0;
3174
- for (let itemIndex = 0; itemIndex < itemCount; ++itemIndex) {
3175
- if (!isItemRandomized(itemDatas[itemIndex])) {
3176
- this.#createItem(tabIndex, itemDatas[itemIndex], itemIndex);
3177
- nonRandomCount++;
3178
- }
3179
- }
3180
-
3181
- // add randomized items:
3182
- for (let itemIndex = nonRandomCount; itemIndex < maxItems; ++itemIndex) {
3183
- let randomItem = Math.floor(Math.random() * itemCount);
3184
-
3185
- if (selectedItems.includes(randomItem) || !isItemRandomized(itemDatas[randomItem])) {
3186
- itemIndex--;
3187
- } else {
3188
- this.#createItem(tabIndex, itemDatas[randomItem], itemIndex);
3189
- selectedItems.push(randomItem)
3190
- }
3191
- }
3192
- } else {
3193
- //console.log("Create ", itemCount, " non-random items");
3194
- let itemsCreated = 0;
3195
- for (let itemIndex = 0; itemIndex < itemCount; ++itemIndex) {
3196
- this.#createItem(tabIndex, itemDatas[itemIndex], itemsCreated++);
3197
- //console.log("Item Created")
3198
- }
3199
- }
3200
- }
3201
-
3202
- #createItem(tabIndex: number, itemData: any, itemIndex: number) {
3203
- let yi = Math.floor(itemIndex / 4);
3204
- let xi = Math.floor(itemIndex % 4);
3205
- let x = 50 + (1 + xi) * this.#itemSpacingHorizontal + xi * this.#itemSizeH;
3206
- let y = (1 + yi) * this.#itemSpacingVertical + yi * this.#itemSizeV;
3207
- let itemPos = [x, y];
3208
- this.#itemButtons[itemData.id] = new ItemButton(this.#jsPlayer, this.#tabWidgets[tabIndex], tabIndex, itemData, itemPos, this.#itemSize, this.#itemSizeH, this.#itemSizeV);
3209
- }
3210
-
3211
- rerollTabItems(tabIndex: number) {
3212
- this.#deleteTabItems(tabIndex);
3213
- let tabData = this.#storeData[tabIndex];
3214
- this.#createItems(tabIndex, tabData.itemDatas, tabData.tabRandomized);
3215
- }
3216
-
3217
- #deleteTabItems(tabIndex: number) {
3218
- for (const id in this.#itemButtons) {
3219
- if (this.#itemButtons[id].tabIndex == tabIndex) {
3220
- this.#itemButtons[id].destroy();
3221
- delete this.#itemButtons[id];
3222
- }
3223
- }
3224
- }
3225
-
3226
- autoBuyRandom() {
3227
- let itemKeys = Object.keys(this.#itemButtons);
3228
- let rnd = GetRandomInt(itemKeys.length);
3229
- debugger;
3230
- let itemData = this.#itemButtons[itemKeys[rnd]].itemData;
3231
- itemData.onBuyCallback?.(this.#jsPlayer, itemData);
3232
- }
3233
- }
3234
-
3235
-
3236
- //-----------------------------------------------------------------------------------------------//
3237
-
3238
- class ItemButton {
3239
- #jsPlayer;
3240
- #itemBgColor = [0.9, 0.6, 0.4];
3241
- tabIndex;
3242
- itemData;
3243
- #isDisabled;
3244
- #widget: mod.UIWidget|undefined;
3245
- #widgetButton: mod.UIWidget|undefined;
3246
- #widgetCost: mod.UIWidget|undefined;
3247
- #widgetCostName = "__cost";
3248
- #widgetDisabled: mod.UIWidget|undefined;
3249
- #widgetDisabledName = "__disabled";
3250
-
3251
- constructor(jsPlayer: JsPlayer, parentWidget: Widget, tabIndex: number, itemData: any, position: any, itemSize: number, itemSizeH: number, itemSizeV: number) {
3252
- this.#jsPlayer = jsPlayer;
3253
- this.tabIndex = tabIndex;
3254
- this.itemData = itemData;
3255
- let size = [itemSizeH, itemSizeV];
3256
- let disabledMsg = itemData.getDisabledMessageCallback?.(jsPlayer, itemData);
3257
- this.#isDisabled = disabledMsg != null;
3258
- let canAffordIt = this.itemData.canAffordIt(this.#jsPlayer, this.itemData);
3259
- this.#widget = ParseUI({
3260
- type: "Container",
3261
- parent: parentWidget,
3262
- position: position,
3263
- size: size,
3264
- bgFill: mod.UIBgFill.None,
3265
- playerID: jsPlayer.player,
3266
- children: [
3267
- {
3268
- type: "Button",
3269
- name: itemData.id,
3270
- size: size,
3271
- bgFill: mod.UIBgFill.Solid,
3272
- bgColor: this.#itemBgColor,
3273
- bgAlpha: 1,
3274
- buttonEnabled: !this.#isDisabled && canAffordIt
3275
- }, {
3276
- type: "Text",
3277
- size: [itemSize, 100],
3278
- anchor: mod.UIAnchor.TopCenter,
3279
- bgFill: mod.UIBgFill.None,
3280
- textLabel: itemData.name,
3281
- textAnchor: mod.UIAnchor.TopCenter,
3282
- textSize: 20,
3283
- }, {
3284
- type: "Text",
3285
- name: this.#widgetCostName,
3286
- anchor: mod.UIAnchor.BottomRight,
3287
- bgFill: mod.UIBgFill.None,
3288
- textLabel: MakeMessage(mod.stringkeys.store.costFmt, itemData.cost),
3289
- textAnchor: mod.UIAnchor.BottomRight,
3290
- textColor: canAffordIt ? [1, 1, 1] : [1, 0, 0],
3291
- textSize: 30,
3292
- }, {
3293
- type: "Text",
3294
- name: this.#widgetDisabledName,
3295
- visible: this.#isDisabled,
3296
- size: size,
3297
- padding: 10,
3298
- bgFill: mod.UIBgFill.Solid,
3299
- bgColor: [0.25, 0.25, 0.25],
3300
- bgAlpha: 0.8,
3301
- textLabel: disabledMsg ?? mod.stringkeys.store.disabledMsg.locked,
3302
- textAnchor: mod.UIAnchor.TopCenter,
3303
- textSize: 30,
3304
- textAlpha: 1
3305
- }
3306
- ]
3307
- });
3308
-
3309
-
3310
- if (!this.#widget)
3311
- return;
3312
-
3313
- if (itemData instanceof StoreItemDataWeapon) {
3314
- console.log("Create Image for weapon: ", itemData.name);
3315
- mod.AddUIWeaponImage(itemData.name, ZEROVEC, mod.CreateVector(size[0], size[1], 1), mod.UIAnchor.Center, itemData.weapon, this.#widget);
3316
- }
3317
- else if (itemData instanceof StoreItemDataGadget) {
3318
- console.log("Create Image for Gadget: ", itemData.name);
3319
- mod.AddUIGadgetImage(itemData.name, ZEROVEC, mod.CreateVector(size[0] * 0.7, size[1] * 0.7, 1), mod.UIAnchor.Center, itemData.weapon, this.#widget);
3320
- }
3321
-
3322
- this.#widgetButton = mod.FindUIWidgetWithName(itemData.id, this.#widget);
3323
- this.#widgetCost = mod.FindUIWidgetWithName(this.#widgetCostName, this.#widget);
3324
- this.#widgetDisabled = mod.FindUIWidgetWithName(this.#widgetDisabledName, this.#widget);
3325
- this.refresh();
3326
- }
3327
-
3328
- destroy() {
3329
- if (!this.#widget)
3330
- return;
3331
- mod.DeleteUIWidget(this.#widget);
3332
- }
3333
-
3334
- refresh() {
3335
- if (!this.#widgetCost || !this.#widgetButton || !this.#widgetDisabled)
3336
- return;
3337
- // price change ?
3338
- mod.SetUITextLabel(this.#widgetCost, MakeMessage(mod.stringkeys.store.costFmt, this.itemData.cost));
3339
- // disabled?
3340
- let wasDisabled = this.#isDisabled;
3341
- let disabledMsg = this.itemData.getDisabledMessageCallback?.(this.#jsPlayer, this.itemData);
3342
- let isDisabled = disabledMsg != null;
3343
- // has it changed?
3344
- if (wasDisabled !== isDisabled) {
3345
- this.#isDisabled = isDisabled;
3346
- mod.SetUIButtonEnabled(this.#widgetButton, !isDisabled);
3347
- mod.SetUIWidgetVisible(this.#widgetDisabled, isDisabled);
3348
- if (disabledMsg) {
3349
- if (typeof (disabledMsg) === "string")
3350
- disabledMsg = MakeMessage(disabledMsg);
3351
- mod.SetUITextLabel(this.#widgetDisabled, disabledMsg as mod.Message);
3352
- }
3353
- }
3354
-
3355
- // update if you can afford it?
3356
- let canAffordIt = this.itemData.canAffordIt(this.#jsPlayer, this.itemData);
3357
- if (!isDisabled)
3358
- mod.SetUIButtonEnabled(this.#widgetButton, canAffordIt);
3359
- mod.SetUITextColor(this.#widgetCost, canAffordIt ? mod.CreateVector(1, 1, 1) : mod.CreateVector(1, 0, 0));
3360
- }
3361
- }
3362
-
3363
-
3364
- //-----------------------------------------------------------------------------------------------//
3365
- //-----------------------------------------------------------------------------------------------//
3366
- //-----------------------------------------------------------------------------------------------//
3367
- //-----------------------------------------------------------------------------------------------//
3368
- // Helper functions to create UI from a JSON object tree:
3369
- //-----------------------------------------------------------------------------------------------//
3370
-
3371
- type UIVector = mod.Vector | number[];
3372
-
3373
- interface UIParams {
3374
- name: string;
3375
- type: string;
3376
- position: any;
3377
- size: any;
3378
- anchor: mod.UIAnchor;
3379
- parent: mod.UIWidget;
3380
- visible: boolean;
3381
- textLabel: string;
3382
- textColor: UIVector;
3383
- textAlpha: number;
3384
- textSize: number;
3385
- textAnchor: mod.UIAnchor;
3386
- padding: number;
3387
- bgColor: UIVector;
3388
- bgAlpha: number;
3389
- bgFill: mod.UIBgFill;
3390
- imageType: mod.UIImageType;
3391
- imageColor: UIVector;
3392
- imageAlpha: number;
3393
- teamId?: mod.Team;
3394
- playerId?: mod.Player;
3395
- children?: any[];
3396
- buttonEnabled: boolean;
3397
- buttonColorBase: UIVector;
3398
- buttonAlphaBase: number;
3399
- buttonColorDisabled: UIVector;
3400
- buttonAlphaDisabled: number;
3401
- buttonColorPressed: UIVector;
3402
- buttonAlphaPressed: number;
3403
- buttonColorHover: UIVector;
3404
- buttonAlphaHover: number;
3405
- buttonColorFocused: UIVector;
3406
- buttonAlphaFocused: number;
3407
- }
3408
-
3409
- function __asModVector(param: number[]|mod.Vector) {
3410
- if (Array.isArray(param))
3411
- return mod.CreateVector(param[0], param[1], param.length == 2 ? 0 : param[2]);
3412
- else
3413
- return param;
3414
- }
3415
-
3416
- function __asModMessage(param: string|mod.Message) {
3417
- if (typeof (param) === "string")
3418
- return mod.Message(param);
3419
- return param;
3420
- }
3421
-
3422
- function __fillInDefaultArgs(params: UIParams) {
3423
- if (!params.hasOwnProperty('name'))
3424
- params.name = "";
3425
- if (!params.hasOwnProperty('position'))
3426
- params.position = mod.CreateVector(0, 0, 0);
3427
- if (!params.hasOwnProperty('size'))
3428
- params.size = mod.CreateVector(100, 100, 0);
3429
- if (!params.hasOwnProperty('anchor'))
3430
- params.anchor = mod.UIAnchor.TopLeft;
3431
- if (!params.hasOwnProperty('parent'))
3432
- params.parent = mod.GetUIRoot();
3433
- if (!params.hasOwnProperty('visible'))
3434
- params.visible = true;
3435
- if (!params.hasOwnProperty('padding'))
3436
- params.padding = (params.type == "Container") ? 0 : 8;
3437
- if (!params.hasOwnProperty('bgColor'))
3438
- params.bgColor = mod.CreateVector(0.25, 0.25, 0.25);
3439
- if (!params.hasOwnProperty('bgAlpha'))
3440
- params.bgAlpha = 0.5;
3441
- if (!params.hasOwnProperty('bgFill'))
3442
- params.bgFill = mod.UIBgFill.Solid;
3443
- }
3444
-
3445
- function __setNameAndGetWidget(uniqueName: any, params: any) {
3446
- let widget = mod.FindUIWidgetWithName(uniqueName) as mod.UIWidget;
3447
- mod.SetUIWidgetName(widget, params.name);
3448
- return widget;
3449
- }
3450
-
3451
- const __cUniqueName = "----uniquename----";
3452
-
3453
- function __addUIContainer(params: UIParams) {
3454
- __fillInDefaultArgs(params);
3455
- let restrict = params.teamId ?? params.playerId;
3456
- if (restrict) {
3457
- mod.AddUIContainer(__cUniqueName,
3458
- __asModVector(params.position),
3459
- __asModVector(params.size),
3460
- params.anchor,
3461
- params.parent,
3462
- params.visible,
3463
- params.padding,
3464
- __asModVector(params.bgColor),
3465
- params.bgAlpha,
3466
- params.bgFill,
3467
- restrict);
3468
- } else {
3469
- mod.AddUIContainer(__cUniqueName,
3470
- __asModVector(params.position),
3471
- __asModVector(params.size),
3472
- params.anchor,
3473
- params.parent,
3474
- params.visible,
3475
- params.padding,
3476
- __asModVector(params.bgColor),
3477
- params.bgAlpha,
3478
- params.bgFill);
3479
- }
3480
- let widget = __setNameAndGetWidget(__cUniqueName, params);
3481
- if (params.children) {
3482
- params.children.forEach((childParams: any) => {
3483
- childParams.parent = widget;
3484
- __addUIWidget(childParams);
3485
- });
3486
- }
3487
- return widget;
3488
- }
3489
-
3490
- function __fillInDefaultTextArgs(params: UIParams) {
3491
- if (!params.hasOwnProperty('textLabel'))
3492
- params.textLabel = "";
3493
- if (!params.hasOwnProperty('textSize'))
3494
- params.textSize = 0;
3495
- if (!params.hasOwnProperty('textColor'))
3496
- params.textColor = mod.CreateVector(1, 1, 1);
3497
- if (!params.hasOwnProperty('textAlpha'))
3498
- params.textAlpha = 1;
3499
- if (!params.hasOwnProperty('textAnchor'))
3500
- params.textAnchor = mod.UIAnchor.CenterLeft;
3501
- }
3502
-
3503
- function __addUIText(params: UIParams) {
3504
- __fillInDefaultArgs(params);
3505
- __fillInDefaultTextArgs(params);
3506
- let restrict = params.teamId ?? params.playerId;
3507
- if (restrict) {
3508
- mod.AddUIText(__cUniqueName,
3509
- __asModVector(params.position),
3510
- __asModVector(params.size),
3511
- params.anchor,
3512
- params.parent,
3513
- params.visible,
3514
- params.padding,
3515
- __asModVector(params.bgColor),
3516
- params.bgAlpha,
3517
- params.bgFill,
3518
- __asModMessage(params.textLabel),
3519
- params.textSize,
3520
- __asModVector(params.textColor),
3521
- params.textAlpha,
3522
- params.textAnchor,
3523
- restrict);
3524
- } else {
3525
- mod.AddUIText(__cUniqueName,
3526
- __asModVector(params.position),
3527
- __asModVector(params.size),
3528
- params.anchor,
3529
- params.parent,
3530
- params.visible,
3531
- params.padding,
3532
- __asModVector(params.bgColor),
3533
- params.bgAlpha,
3534
- params.bgFill,
3535
- __asModMessage(params.textLabel),
3536
- params.textSize,
3537
- __asModVector(params.textColor),
3538
- params.textAlpha,
3539
- params.textAnchor);
3540
- }
3541
- return __setNameAndGetWidget(__cUniqueName, params);
3542
- }
3543
-
3544
- function __fillInDefaultImageArgs(params: any) {
3545
- if (!params.hasOwnProperty('imageType'))
3546
- params.imageType = mod.UIImageType.None;
3547
- if (!params.hasOwnProperty('imageColor'))
3548
- params.imageColor = mod.CreateVector(1, 1, 1);
3549
- if (!params.hasOwnProperty('imageAlpha'))
3550
- params.imageAlpha = 1;
3551
- }
3552
-
3553
- function __addUIImage(params: UIParams) {
3554
- __fillInDefaultArgs(params);
3555
- __fillInDefaultImageArgs(params);
3556
- let restrict = params.teamId ?? params.playerId;
3557
- if (restrict) {
3558
- mod.AddUIImage(__cUniqueName,
3559
- __asModVector(params.position),
3560
- __asModVector(params.size),
3561
- params.anchor,
3562
- params.parent,
3563
- params.visible,
3564
- params.padding,
3565
- __asModVector(params.bgColor),
3566
- params.bgAlpha,
3567
- params.bgFill,
3568
- params.imageType,
3569
- __asModVector(params.imageColor),
3570
- params.imageAlpha,
3571
- restrict);
3572
- } else {
3573
- mod.AddUIImage(__cUniqueName,
3574
- __asModVector(params.position),
3575
- __asModVector(params.size),
3576
- params.anchor,
3577
- params.parent,
3578
- params.visible,
3579
- params.padding,
3580
- __asModVector(params.bgColor),
3581
- params.bgAlpha,
3582
- params.bgFill,
3583
- params.imageType,
3584
- __asModVector(params.imageColor),
3585
- params.imageAlpha);
3586
- }
3587
- return __setNameAndGetWidget(__cUniqueName, params);
3588
- }
3589
-
3590
- function __fillInDefaultArg(params: any, argName: any, defaultValue: any) {
3591
- if (!params.hasOwnProperty(argName))
3592
- params[argName] = defaultValue;
3593
- }
3594
-
3595
- function __fillInDefaultButtonArgs(params: any) {
3596
- if (!params.hasOwnProperty('buttonEnabled'))
3597
- params.buttonEnabled = true;
3598
- if (!params.hasOwnProperty('buttonColorBase'))
3599
- params.buttonColorBase = mod.CreateVector(0.7, 0.7, 0.7);
3600
- if (!params.hasOwnProperty('buttonAlphaBase'))
3601
- params.buttonAlphaBase = 1;
3602
- if (!params.hasOwnProperty('buttonColorDisabled'))
3603
- params.buttonColorDisabled = mod.CreateVector(0.2, 0.2, 0.2);
3604
- if (!params.hasOwnProperty('buttonAlphaDisabled'))
3605
- params.buttonAlphaDisabled = 0.5;
3606
- if (!params.hasOwnProperty('buttonColorPressed'))
3607
- params.buttonColorPressed = mod.CreateVector(0.25, 0.25, 0.25);
3608
- if (!params.hasOwnProperty('buttonAlphaPressed'))
3609
- params.buttonAlphaPressed = 1;
3610
- if (!params.hasOwnProperty('buttonColorHover'))
3611
- params.buttonColorHover = mod.CreateVector(1,1,1);
3612
- if (!params.hasOwnProperty('buttonAlphaHover'))
3613
- params.buttonAlphaHover = 1;
3614
- if (!params.hasOwnProperty('buttonColorFocused'))
3615
- params.buttonColorFocused = mod.CreateVector(1,1,1);
3616
- if (!params.hasOwnProperty('buttonAlphaFocused'))
3617
- params.buttonAlphaFocused = 1;
3618
- }
3619
-
3620
- function __addUIButton(params: UIParams) {
3621
- __fillInDefaultArgs(params);
3622
- __fillInDefaultButtonArgs(params);
3623
- let restrict = params.teamId ?? params.playerId;
3624
- if (restrict) {
3625
- mod.AddUIButton(__cUniqueName,
3626
- __asModVector(params.position),
3627
- __asModVector(params.size),
3628
- params.anchor,
3629
- params.parent,
3630
- params.visible,
3631
- params.padding,
3632
- __asModVector(params.bgColor),
3633
- params.bgAlpha,
3634
- params.bgFill,
3635
- params.buttonEnabled,
3636
- __asModVector(params.buttonColorBase), params.buttonAlphaBase,
3637
- __asModVector(params.buttonColorDisabled), params.buttonAlphaDisabled,
3638
- __asModVector(params.buttonColorPressed), params.buttonAlphaPressed,
3639
- __asModVector(params.buttonColorHover), params.buttonAlphaHover,
3640
- __asModVector(params.buttonColorFocused), params.buttonAlphaFocused,
3641
- restrict);
3642
- } else {
3643
- mod.AddUIButton(__cUniqueName,
3644
- __asModVector(params.position),
3645
- __asModVector(params.size),
3646
- params.anchor,
3647
- params.parent,
3648
- params.visible,
3649
- params.padding,
3650
- __asModVector(params.bgColor),
3651
- params.bgAlpha,
3652
- params.bgFill,
3653
- params.buttonEnabled,
3654
- __asModVector(params.buttonColorBase), params.buttonAlphaBase,
3655
- __asModVector(params.buttonColorDisabled), params.buttonAlphaDisabled,
3656
- __asModVector(params.buttonColorPressed), params.buttonAlphaPressed,
3657
- __asModVector(params.buttonColorHover), params.buttonAlphaHover,
3658
- __asModVector(params.buttonColorFocused), params.buttonAlphaFocused);
3659
- }
3660
- return __setNameAndGetWidget(__cUniqueName, params);
3661
- }
3662
-
3663
- function __addUIWidget(params: UIParams) {
3664
- if (params == null)
3665
- return undefined;
3666
- if (params.type == "Container")
3667
- return __addUIContainer(params);
3668
- else if (params.type == "Text")
3669
- return __addUIText(params);
3670
- else if (params.type == "Image")
3671
- return __addUIImage(params);
3672
- else if (params.type == "Button")
3673
- return __addUIButton(params);
3674
- return undefined;
3675
- }
3676
-
3677
- export function ParseUI(...params: any[]) {
3678
- let widget: mod.UIWidget|undefined;
3679
- for (let a = 0; a < params.length; a++) {
3680
- widget = __addUIWidget(params[a] as UIParams);
3681
- }
3682
- return widget;
3683
- }