@hytopia.com/examples 1.0.17 → 1.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/frontiers-rpg-game/assets/icons/buttons/e-mobile.png +0 -0
- package/frontiers-rpg-game/assets/icons/buttons/jump.png +0 -0
- package/frontiers-rpg-game/assets/ui/hud.html +336 -137
- package/frontiers-rpg-game/assets/ui/index.html +1089 -491
- package/frontiers-rpg-game/assets/ui/menus/backpack.html +121 -52
- package/frontiers-rpg-game/assets/ui/menus/crafting.html +63 -41
- package/frontiers-rpg-game/assets/ui/menus/dialogue.html +53 -75
- package/frontiers-rpg-game/assets/ui/menus/merchant.html +117 -123
- package/frontiers-rpg-game/assets/ui/menus/quests.html +151 -28
- package/frontiers-rpg-game/assets/ui/menus/skills.html +123 -30
- package/frontiers-rpg-game/assets/ui/shared/item-tooltips.html +125 -5
- package/frontiers-rpg-game/src/GameManager.ts +1 -1
- package/frontiers-rpg-game/src/GamePlayer.ts +6 -4
- package/frontiers-rpg-game/src/GameRegion.ts +4 -10
- package/frontiers-rpg-game/src/entities/BaseCombatEntity.ts +1 -1
- package/package.json +1 -1
- package/frontiers-rpg-game/dev/persistence/player-player-1.json +0 -103
|
@@ -77,6 +77,9 @@
|
|
|
77
77
|
function closeSkills() {
|
|
78
78
|
document.querySelector('.skills-overlay').style.display = 'none';
|
|
79
79
|
hytopia.lockPointer(true);
|
|
80
|
+
|
|
81
|
+
// Close any open mobile tooltips
|
|
82
|
+
closeAllMobileTooltips();
|
|
80
83
|
}
|
|
81
84
|
|
|
82
85
|
// Update Functions
|
|
@@ -107,6 +110,9 @@
|
|
|
107
110
|
const skillItem = createSkillItem(skill);
|
|
108
111
|
skillsGrid.appendChild(skillItem);
|
|
109
112
|
});
|
|
113
|
+
|
|
114
|
+
// Close any open mobile tooltips after updating skills
|
|
115
|
+
closeAllMobileTooltips();
|
|
110
116
|
}
|
|
111
117
|
|
|
112
118
|
function updateSkillsExp(data) {
|
|
@@ -174,6 +180,54 @@
|
|
|
174
180
|
// Event Listeners
|
|
175
181
|
function setupEventListeners() {
|
|
176
182
|
document.querySelector('.skills-close').addEventListener('click', closeSkills);
|
|
183
|
+
|
|
184
|
+
// Setup mobile tooltip handling
|
|
185
|
+
setupMobileTooltips();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Mobile tooltip handling
|
|
189
|
+
function setupMobileTooltips() {
|
|
190
|
+
// Check if we're on mobile
|
|
191
|
+
const isMobile = document.body.classList.contains('mobile');
|
|
192
|
+
if (!isMobile) return;
|
|
193
|
+
|
|
194
|
+
// Add click handler to skills container for event delegation
|
|
195
|
+
document.querySelector('.skills-skills-grid').addEventListener('click', handleMobileTooltipClick);
|
|
196
|
+
|
|
197
|
+
// Add click handler to document to close tooltips when clicking outside
|
|
198
|
+
document.addEventListener('click', handleDocumentClick);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function handleMobileTooltipClick(e) {
|
|
202
|
+
const skillItem = e.target.closest('.skills-skill-item');
|
|
203
|
+
if (!skillItem) return;
|
|
204
|
+
|
|
205
|
+
e.stopPropagation();
|
|
206
|
+
|
|
207
|
+
const tooltip = skillItem.querySelector('.skills-skill-tooltip');
|
|
208
|
+
if (!tooltip) return;
|
|
209
|
+
|
|
210
|
+
// Close any other open tooltips
|
|
211
|
+
closeAllMobileTooltips();
|
|
212
|
+
|
|
213
|
+
// Toggle this tooltip
|
|
214
|
+
tooltip.classList.add('skills-mobile-tooltip-visible');
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function handleDocumentClick(e) {
|
|
218
|
+
// Close tooltips when clicking outside
|
|
219
|
+
if (!e.target.closest('.skills-skill-item')) {
|
|
220
|
+
closeAllMobileTooltips();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function closeAllMobileTooltips() {
|
|
225
|
+
const visibleTooltips = document.querySelectorAll('.skills-mobile-tooltip-visible');
|
|
226
|
+
if (visibleTooltips.length > 0) {
|
|
227
|
+
visibleTooltips.forEach(tooltip => {
|
|
228
|
+
tooltip.classList.remove('skills-mobile-tooltip-visible');
|
|
229
|
+
});
|
|
230
|
+
}
|
|
177
231
|
}
|
|
178
232
|
|
|
179
233
|
// Initialize
|
|
@@ -490,96 +544,135 @@
|
|
|
490
544
|
/* Mobile Styles */
|
|
491
545
|
body.mobile .skills-container {
|
|
492
546
|
width: auto;
|
|
493
|
-
max-width:
|
|
494
|
-
min-width:
|
|
547
|
+
max-width: 680px;
|
|
548
|
+
min-width: 475px;
|
|
549
|
+
border-radius: 8px;
|
|
495
550
|
}
|
|
496
551
|
|
|
497
552
|
body.mobile .skills-header {
|
|
498
|
-
padding:
|
|
553
|
+
padding: 8px 12px;
|
|
554
|
+
border-radius: 8px 8px 0 0;
|
|
499
555
|
}
|
|
500
556
|
|
|
501
557
|
body.mobile .skills-title {
|
|
502
|
-
font-size:
|
|
558
|
+
font-size: 14px;
|
|
503
559
|
}
|
|
504
560
|
|
|
505
561
|
body.mobile .skills-close {
|
|
506
|
-
width:
|
|
507
|
-
height:
|
|
508
|
-
font-size:
|
|
562
|
+
width: 24px;
|
|
563
|
+
height: 24px;
|
|
564
|
+
font-size: 16px;
|
|
565
|
+
border-radius: 6px;
|
|
509
566
|
}
|
|
510
567
|
|
|
511
568
|
body.mobile .skills-content {
|
|
512
|
-
padding:
|
|
569
|
+
padding: 12px;
|
|
513
570
|
}
|
|
514
571
|
|
|
515
572
|
body.mobile .skills-player-section,
|
|
516
573
|
body.mobile .skills-skills-section {
|
|
517
|
-
|
|
518
|
-
|
|
574
|
+
padding: 10px;
|
|
575
|
+
border-radius: 6px;
|
|
519
576
|
}
|
|
520
577
|
|
|
521
578
|
body.mobile .skills-section-title {
|
|
522
|
-
font-size:
|
|
523
|
-
margin-bottom:
|
|
579
|
+
font-size: 12px;
|
|
580
|
+
margin-bottom: 8px;
|
|
524
581
|
}
|
|
525
582
|
|
|
526
583
|
body.mobile .skills-level-display {
|
|
527
|
-
margin-bottom:
|
|
584
|
+
margin-bottom: 8px;
|
|
528
585
|
}
|
|
529
586
|
|
|
530
587
|
body.mobile .skills-level-number {
|
|
531
|
-
font-size:
|
|
588
|
+
font-size: 16px;
|
|
532
589
|
}
|
|
533
590
|
|
|
534
591
|
body.mobile .skills-exp-bar {
|
|
535
|
-
height:
|
|
592
|
+
height: 16px;
|
|
593
|
+
border-radius: 6px;
|
|
536
594
|
}
|
|
537
595
|
|
|
538
596
|
body.mobile .skills-exp-text {
|
|
539
|
-
font-size:
|
|
597
|
+
font-size: 10px;
|
|
540
598
|
}
|
|
541
599
|
|
|
542
600
|
body.mobile .skills-skills-grid {
|
|
543
|
-
grid-template-columns: 1fr 1fr;
|
|
544
|
-
gap:
|
|
601
|
+
grid-template-columns: 1fr 1fr 1fr;
|
|
602
|
+
gap: 6px;
|
|
545
603
|
}
|
|
546
604
|
|
|
547
605
|
body.mobile .skills-skill-item {
|
|
548
|
-
gap:
|
|
549
|
-
padding:
|
|
606
|
+
gap: 6px;
|
|
607
|
+
padding: 4px 8px;
|
|
608
|
+
border-radius: 6px;
|
|
609
|
+
min-height: 40px;
|
|
610
|
+
cursor: pointer;
|
|
611
|
+
-webkit-tap-highlight-color: rgba(255, 255, 255, 0.1);
|
|
550
612
|
}
|
|
551
613
|
|
|
552
614
|
body.mobile .skills-skill-icon {
|
|
553
615
|
width: 28px;
|
|
554
616
|
height: 28px;
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
body.mobile .skills-skill-icon-img {
|
|
558
|
-
width: 100%;
|
|
559
|
-
height: 100%;
|
|
617
|
+
border-radius: 6px;
|
|
560
618
|
}
|
|
561
619
|
|
|
562
620
|
body.mobile .skills-skill-header {
|
|
563
|
-
margin-bottom:
|
|
621
|
+
margin-bottom: 4px;
|
|
564
622
|
}
|
|
565
623
|
|
|
566
624
|
body.mobile .skills-skill-name {
|
|
567
|
-
font-size:
|
|
625
|
+
font-size: 10px;
|
|
626
|
+
overflow: hidden;
|
|
627
|
+
text-overflow: ellipsis;
|
|
628
|
+
white-space: nowrap;
|
|
568
629
|
}
|
|
569
630
|
|
|
570
631
|
body.mobile .skills-skill-level {
|
|
571
|
-
font-size:
|
|
632
|
+
font-size: 9px;
|
|
633
|
+
flex-shrink: 0;
|
|
572
634
|
}
|
|
573
635
|
|
|
574
636
|
body.mobile .skills-skill-exp-bar {
|
|
575
637
|
height: 10px;
|
|
638
|
+
border-radius: 6px;
|
|
576
639
|
}
|
|
577
640
|
|
|
578
641
|
body.mobile .skills-skill-exp-text {
|
|
579
|
-
font-size:
|
|
642
|
+
font-size: 7px;
|
|
580
643
|
}
|
|
581
644
|
|
|
582
645
|
body.mobile .skills-skill-tooltip {
|
|
583
|
-
|
|
646
|
+
opacity: 0;
|
|
647
|
+
visibility: hidden;
|
|
648
|
+
transform: translateY(-4px);
|
|
649
|
+
transition: all 0.2s ease;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
body.mobile .skills-mobile-tooltip-visible {
|
|
653
|
+
opacity: 1 !important;
|
|
654
|
+
visibility: visible !important;
|
|
655
|
+
transform: translateY(-8px) !important;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
body.mobile .skills-skill-tooltip-content {
|
|
659
|
+
max-width: 180px;
|
|
660
|
+
font-size: 10px;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/* Center the caret on mobile */
|
|
664
|
+
body.mobile .skills-skill-tooltip-content::after {
|
|
665
|
+
left: 50% !important;
|
|
666
|
+
transform: translateX(-50%) !important;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
body.mobile .skills-skill-tooltip-content::before {
|
|
670
|
+
left: 50% !important;
|
|
671
|
+
transform: translateX(-50%) !important;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/* Enable scrolling if needed */
|
|
675
|
+
body.mobile .skills-content * {
|
|
676
|
+
touch-action: pan-y !important;
|
|
584
677
|
}
|
|
585
678
|
</style>
|
|
@@ -123,12 +123,75 @@ window.ItemTooltips = (function() {
|
|
|
123
123
|
if (existingTooltip) existingTooltip.remove();
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
// Mobile tooltip handling
|
|
127
|
+
let mobileTooltipActive = false;
|
|
128
|
+
|
|
129
|
+
function initializeMobileTooltips() {
|
|
130
|
+
// Check if we're on mobile
|
|
131
|
+
const isMobile = document.body.classList.contains('mobile');
|
|
132
|
+
if (!isMobile) return;
|
|
133
|
+
|
|
134
|
+
// Add click handler to document for event delegation
|
|
135
|
+
document.addEventListener('click', handleMobileTooltipClick, true);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function handleMobileTooltipClick(e) {
|
|
139
|
+
// List of tooltip container selectors - include quest reward enabled class
|
|
140
|
+
const tooltipContainers = [
|
|
141
|
+
'.backpack-slot', '.backpack-hotbar-slot', '.backpack-wearable-slot',
|
|
142
|
+
'.hud-hotbar-slot', '.merchant-slot', '.merchant-hotbar-slot',
|
|
143
|
+
'.crafting-slot', '.crafting-requirement-item',
|
|
144
|
+
'.quests-reward-item', '.quests-reward-item-tooltip-enabled'
|
|
145
|
+
];
|
|
146
|
+
|
|
147
|
+
// Check if click is on a tooltip container
|
|
148
|
+
const container = e.target.closest(tooltipContainers.join(', '));
|
|
149
|
+
|
|
150
|
+
if (container) {
|
|
151
|
+
// Find tooltip in this container
|
|
152
|
+
const tooltip = container.querySelector([
|
|
153
|
+
'.item-tooltip', '.backpack-item-tooltip', '.merchant-item-tooltip',
|
|
154
|
+
'.crafting-item-tooltip', '.crafting-requirement-tooltip', '.quests-reward-item-tooltip'
|
|
155
|
+
].join(', '));
|
|
156
|
+
|
|
157
|
+
if (tooltip) {
|
|
158
|
+
// Close any other open tooltips
|
|
159
|
+
closeAllMobileTooltips();
|
|
160
|
+
|
|
161
|
+
// Show this tooltip
|
|
162
|
+
tooltip.classList.add('mobile-tooltip-visible');
|
|
163
|
+
mobileTooltipActive = true;
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
// Click outside any container - close all tooltips
|
|
167
|
+
closeAllMobileTooltips();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function closeAllMobileTooltips() {
|
|
172
|
+
const visibleTooltips = document.querySelectorAll('.mobile-tooltip-visible');
|
|
173
|
+
if (visibleTooltips.length > 0) {
|
|
174
|
+
visibleTooltips.forEach(tooltip => {
|
|
175
|
+
tooltip.classList.remove('mobile-tooltip-visible');
|
|
176
|
+
});
|
|
177
|
+
mobileTooltipActive = false;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Initialize mobile tooltips when DOM is ready
|
|
182
|
+
if (document.readyState === 'loading') {
|
|
183
|
+
document.addEventListener('DOMContentLoaded', initializeMobileTooltips);
|
|
184
|
+
} else {
|
|
185
|
+
initializeMobileTooltips();
|
|
186
|
+
}
|
|
187
|
+
|
|
126
188
|
// Public API
|
|
127
189
|
return {
|
|
128
190
|
parseText: parseText,
|
|
129
191
|
hasTooltipData: hasTooltipData,
|
|
130
192
|
createTooltip: createTooltip,
|
|
131
|
-
removeTooltip: removeTooltip
|
|
193
|
+
removeTooltip: removeTooltip,
|
|
194
|
+
closeAllMobileTooltips: closeAllMobileTooltips
|
|
132
195
|
};
|
|
133
196
|
})();
|
|
134
197
|
</script>
|
|
@@ -156,8 +219,7 @@ window.ItemTooltips = (function() {
|
|
|
156
219
|
.merchant-hotbar-slot:hover .item-tooltip,
|
|
157
220
|
.crafting-slot:hover .item-tooltip,
|
|
158
221
|
.crafting-requirement-item:hover .item-tooltip,
|
|
159
|
-
|
|
160
|
-
/* Tooltip visibility on hover - Specific classes */
|
|
222
|
+
|
|
161
223
|
.backpack-slot:hover .backpack-item-tooltip,
|
|
162
224
|
.backpack-hotbar-slot:hover .backpack-item-tooltip,
|
|
163
225
|
.backpack-wearable-slot:hover .backpack-item-tooltip,
|
|
@@ -281,14 +343,72 @@ window.ItemTooltips = (function() {
|
|
|
281
343
|
font-size: 11px;
|
|
282
344
|
}
|
|
283
345
|
|
|
284
|
-
/* Mobile -
|
|
346
|
+
/* Mobile - Control tooltip visibility on mobile devices */
|
|
285
347
|
body.mobile .item-tooltip,
|
|
286
348
|
body.mobile .backpack-item-tooltip,
|
|
287
349
|
body.mobile .merchant-item-tooltip,
|
|
288
350
|
body.mobile .crafting-item-tooltip,
|
|
289
351
|
body.mobile .crafting-requirement-tooltip,
|
|
290
352
|
body.mobile .quests-reward-item-tooltip {
|
|
291
|
-
|
|
353
|
+
opacity: 0;
|
|
354
|
+
visibility: hidden;
|
|
355
|
+
transform: translateY(-4px);
|
|
356
|
+
transition: all 0.2s ease;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/* Mobile tooltip visibility when tapped */
|
|
360
|
+
body.mobile .mobile-tooltip-visible {
|
|
361
|
+
opacity: 1 !important;
|
|
362
|
+
visibility: visible !important;
|
|
363
|
+
transform: translateY(-8px) !important;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* Improve mobile tooltip positioning and touch targets */
|
|
367
|
+
body.mobile .backpack-slot,
|
|
368
|
+
body.mobile .backpack-hotbar-slot,
|
|
369
|
+
body.mobile .backpack-wearable-slot,
|
|
370
|
+
body.mobile .hud-hotbar-slot,
|
|
371
|
+
body.mobile .merchant-slot,
|
|
372
|
+
body.mobile .merchant-hotbar-slot,
|
|
373
|
+
body.mobile .crafting-slot,
|
|
374
|
+
body.mobile .crafting-requirement-item,
|
|
375
|
+
body.mobile .quests-reward-item,
|
|
376
|
+
body.mobile .quests-reward-item-tooltip-enabled {
|
|
377
|
+
cursor: pointer;
|
|
378
|
+
-webkit-tap-highlight-color: rgba(255, 255, 255, 0.1);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/* Center carets on mobile tooltips */
|
|
382
|
+
body.mobile .item-tooltip-content::after,
|
|
383
|
+
body.mobile .backpack-item-tooltip-content::after,
|
|
384
|
+
body.mobile .merchant-item-tooltip-content::after,
|
|
385
|
+
body.mobile .crafting-item-tooltip-content::after,
|
|
386
|
+
body.mobile .crafting-requirement-tooltip-content::after,
|
|
387
|
+
body.mobile .quests-reward-item-tooltip-content::after {
|
|
388
|
+
left: 50% !important;
|
|
389
|
+
transform: translateX(-50%) !important;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
body.mobile .item-tooltip-content::before,
|
|
393
|
+
body.mobile .backpack-item-tooltip-content::before,
|
|
394
|
+
body.mobile .merchant-item-tooltip-content::before,
|
|
395
|
+
body.mobile .crafting-item-tooltip-content::before,
|
|
396
|
+
body.mobile .crafting-requirement-tooltip-content::before,
|
|
397
|
+
body.mobile .quests-reward-item-tooltip-content::before {
|
|
398
|
+
left: 50% !important;
|
|
399
|
+
transform: translateX(-50%) !important;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/* Mobile tooltip content sizing */
|
|
403
|
+
body.mobile .item-tooltip-content,
|
|
404
|
+
body.mobile .backpack-item-tooltip-content,
|
|
405
|
+
body.mobile .merchant-item-tooltip-content,
|
|
406
|
+
body.mobile .crafting-item-tooltip-content,
|
|
407
|
+
body.mobile .crafting-requirement-tooltip-content,
|
|
408
|
+
body.mobile .quests-reward-item-tooltip-content {
|
|
409
|
+
max-width: 220px;
|
|
410
|
+
font-size: 11px;
|
|
411
|
+
padding: 8px 10px;
|
|
292
412
|
}
|
|
293
413
|
|
|
294
414
|
/* Mouse Follower Tooltip (for backpack drag system) */
|
|
@@ -77,7 +77,7 @@ export default class GameManager {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
private _selectWorldForPlayer = async (player: Player): Promise<World | undefined> => {
|
|
80
|
-
const gamePlayer =
|
|
80
|
+
const gamePlayer = GamePlayer.getOrCreate(player);
|
|
81
81
|
return gamePlayer.currentRegion?.world ?? this._startRegion.world;
|
|
82
82
|
}
|
|
83
83
|
}
|
|
@@ -88,13 +88,15 @@ export default class GamePlayer {
|
|
|
88
88
|
this.hotbar.onSelectedItemChanged = this._onHotbarSelectedItemChanged;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
public static
|
|
91
|
+
public static getOrCreate(player: Player): GamePlayer {
|
|
92
92
|
let gamePlayer = this._instances.get(player.id);
|
|
93
|
+
|
|
93
94
|
if (!gamePlayer) {
|
|
94
95
|
gamePlayer = new GamePlayer(player);
|
|
95
|
-
|
|
96
|
+
gamePlayer.load();
|
|
96
97
|
this._instances.set(player.id, gamePlayer);
|
|
97
98
|
}
|
|
99
|
+
|
|
98
100
|
return gamePlayer;
|
|
99
101
|
}
|
|
100
102
|
|
|
@@ -342,8 +344,8 @@ export default class GamePlayer {
|
|
|
342
344
|
this.player.joinWorld(region.world);
|
|
343
345
|
}
|
|
344
346
|
|
|
345
|
-
public
|
|
346
|
-
const serializedGamePlayerData =
|
|
347
|
+
public load(): void {
|
|
348
|
+
const serializedGamePlayerData = this.player.getPersistedData();
|
|
347
349
|
|
|
348
350
|
if (serializedGamePlayerData) { // Existing player, load their state
|
|
349
351
|
this._loadFromSerializedData(serializedGamePlayerData as SerializedGamePlayerData);
|
|
@@ -140,9 +140,8 @@ export default class GameRegion {
|
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
protected
|
|
144
|
-
|
|
145
|
-
const gamePlayer = await GamePlayer.getOrCreate(player);
|
|
143
|
+
protected onPlayerJoin(player: Player) {
|
|
144
|
+
const gamePlayer = GamePlayer.getOrCreate(player);
|
|
146
145
|
|
|
147
146
|
// Set the current region for the player
|
|
148
147
|
gamePlayer.setCurrentRegion(this);
|
|
@@ -153,11 +152,6 @@ export default class GameRegion {
|
|
|
153
152
|
const gamePlayerEntity = new GamePlayerEntity(gamePlayer);
|
|
154
153
|
|
|
155
154
|
gamePlayerEntity.spawn(this._world, spawnPoint, Quaternion.fromEuler(0, spawnFacingAngle, 0));
|
|
156
|
-
|
|
157
|
-
// Since we're using an async onPlayerJoin, we need to explicitly set the camera
|
|
158
|
-
// since the camera attachment logic as of SDK 0.6.7 only checks for an entity
|
|
159
|
-
// the first tick after a player joins a world in order to auto attach the camera.
|
|
160
|
-
player.camera.setAttachedToEntity(gamePlayerEntity);
|
|
161
155
|
|
|
162
156
|
// Make the camera look at the correct spawn facing angle.
|
|
163
157
|
// Calculate look direction based on facing angle (identity direction is -z, consistent with threejs)
|
|
@@ -200,8 +194,8 @@ export default class GameRegion {
|
|
|
200
194
|
// The HYTOPIA SDK handles resynchronization of all persisted state back to the player client such as
|
|
201
195
|
// their entity, scene ui states, etc, but anything that uses ephemeral state (Such as UI) we need
|
|
202
196
|
// to handle reloading for them manually here.
|
|
203
|
-
protected
|
|
204
|
-
const gamePlayer =
|
|
197
|
+
protected onPlayerReconnected(player: Player) {
|
|
198
|
+
const gamePlayer = GamePlayer.getOrCreate(player);
|
|
205
199
|
gamePlayer.onPlayerReconnected();
|
|
206
200
|
}
|
|
207
201
|
}
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
|
|
16
16
|
const MOVEMENT_NOT_STUCK_DISTANCE_SQUARED = 3;
|
|
17
17
|
const COMBAT_REGEN_DEFAULT_DELAY_MS = 7000; // 7 seconds
|
|
18
|
-
const COMBAT_REGEN_DEFAULT_RATE = 0.
|
|
18
|
+
const COMBAT_REGEN_DEFAULT_RATE = 0.05; // 5% per interval
|
|
19
19
|
const COMBAT_REGEN_INTERVAL_MS = 3000; // 3 seconds
|
|
20
20
|
|
|
21
21
|
import BaseEntity, { BaseEntityOptions } from './BaseEntity';
|
package/package.json
CHANGED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"health": 120,
|
|
3
|
-
"currentRegionId": "chitter-forest",
|
|
4
|
-
"skillExperience": [
|
|
5
|
-
[
|
|
6
|
-
"exploration",
|
|
7
|
-
225
|
|
8
|
-
],
|
|
9
|
-
[
|
|
10
|
-
"combat",
|
|
11
|
-
162
|
|
12
|
-
],
|
|
13
|
-
[
|
|
14
|
-
"agility",
|
|
15
|
-
20
|
|
16
|
-
]
|
|
17
|
-
],
|
|
18
|
-
"backpack": {
|
|
19
|
-
"items": []
|
|
20
|
-
},
|
|
21
|
-
"hotbar": {
|
|
22
|
-
"items": [
|
|
23
|
-
{
|
|
24
|
-
"position": 0,
|
|
25
|
-
"itemId": "dull_sword"
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"position": 2,
|
|
29
|
-
"itemId": "toy_sword"
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
"position": 3,
|
|
33
|
-
"itemId": "gold",
|
|
34
|
-
"quantity": 82
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
"position": 1,
|
|
38
|
-
"itemId": "ratkin_tail"
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
"position": 4,
|
|
42
|
-
"itemId": "ratkin_tooth"
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
"position": 5,
|
|
46
|
-
"itemId": "ratkin_eyes",
|
|
47
|
-
"quantity": 3
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
"position": 6,
|
|
51
|
-
"itemId": "ratkin_bones",
|
|
52
|
-
"quantity": 3
|
|
53
|
-
}
|
|
54
|
-
]
|
|
55
|
-
},
|
|
56
|
-
"questLog": {
|
|
57
|
-
"quests": [
|
|
58
|
-
{
|
|
59
|
-
"questId": "welcome-to-stalkhaven",
|
|
60
|
-
"state": "completed",
|
|
61
|
-
"objectiveProgress": {
|
|
62
|
-
"talk-to-mark": 1
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
"questId": "exploring-stalkhaven",
|
|
67
|
-
"state": "completed",
|
|
68
|
-
"objectiveProgress": {
|
|
69
|
-
"talk-to-mycelis": 1,
|
|
70
|
-
"talk-to-finn": 1,
|
|
71
|
-
"talk-to-sporn": 1,
|
|
72
|
-
"talk-to-mark": 1
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
"questId": "tested-mettle",
|
|
77
|
-
"state": "active",
|
|
78
|
-
"objectiveProgress": {
|
|
79
|
-
"kill-5-ratkin": 5,
|
|
80
|
-
"dodge-3-times": 3,
|
|
81
|
-
"talk-to-mark": 0
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
]
|
|
85
|
-
},
|
|
86
|
-
"storage": {
|
|
87
|
-
"items": []
|
|
88
|
-
},
|
|
89
|
-
"wearables": {
|
|
90
|
-
"items": [
|
|
91
|
-
{
|
|
92
|
-
"position": 1,
|
|
93
|
-
"itemId": "adventurer_tunic"
|
|
94
|
-
}
|
|
95
|
-
]
|
|
96
|
-
},
|
|
97
|
-
"currentRegionSpawnFacingAngle": 0,
|
|
98
|
-
"currentRegionSpawnPoint": {
|
|
99
|
-
"x": -7,
|
|
100
|
-
"y": 2,
|
|
101
|
-
"z": 76
|
|
102
|
-
}
|
|
103
|
-
}
|