@hytopia.com/examples 1.0.50 → 1.0.51
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.
|
Binary file
|
|
Binary file
|
|
@@ -33,8 +33,36 @@
|
|
|
33
33
|
<!-- Leaderboard -->
|
|
34
34
|
<div class="leaderboard">
|
|
35
35
|
<div class="leaderboard-title">Deathmatch</div>
|
|
36
|
-
<div class="leaderboard-
|
|
37
|
-
|
|
36
|
+
<div class="leaderboard-info-row">
|
|
37
|
+
<div class="leaderboard-timer">
|
|
38
|
+
<img src="{{CDN_ASSETS_URL}}/icons/clock.png" alt="Timer" class="leaderboard-info-icon">
|
|
39
|
+
<span class="leaderboard-timer-value">0:00</span>
|
|
40
|
+
</div>
|
|
41
|
+
<div class="leaderboard-players-count">
|
|
42
|
+
<img src="{{CDN_ASSETS_URL}}/icons/player.png" alt="Players" class="leaderboard-info-icon">
|
|
43
|
+
<span class="leaderboard-player-count-value">0</span>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
<div class="leaderboard-mobile-summary">
|
|
47
|
+
<div class="leaderboard-summary-entry summary-top">
|
|
48
|
+
<div class="summary-label-with-icon">
|
|
49
|
+
<img src="{{CDN_ASSETS_URL}}/icons/crown-gold.png" class="summary-crown" alt="Top player">
|
|
50
|
+
<span class="summary-name summary-top-name">—</span>
|
|
51
|
+
</div>
|
|
52
|
+
<span class="summary-kills summary-top-kills">0</span>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="leaderboard-summary-entry summary-second">
|
|
55
|
+
<div class="summary-label-with-icon">
|
|
56
|
+
<img src="{{CDN_ASSETS_URL}}/icons/crown-silver.png" class="summary-crown" alt="Second player">
|
|
57
|
+
<span class="summary-name summary-second-name">—</span>
|
|
58
|
+
</div>
|
|
59
|
+
<span class="summary-kills summary-second-kills">0</span>
|
|
60
|
+
</div>
|
|
61
|
+
<div class="leaderboard-summary-entry summary-self">
|
|
62
|
+
<span class="summary-name summary-self-name">You</span>
|
|
63
|
+
<span class="summary-kills summary-self-kills">0</span>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
38
66
|
<div class="leaderboard-header">
|
|
39
67
|
<div class="header-name">Player</div>
|
|
40
68
|
<div class="header-kills">Kills</div>
|
|
@@ -62,15 +90,17 @@
|
|
|
62
90
|
<div class="exp-text">Unranked</div>
|
|
63
91
|
</div>
|
|
64
92
|
|
|
65
|
-
<div class="shield-
|
|
66
|
-
<div class="
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
<div class="
|
|
72
|
-
|
|
73
|
-
|
|
93
|
+
<div class="health-shield-row">
|
|
94
|
+
<div class="health-bar">
|
|
95
|
+
<div class="health-bar-fill"></div>
|
|
96
|
+
<img src="{{CDN_ASSETS_URL}}/icons/heart.png" alt="Health Icon" class="health-icon">
|
|
97
|
+
<div class="health-text">100</div>
|
|
98
|
+
</div>
|
|
99
|
+
<div class="shield-bar">
|
|
100
|
+
<div class="shield-bar-fill"></div>
|
|
101
|
+
<img src="{{CDN_ASSETS_URL}}/icons/shield.png" alt="Shield Icon" class="shield-icon">
|
|
102
|
+
<div class="shield-text">0</div>
|
|
103
|
+
</div>
|
|
74
104
|
</div>
|
|
75
105
|
</div>
|
|
76
106
|
</div>
|
|
@@ -176,6 +206,13 @@
|
|
|
176
206
|
let gameEndTime = 0;
|
|
177
207
|
let timerInterval;
|
|
178
208
|
let isLoadExpUpdate = true; // Flag to track the first EXP update
|
|
209
|
+
let localPlayerUsername = '';
|
|
210
|
+
const summaryTopNameEl = document.querySelector('.summary-top-name');
|
|
211
|
+
const summaryTopKillsEl = document.querySelector('.summary-top-kills');
|
|
212
|
+
const summarySecondNameEl = document.querySelector('.summary-second-name');
|
|
213
|
+
const summarySecondKillsEl = document.querySelector('.summary-second-kills');
|
|
214
|
+
const summarySelfNameEl = document.querySelector('.summary-self-name');
|
|
215
|
+
const summarySelfKillsEl = document.querySelector('.summary-self-kills');
|
|
179
216
|
|
|
180
217
|
function updateLeaderboard() {
|
|
181
218
|
const leaderboardPlayers = document.querySelector('.leaderboard-players');
|
|
@@ -239,6 +276,35 @@
|
|
|
239
276
|
|
|
240
277
|
leaderboardPlayers.appendChild(playerElement);
|
|
241
278
|
});
|
|
279
|
+
|
|
280
|
+
updateLeaderboardSummary();
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function updateLeaderboardSummary() {
|
|
284
|
+
if (
|
|
285
|
+
!document.body.classList.contains('mobile') ||
|
|
286
|
+
!summaryTopNameEl ||
|
|
287
|
+
!summaryTopKillsEl ||
|
|
288
|
+
!summarySecondNameEl ||
|
|
289
|
+
!summarySecondKillsEl ||
|
|
290
|
+
!summarySelfNameEl ||
|
|
291
|
+
!summarySelfKillsEl
|
|
292
|
+
) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const entries = Object.entries(leaderboardKillCounts).sort((a, b) => b[1] - a[1]);
|
|
297
|
+
const [topName = '—', topKills = 0] = entries[0] ?? [];
|
|
298
|
+
const [secondName = '—', secondKills = 0] = entries[1] ?? [];
|
|
299
|
+
const yourName = localPlayerUsername || 'You';
|
|
300
|
+
const yourKills = localPlayerUsername ? (leaderboardKillCounts[localPlayerUsername] ?? 0) : 0;
|
|
301
|
+
|
|
302
|
+
summaryTopNameEl.textContent = topName || '—';
|
|
303
|
+
summaryTopKillsEl.textContent = `${topKills || 0} Kills`;
|
|
304
|
+
summarySecondNameEl.textContent = secondName || '—';
|
|
305
|
+
summarySecondKillsEl.textContent = `${secondKills || 0} Kills`;
|
|
306
|
+
summarySelfNameEl.textContent = yourName;
|
|
307
|
+
summarySelfKillsEl.textContent = `${yourKills || 0} Kills`;
|
|
242
308
|
}
|
|
243
309
|
|
|
244
310
|
function updateTimer() {
|
|
@@ -250,8 +316,10 @@
|
|
|
250
316
|
const seconds = Math.floor((timeRemaining % 60000) / 1000);
|
|
251
317
|
const formattedTime = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
|
252
318
|
|
|
253
|
-
const
|
|
254
|
-
|
|
319
|
+
const timerValue = document.querySelector('.leaderboard-timer-value');
|
|
320
|
+
if (timerValue) {
|
|
321
|
+
timerValue.textContent = formattedTime;
|
|
322
|
+
}
|
|
255
323
|
|
|
256
324
|
// Stop the timer when it reaches zero
|
|
257
325
|
if (timeRemaining <= 0) {
|
|
@@ -549,21 +617,29 @@
|
|
|
549
617
|
}
|
|
550
618
|
|
|
551
619
|
if (type === 'leaderboard-sync') {
|
|
552
|
-
const { killCounts } = data;
|
|
620
|
+
const { killCounts, localPlayer } = data;
|
|
553
621
|
leaderboardKillCounts = killCounts;
|
|
622
|
+
if (localPlayer) {
|
|
623
|
+
localPlayerUsername = localPlayer;
|
|
624
|
+
}
|
|
554
625
|
updateLeaderboard();
|
|
555
626
|
}
|
|
556
627
|
|
|
557
628
|
if (type === 'leaderboard-update') {
|
|
558
|
-
const { username, killCount } = data;
|
|
629
|
+
const { username, killCount, localPlayer } = data;
|
|
559
630
|
leaderboardKillCounts[username] = killCount;
|
|
631
|
+
if (localPlayer) {
|
|
632
|
+
localPlayerUsername = localPlayer;
|
|
633
|
+
}
|
|
560
634
|
updateLeaderboard();
|
|
561
635
|
}
|
|
562
636
|
|
|
563
637
|
if (type === 'players-count') {
|
|
564
638
|
const { count } = data;
|
|
565
|
-
const playersCount = document.querySelector('.leaderboard-
|
|
566
|
-
playersCount
|
|
639
|
+
const playersCount = document.querySelector('.leaderboard-player-count-value');
|
|
640
|
+
if (playersCount) {
|
|
641
|
+
playersCount.textContent = count;
|
|
642
|
+
}
|
|
567
643
|
}
|
|
568
644
|
|
|
569
645
|
if (type === 'materials') {
|
|
@@ -1141,6 +1217,7 @@
|
|
|
1141
1217
|
border-radius: 3px;
|
|
1142
1218
|
box-shadow: 0 0 10px rgba(230, 190, 40, 0.3);
|
|
1143
1219
|
position: relative; /* Needed for absolute positioning of children */
|
|
1220
|
+
text-align: center;
|
|
1144
1221
|
}
|
|
1145
1222
|
|
|
1146
1223
|
.exp-bar-fill {
|
|
@@ -1358,6 +1435,7 @@
|
|
|
1358
1435
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
|
|
1359
1436
|
border: 2px solid rgba(255, 255, 255, 0.2);
|
|
1360
1437
|
z-index: 100;
|
|
1438
|
+
pointer-events: none;
|
|
1361
1439
|
}
|
|
1362
1440
|
|
|
1363
1441
|
.leaderboard-title {
|
|
@@ -1372,17 +1450,36 @@
|
|
|
1372
1450
|
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
|
|
1373
1451
|
}
|
|
1374
1452
|
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1453
|
+
.leaderboard-info-row {
|
|
1454
|
+
display: flex;
|
|
1455
|
+
justify-content: space-between;
|
|
1456
|
+
gap: 8px;
|
|
1379
1457
|
margin-bottom: 10px;
|
|
1380
|
-
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
.leaderboard-info-row .leaderboard-timer,
|
|
1461
|
+
.leaderboard-info-row .leaderboard-players-count {
|
|
1462
|
+
flex: 1;
|
|
1463
|
+
display: flex;
|
|
1464
|
+
align-items: center;
|
|
1465
|
+
justify-content: center;
|
|
1466
|
+
gap: 6px;
|
|
1381
1467
|
background: rgba(255, 255, 255, 0.1);
|
|
1382
1468
|
border-radius: 3px;
|
|
1469
|
+
padding: 3px 6px;
|
|
1470
|
+
height: 20px;
|
|
1471
|
+
font-size: 15px;
|
|
1472
|
+
font-weight: bold;
|
|
1383
1473
|
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
|
|
1384
1474
|
}
|
|
1385
1475
|
|
|
1476
|
+
.leaderboard-info-icon {
|
|
1477
|
+
width: 14px;
|
|
1478
|
+
height: 14px;
|
|
1479
|
+
object-fit: contain;
|
|
1480
|
+
display: block;
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1386
1483
|
.leaderboard-header {
|
|
1387
1484
|
display: flex;
|
|
1388
1485
|
justify-content: space-between;
|
|
@@ -1450,50 +1547,107 @@
|
|
|
1450
1547
|
display: none;
|
|
1451
1548
|
}
|
|
1452
1549
|
|
|
1550
|
+
.leaderboard-mobile-summary {
|
|
1551
|
+
display: none;
|
|
1552
|
+
gap: 4px;
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
.leaderboard-summary-entry {
|
|
1556
|
+
display: flex;
|
|
1557
|
+
justify-content: space-between;
|
|
1558
|
+
align-items: center;
|
|
1559
|
+
padding: 4px 8px;
|
|
1560
|
+
background: rgba(255, 255, 255, 0.1);
|
|
1561
|
+
border-radius: 4px;
|
|
1562
|
+
font-weight: 600;
|
|
1563
|
+
font-size: 10px;
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
.summary-label-with-icon {
|
|
1567
|
+
display: flex;
|
|
1568
|
+
align-items: center;
|
|
1569
|
+
gap: 6px;
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
.summary-crown {
|
|
1573
|
+
width: 12px;
|
|
1574
|
+
height: 12px;
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
.leaderboard-summary-entry .summary-name {
|
|
1578
|
+
letter-spacing: 0.4px;
|
|
1579
|
+
text-transform: uppercase;
|
|
1580
|
+
font-size: 10px;
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
.leaderboard-summary-entry .summary-kills {
|
|
1584
|
+
font-size: 11px;
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1453
1587
|
/* Mobile UI */
|
|
1454
1588
|
body.mobile .hud {
|
|
1589
|
+
top: 15px;
|
|
1455
1590
|
left: 50%;
|
|
1456
1591
|
transform: translateX(-50%);
|
|
1457
|
-
bottom:
|
|
1592
|
+
bottom: auto;
|
|
1458
1593
|
right: auto;
|
|
1459
1594
|
}
|
|
1460
1595
|
|
|
1461
1596
|
body.mobile .inventory-hud {
|
|
1462
|
-
bottom:
|
|
1597
|
+
bottom: 28px;
|
|
1598
|
+
left: 24px;
|
|
1599
|
+
right: auto;
|
|
1600
|
+
top: auto;
|
|
1601
|
+
transform: none;
|
|
1602
|
+
display: flex;
|
|
1603
|
+
gap: 10px;
|
|
1463
1604
|
}
|
|
1464
1605
|
|
|
1465
1606
|
body.mobile .inventory-slot {
|
|
1466
|
-
width:
|
|
1467
|
-
height:
|
|
1468
|
-
}
|
|
1469
|
-
|
|
1470
|
-
body.mobile .slot-number {
|
|
1471
|
-
font-size: 12px;
|
|
1472
|
-
top: -16px;
|
|
1607
|
+
width: 50px;
|
|
1608
|
+
height: 50px;
|
|
1473
1609
|
}
|
|
1474
1610
|
|
|
1611
|
+
body.mobile .slot-number,
|
|
1475
1612
|
body.mobile .slot-name {
|
|
1476
|
-
|
|
1477
|
-
bottom: -14px;
|
|
1613
|
+
display: none;
|
|
1478
1614
|
}
|
|
1479
1615
|
|
|
1480
1616
|
body.mobile .slot-quantity {
|
|
1481
1617
|
font-size: 10px;
|
|
1482
1618
|
}
|
|
1483
1619
|
|
|
1484
|
-
body.mobile .shield-bar,
|
|
1485
|
-
body.mobile .health-bar,
|
|
1486
1620
|
body.mobile .exp-bar {
|
|
1621
|
+
width: 160px;
|
|
1622
|
+
height: 16px;
|
|
1623
|
+
margin-bottom: 8px;
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
body.mobile .exp-text {
|
|
1627
|
+
font-size: 0.7em;
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
body.mobile .shield-bar,
|
|
1631
|
+
body.mobile .health-bar {
|
|
1487
1632
|
width: 120px;
|
|
1488
1633
|
height: 16px;
|
|
1489
1634
|
}
|
|
1490
1635
|
|
|
1491
1636
|
body.mobile .shield-text,
|
|
1492
|
-
body.mobile .health-text
|
|
1493
|
-
body.mobile .exp-text {
|
|
1637
|
+
body.mobile .health-text {
|
|
1494
1638
|
font-size: 0.7em;
|
|
1495
1639
|
}
|
|
1496
1640
|
|
|
1641
|
+
body.mobile .info-container {
|
|
1642
|
+
flex-direction: column;
|
|
1643
|
+
gap: 6px;
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
body.mobile .health-shield-row {
|
|
1647
|
+
display: flex;
|
|
1648
|
+
gap: 10px;
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1497
1651
|
body.mobile .shield-icon,
|
|
1498
1652
|
body.mobile .health-icon {
|
|
1499
1653
|
width: 10px;
|
|
@@ -1505,31 +1659,57 @@
|
|
|
1505
1659
|
height: 35px;
|
|
1506
1660
|
}
|
|
1507
1661
|
|
|
1662
|
+
body.mobile .leaderboard {
|
|
1663
|
+
top: 20px;
|
|
1664
|
+
right: 20px;
|
|
1665
|
+
width: 180px;
|
|
1666
|
+
max-height: none;
|
|
1667
|
+
z-index: 120;
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1508
1670
|
body.mobile .leaderboard-title {
|
|
1509
1671
|
font-size: 14px;
|
|
1510
1672
|
}
|
|
1511
1673
|
|
|
1512
|
-
body.mobile .leaderboard-timer
|
|
1513
|
-
|
|
1674
|
+
body.mobile .leaderboard-timer,
|
|
1675
|
+
body.mobile .leaderboard-players-count {
|
|
1676
|
+
font-size: 11px;
|
|
1677
|
+
padding: 3px 4px;
|
|
1514
1678
|
}
|
|
1515
1679
|
|
|
1516
|
-
body.mobile .leaderboard-
|
|
1517
|
-
display:
|
|
1518
|
-
|
|
1680
|
+
body.mobile .leaderboard-mobile-summary {
|
|
1681
|
+
display: flex;
|
|
1682
|
+
flex-direction: column;
|
|
1683
|
+
gap: 4px;
|
|
1519
1684
|
}
|
|
1520
1685
|
|
|
1521
|
-
body.mobile .leaderboard-
|
|
1522
|
-
|
|
1686
|
+
body.mobile .leaderboard-info-row {
|
|
1687
|
+
margin-bottom: 0px;
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
body.mobile .leaderboard-mobile-summary .leaderboard-summary-entry:last-child {
|
|
1691
|
+
margin-bottom: 0;
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
body.mobile .leaderboard-header,
|
|
1695
|
+
body.mobile .leaderboard-players {
|
|
1696
|
+
display: none;
|
|
1523
1697
|
}
|
|
1524
1698
|
|
|
1525
1699
|
body.mobile .leaderboard-player {
|
|
1526
1700
|
font-size: 10px;
|
|
1527
1701
|
}
|
|
1528
1702
|
|
|
1703
|
+
body.mobile .materials-amount {
|
|
1704
|
+
font-size: 14px;
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1529
1707
|
body.mobile .materials-counter {
|
|
1530
|
-
|
|
1531
|
-
bottom:
|
|
1532
|
-
|
|
1708
|
+
left: 24px;
|
|
1709
|
+
bottom: 90px;
|
|
1710
|
+
top: auto;
|
|
1711
|
+
right: auto;
|
|
1712
|
+
font-size: 10px;
|
|
1533
1713
|
}
|
|
1534
1714
|
|
|
1535
1715
|
body.mobile .floating-number {
|
|
@@ -1545,31 +1725,34 @@
|
|
|
1545
1725
|
}
|
|
1546
1726
|
|
|
1547
1727
|
body.mobile .mobile-buttons-container {
|
|
1548
|
-
display:
|
|
1549
|
-
gap: 10px;
|
|
1728
|
+
display: block;
|
|
1550
1729
|
position: fixed;
|
|
1551
|
-
bottom:
|
|
1552
|
-
right:
|
|
1730
|
+
bottom: 30px;
|
|
1731
|
+
right: 50px;
|
|
1732
|
+
width: 250px;
|
|
1733
|
+
height: 230px;
|
|
1553
1734
|
user-select: none;
|
|
1554
|
-
pointer-events:
|
|
1735
|
+
pointer-events: none;
|
|
1736
|
+
z-index: 1000;
|
|
1555
1737
|
}
|
|
1556
1738
|
|
|
1557
1739
|
body.mobile .mobile-button {
|
|
1558
|
-
|
|
1740
|
+
position: absolute;
|
|
1741
|
+
background-color: rgba(0, 0, 0, 0.55);
|
|
1559
1742
|
border-radius: 50%;
|
|
1560
1743
|
align-items: center;
|
|
1561
1744
|
justify-content: center;
|
|
1562
1745
|
display: flex;
|
|
1563
|
-
width:
|
|
1564
|
-
height:
|
|
1746
|
+
width: 56px;
|
|
1747
|
+
height: 56px;
|
|
1565
1748
|
-webkit-tap-highlight-color: transparent;
|
|
1566
|
-
touch-action:
|
|
1749
|
+
touch-action: manipulation;
|
|
1567
1750
|
user-select: none;
|
|
1568
1751
|
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
|
|
1569
1752
|
will-change: transform, background-color;
|
|
1570
|
-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.
|
|
1753
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
|
|
1571
1754
|
font-family: 'Inter', sans-serif;
|
|
1572
|
-
font-size:
|
|
1755
|
+
font-size: 13px;
|
|
1573
1756
|
font-weight: bold;
|
|
1574
1757
|
color: rgba(255, 255, 255, 0.8);
|
|
1575
1758
|
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
|
|
@@ -1583,8 +1766,48 @@
|
|
|
1583
1766
|
}
|
|
1584
1767
|
|
|
1585
1768
|
body.mobile .mobile-button img {
|
|
1586
|
-
width:
|
|
1587
|
-
height:
|
|
1769
|
+
width: 22px;
|
|
1770
|
+
height: 22px;
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
body.mobile #mobile-attack-button {
|
|
1774
|
+
width: 100px;
|
|
1775
|
+
height: 100px;
|
|
1776
|
+
bottom: 0;
|
|
1777
|
+
right: 0;
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
body.mobile #mobile-attack-button img {
|
|
1781
|
+
width: 40px;
|
|
1782
|
+
height: 40px;
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1785
|
+
body.mobile #mobile-jump-button {
|
|
1786
|
+
width: 66px;
|
|
1787
|
+
height: 66px;
|
|
1788
|
+
bottom: 110px;
|
|
1789
|
+
right: -10px;
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
body.mobile #mobile-place-block-button {
|
|
1793
|
+
width: 62px;
|
|
1794
|
+
height: 62px;
|
|
1795
|
+
bottom: -20px;
|
|
1796
|
+
right: 105px;
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
body.mobile #mobile-interact-button {
|
|
1800
|
+
width: 58px;
|
|
1801
|
+
height: 58px;
|
|
1802
|
+
bottom: 50px;
|
|
1803
|
+
right: 110px;
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
body.mobile #mobile-reload-button {
|
|
1807
|
+
width: 58px;
|
|
1808
|
+
height: 58px;
|
|
1809
|
+
bottom: 100px;
|
|
1810
|
+
right: 65px;
|
|
1588
1811
|
}
|
|
1589
1812
|
|
|
1590
1813
|
body.mobile .rank-up-title {
|
|
@@ -17,9 +17,9 @@ import GunEntity from './GunEntity';
|
|
|
17
17
|
import ItemEntity from './ItemEntity';
|
|
18
18
|
import { SPAWN_REGION_AABB } from '../gameConfig';
|
|
19
19
|
|
|
20
|
-
const AIM_JITTER_RADIANS = 0.
|
|
21
|
-
const AIM_JITTER_RANDOM_MIN_SCALE = 0.
|
|
22
|
-
const AIM_JITTER_RANDOM_MAX_SCALE = 2.
|
|
20
|
+
const AIM_JITTER_RADIANS = 0.055;
|
|
21
|
+
const AIM_JITTER_RANDOM_MIN_SCALE = 0.6;
|
|
22
|
+
const AIM_JITTER_RANDOM_MAX_SCALE = 2.6;
|
|
23
23
|
const MELEE_ATTACK_RANGE = 2.4;
|
|
24
24
|
const PICKAXE_SLOT_INDEX = 0;
|
|
25
25
|
const LOOT_INTERACT_RANGE = 1.5;
|
|
@@ -28,6 +28,7 @@ const NAVIGATION_MIN_PROGRESS = 0.35;
|
|
|
28
28
|
const MAX_VERTICAL_TARGET_DELTA = 12;
|
|
29
29
|
const MELEE_LOOT_OPPORTUNITY_RANGE = 8;
|
|
30
30
|
const BEHAVIOR_LOCK_MS = 450;
|
|
31
|
+
const REACTION_DELAY_MS = 180;
|
|
31
32
|
const ENEMY_RETARGET_COOLDOWN_MS = 750;
|
|
32
33
|
const ENEMY_LOST_GRACE_MS = 1400;
|
|
33
34
|
const LOOT_RETARGET_COOLDOWN_MS = 550;
|
|
@@ -194,7 +195,7 @@ class BotStubPlayer extends EventRouter {
|
|
|
194
195
|
export default class BotPlayerEntity extends GamePlayerEntity {
|
|
195
196
|
private static readonly _botsByWorld: Map<number, Set<BotPlayerEntity>> = new Map();
|
|
196
197
|
private static readonly _activeWorlds: Set<number> = new Set();
|
|
197
|
-
private static readonly _maxBots = 5 + Math.floor(Math.random() * 4); // 5-8 inclusive
|
|
198
|
+
private static readonly _maxBots = 50; //5 + Math.floor(Math.random() * 4); // 5-8 inclusive
|
|
198
199
|
|
|
199
200
|
public static ensureForWorld(world: World): void {
|
|
200
201
|
const bots = this._botsByWorld.get(world.id) ?? new Set<BotPlayerEntity>();
|
|
@@ -292,6 +293,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
|
|
|
292
293
|
private _lootForgetAt = 0;
|
|
293
294
|
private _activeLootTargetId: number | undefined;
|
|
294
295
|
private _lootOverrideUntil = 0;
|
|
296
|
+
private _nextReactionAt = 0;
|
|
295
297
|
|
|
296
298
|
private constructor(driver: BotStubPlayer) {
|
|
297
299
|
super(driver as unknown as Player);
|
|
@@ -552,6 +554,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
|
|
|
552
554
|
this._enemyForgetAt = now + ENEMY_LOST_GRACE_MS;
|
|
553
555
|
this._blockBreakTarget = undefined;
|
|
554
556
|
this._blockBreakExpiresAt = 0;
|
|
557
|
+
this._nextReactionAt = now + REACTION_DELAY_MS + Math.random() * REACTION_DELAY_MS;
|
|
555
558
|
}
|
|
556
559
|
|
|
557
560
|
return;
|
|
@@ -562,6 +565,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
|
|
|
562
565
|
(!current.isSpawned || current.isDead || now > this._enemyForgetAt)
|
|
563
566
|
) {
|
|
564
567
|
this._targetEnemy = undefined;
|
|
568
|
+
this._nextReactionAt = 0;
|
|
565
569
|
}
|
|
566
570
|
}
|
|
567
571
|
|
|
@@ -676,6 +680,11 @@ export default class BotPlayerEntity extends GamePlayerEntity {
|
|
|
676
680
|
|
|
677
681
|
const enemyPosition = this._targetEnemy.position;
|
|
678
682
|
const distance = Math.sqrt(this._distanceSq(this.position, enemyPosition));
|
|
683
|
+
if (performance.now() < this._nextReactionAt) {
|
|
684
|
+
this._facePosition(enemyPosition, true, AIM_JITTER_RADIANS);
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
|
|
679
688
|
const gun = this._ensureBestWeaponEquipped();
|
|
680
689
|
|
|
681
690
|
if (gun && gun.hasUsableAmmo()) {
|
|
@@ -786,7 +795,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
|
|
|
786
795
|
const shouldJump = this._shouldAutoJump(target);
|
|
787
796
|
if (shouldJump) {
|
|
788
797
|
input.sp = true;
|
|
789
|
-
this._jumpRetryDebounceAt = performance.now() +
|
|
798
|
+
this._jumpRetryDebounceAt = performance.now() + 550;
|
|
790
799
|
} else if (!this._hasHeadroom() && this.playerController.isGrounded) {
|
|
791
800
|
input.sp = true;
|
|
792
801
|
}
|
|
@@ -795,7 +804,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
|
|
|
795
804
|
this._strafe(0);
|
|
796
805
|
if (this.playerController.isGrounded && performance.now() > this._jumpRetryDebounceAt) {
|
|
797
806
|
input.sp = true;
|
|
798
|
-
this._jumpRetryDebounceAt = performance.now() +
|
|
807
|
+
this._jumpRetryDebounceAt = performance.now() + 550;
|
|
799
808
|
}
|
|
800
809
|
}
|
|
801
810
|
|
|
@@ -806,7 +815,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
|
|
|
806
815
|
const now = performance.now();
|
|
807
816
|
if (now > this._strafeSwitchAt) {
|
|
808
817
|
this._strafeDirection = this._strafeDirection === 1 ? -1 : 1;
|
|
809
|
-
this._strafeSwitchAt = now +
|
|
818
|
+
this._strafeSwitchAt = now + 1500 + Math.random() * 1200;
|
|
810
819
|
}
|
|
811
820
|
|
|
812
821
|
const input = this.player.input as PlayerInput;
|
|
@@ -816,7 +825,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
|
|
|
816
825
|
input.a = true;
|
|
817
826
|
}
|
|
818
827
|
|
|
819
|
-
if (deltaTimeMs > 0 && Math.random() < 0.
|
|
828
|
+
if (deltaTimeMs > 0 && Math.random() < 0.008 && this.playerController.isGrounded) {
|
|
820
829
|
input.sp = true;
|
|
821
830
|
}
|
|
822
831
|
}
|
|
@@ -942,7 +951,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
|
|
|
942
951
|
const now = performance.now();
|
|
943
952
|
if (now > this._jumpRetryDebounceAt && this.playerController.isGrounded) {
|
|
944
953
|
(this.player.input as PlayerInput).sp = true;
|
|
945
|
-
this._jumpRetryDebounceAt = now +
|
|
954
|
+
this._jumpRetryDebounceAt = now + 550;
|
|
946
955
|
}
|
|
947
956
|
|
|
948
957
|
if (!this._blockBreakTarget) {
|
|
@@ -1058,7 +1067,7 @@ export default class BotPlayerEntity extends GamePlayerEntity {
|
|
|
1058
1067
|
|
|
1059
1068
|
this.applyImpulse(impulse);
|
|
1060
1069
|
(this.player.input as PlayerInput).sp = true;
|
|
1061
|
-
this._jumpRetryDebounceAt = performance.now() +
|
|
1070
|
+
this._jumpRetryDebounceAt = performance.now() + 520;
|
|
1062
1071
|
|
|
1063
1072
|
if (this._behaviorState === BotBehaviorState.LOOT) {
|
|
1064
1073
|
this._targetLootEntity = undefined;
|