@hytopia.com/examples 1.0.11 → 1.0.13
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/items/leather-boots.png +0 -0
- package/frontiers-rpg-game/assets/icons/items/leather-bracers.png +0 -0
- package/frontiers-rpg-game/assets/icons/items/leather-helmet.png +0 -0
- package/frontiers-rpg-game/assets/icons/items/leather-leggings.png +0 -0
- package/frontiers-rpg-game/assets/icons/items/leather-vest.png +0 -0
- package/frontiers-rpg-game/assets/icons/items/spiked-club.png +0 -0
- package/frontiers-rpg-game/assets/icons/skills/crafting.png +0 -0
- package/frontiers-rpg-game/assets/models/weapons/.optimized/mace/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/weapons/.optimized/mace/mace-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/weapons/.optimized/mace/mace-named-nodes.gltf +653 -0
- package/frontiers-rpg-game/assets/models/weapons/.optimized/mace/mace.bin +0 -0
- package/frontiers-rpg-game/assets/models/weapons/.optimized/mace/mace.gltf +135 -0
- package/frontiers-rpg-game/assets/models/weapons/.optimized/mace/mace.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/weapons/.optimized/spiked-club/baseColor.png +0 -0
- package/frontiers-rpg-game/assets/models/weapons/.optimized/spiked-club/spiked-club-named-nodes.bin +0 -0
- package/frontiers-rpg-game/assets/models/weapons/.optimized/spiked-club/spiked-club-named-nodes.gltf +840 -0
- package/frontiers-rpg-game/assets/models/weapons/.optimized/spiked-club/spiked-club.bin +0 -0
- package/frontiers-rpg-game/assets/models/weapons/.optimized/spiked-club/spiked-club.gltf +141 -0
- package/frontiers-rpg-game/assets/models/weapons/.optimized/spiked-club/spiked-club.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/weapons/mace.gltf +1 -0
- package/frontiers-rpg-game/assets/ui/build.js +2 -0
- package/frontiers-rpg-game/assets/ui/index.html +1328 -64
- package/frontiers-rpg-game/assets/ui/menus/crafting.html +976 -0
- package/frontiers-rpg-game/assets/ui/menus/quests.html +70 -2
- package/frontiers-rpg-game/assets/ui/shared/item-stats.html +224 -0
- package/frontiers-rpg-game/assets/ui/shared/item-tooltips.html +72 -81
- package/frontiers-rpg-game/dev/persistence/player-player-1.json +121 -12
- package/frontiers-rpg-game/src/GamePlayer.ts +54 -0
- package/frontiers-rpg-game/src/GamePlayerEntity.ts +9 -4
- package/frontiers-rpg-game/src/config.ts +7 -0
- package/frontiers-rpg-game/src/entities/BaseCraftingEntity.ts +115 -0
- package/frontiers-rpg-game/src/entities/enemies/RatkinBruteEntity.ts +2 -0
- package/frontiers-rpg-game/src/entities/enemies/RatkinRangerEntity.ts +2 -0
- package/frontiers-rpg-game/src/entities/enemies/RatkinSpellcasterEntity.ts +2 -0
- package/frontiers-rpg-game/src/entities/enemies/RatkinWarriorEntity.ts +2 -0
- package/frontiers-rpg-game/src/entities/enemies/TaintedRatkinBruteEntity.ts +2 -0
- package/frontiers-rpg-game/src/entities/enemies/TaintedRatkinRangerEntity.ts +2 -1
- package/frontiers-rpg-game/src/entities/enemies/TaintedRatkinSpellcasterEntity.ts +2 -0
- package/frontiers-rpg-game/src/entities/enemies/TaintedRatkinWarriorEntity.ts +2 -0
- package/frontiers-rpg-game/src/entities/forageables/DecayingPileEntity.ts +2 -2
- package/frontiers-rpg-game/src/entities/forageables/RottenLogEntity.ts +2 -2
- package/frontiers-rpg-game/src/items/ItemClasses.ts +14 -2
- package/frontiers-rpg-game/src/items/materials/RawHideItem.ts +10 -0
- package/frontiers-rpg-game/src/items/weapons/DullSwordItem.ts +5 -4
- package/frontiers-rpg-game/src/items/weapons/IronDaggerItem.ts +1 -1
- package/frontiers-rpg-game/src/items/weapons/IronLongSwordItem.ts +5 -4
- package/frontiers-rpg-game/src/items/weapons/SpikedClubItem.ts +26 -0
- package/frontiers-rpg-game/src/items/weapons/TrainingSwordItem.ts +5 -4
- package/frontiers-rpg-game/src/items/wearables/LeatherBootsItem.ts +14 -0
- package/frontiers-rpg-game/src/items/wearables/LeatherBracersItem.ts +14 -0
- package/frontiers-rpg-game/src/items/wearables/LeatherHelmetItem.ts +14 -0
- package/frontiers-rpg-game/src/items/wearables/LeatherLeggingsItem.ts +14 -0
- package/frontiers-rpg-game/src/items/wearables/LeatherVestItem.ts +14 -0
- package/frontiers-rpg-game/src/quests/BaseQuest.ts +1 -2
- package/frontiers-rpg-game/src/quests/QuestClasses.ts +2 -0
- package/frontiers-rpg-game/src/quests/side/FungalForagingQuest.ts +1 -23
- package/frontiers-rpg-game/src/quests/side/HammersAndCraftingQuest.ts +139 -0
- package/frontiers-rpg-game/src/regions/stalkhaven/StalkhavenRegion.ts +2 -0
- package/frontiers-rpg-game/src/regions/stalkhaven/npcs/BlacksmithArdenEntity.ts +114 -0
- package/frontiers-rpg-game/src/systems/QuestLog.ts +2 -5
- package/package.json +1 -1
- package/frontiers-rpg-game/dev/persistence/player-player-2.json +0 -31
- package/frontiers-rpg-game/dev/persistence/player-player-3.json +0 -25
- package/frontiers-rpg-game/dev/persistence/player-player-4.json +0 -31
- package/frontiers-rpg-game/src/items/materials/MonsterHideItem.ts +0 -10
- /package/frontiers-rpg-game/assets/icons/items/{monster-hide.png → raw-hide.png} +0 -0
- /package/frontiers-rpg-game/assets/models/weapons/{club.gltf → spiked-club.gltf} +0 -0
|
@@ -294,6 +294,40 @@
|
|
|
294
294
|
</div>
|
|
295
295
|
</div>
|
|
296
296
|
`;
|
|
297
|
+
|
|
298
|
+
// Add tooltips to reward items after rendering
|
|
299
|
+
addRewardTooltips(quest.reward);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function addRewardTooltips(reward) {
|
|
303
|
+
// Clear any existing tooltips first
|
|
304
|
+
const existingTooltipItems = document.querySelectorAll('.quests-reward-item-tooltip-enabled');
|
|
305
|
+
existingTooltipItems.forEach(item => removeRewardTooltip(item));
|
|
306
|
+
|
|
307
|
+
// Add tooltips to item rewards
|
|
308
|
+
if (reward.items) {
|
|
309
|
+
reward.items.forEach((itemReward, index) => {
|
|
310
|
+
const rewardItem = document.querySelector(`[data-reward-item-index="${index}"]`);
|
|
311
|
+
if (rewardItem && window.ItemTooltips) {
|
|
312
|
+
createRewardTooltip(rewardItem, itemReward);
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function createRewardTooltip(item, itemData) {
|
|
319
|
+
const options = {
|
|
320
|
+
tooltipClass: 'quests-reward-item-tooltip',
|
|
321
|
+
contentClass: 'quests-reward-item-tooltip-content',
|
|
322
|
+
showBuyPrice: false,
|
|
323
|
+
showSellPrice: false
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
ItemTooltips.createTooltip(item, itemData, options);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function removeRewardTooltip(item) {
|
|
330
|
+
ItemTooltips.removeTooltip(item, 'quests-reward-item-tooltip');
|
|
297
331
|
}
|
|
298
332
|
|
|
299
333
|
function generateObjectivesHTML(quest) {
|
|
@@ -330,11 +364,11 @@
|
|
|
330
364
|
});
|
|
331
365
|
|
|
332
366
|
// Handle item rewards
|
|
333
|
-
reward.items?.forEach(itemReward => {
|
|
367
|
+
reward.items?.forEach((itemReward, index) => {
|
|
334
368
|
const quantity = itemReward.quantity > 1 ? `x${itemReward.quantity.toLocaleString()}` : 'x1';
|
|
335
369
|
const iconSrc = itemReward.iconImageUri ? `{{CDN_ASSETS_URL}}/${itemReward.iconImageUri}` : '{{CDN_ASSETS_URL}}/icons/items/gold.png';
|
|
336
370
|
rewards.push(`
|
|
337
|
-
<div class="quests-reward-item">
|
|
371
|
+
<div class="quests-reward-item quests-reward-item-tooltip-enabled" data-reward-item-index="${index}">
|
|
338
372
|
<img src="${iconSrc}" alt="Item" class="quests-reward-icon">
|
|
339
373
|
<span class="quests-reward-text">${sanitizeText(itemReward.name)} (${quantity})</span>
|
|
340
374
|
</div>
|
|
@@ -754,6 +788,40 @@
|
|
|
754
788
|
line-height: 1.3;
|
|
755
789
|
}
|
|
756
790
|
|
|
791
|
+
/* Quest reward tooltip positioning - left-aligned for full-width items */
|
|
792
|
+
.quests-reward-item-tooltip {
|
|
793
|
+
position: absolute;
|
|
794
|
+
bottom: 100%;
|
|
795
|
+
left: 0;
|
|
796
|
+
margin-bottom: 8px;
|
|
797
|
+
opacity: 0;
|
|
798
|
+
visibility: hidden;
|
|
799
|
+
transition: all 0.3s ease;
|
|
800
|
+
z-index: 2000;
|
|
801
|
+
pointer-events: none;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
.quests-reward-item-tooltip-enabled {
|
|
805
|
+
position: relative;
|
|
806
|
+
cursor: pointer;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
/* Override center positioning for quest reward tooltips */
|
|
810
|
+
.quests-reward-item-tooltip-content {
|
|
811
|
+
transform: translateX(0) !important;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/* Position caret over the reward icon */
|
|
815
|
+
.quests-reward-item-tooltip-content::after {
|
|
816
|
+
left: 20px !important;
|
|
817
|
+
transform: translateX(-50%) !important;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
.quests-reward-item-tooltip-content::before {
|
|
821
|
+
left: 20px !important;
|
|
822
|
+
transform: translateX(-50%) !important;
|
|
823
|
+
}
|
|
824
|
+
|
|
757
825
|
/* Empty State */
|
|
758
826
|
.quests-empty-state {
|
|
759
827
|
flex: 1;
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
<!-- Shared Item Stats System -->
|
|
2
|
+
<script>
|
|
3
|
+
/**
|
|
4
|
+
* Centralized Item Stats System
|
|
5
|
+
* Provides consistent stat formatting across all UI components
|
|
6
|
+
*/
|
|
7
|
+
window.ItemStats = (function() {
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
// Parse color formatting in text: [HEXCODE]text[/] -> <span style="color: #HEXCODE">text</span>
|
|
11
|
+
// Parse line breaks: [b] -> <br>
|
|
12
|
+
function parseText(text) {
|
|
13
|
+
if (!text) return text;
|
|
14
|
+
|
|
15
|
+
// First, replace [b] with <br> for line breaks
|
|
16
|
+
text = text.replace(/\[b\]/g, '<br>');
|
|
17
|
+
|
|
18
|
+
// Then, handle color formatting [HEXCODE]text[/] pattern
|
|
19
|
+
const colorPattern = /\[([A-Fa-f0-9]{6})\](.*?)\[\/\]/g;
|
|
20
|
+
|
|
21
|
+
return text.replace(colorPattern, (match, hexCode, content) => {
|
|
22
|
+
return `<span style="color: #${hexCode}">${content}</span>`;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function generateItemStats(itemData, options = {}) {
|
|
27
|
+
const config = {
|
|
28
|
+
includeDescription: true,
|
|
29
|
+
includePricing: false,
|
|
30
|
+
showBuyPrice: false,
|
|
31
|
+
showSellPrice: false,
|
|
32
|
+
buyPriceLabel: 'Price: ',
|
|
33
|
+
sellPriceLabel: 'Sells For: ',
|
|
34
|
+
notBuyableLabel: 'Not Buyable',
|
|
35
|
+
notSellableLabel: 'Not Sellable',
|
|
36
|
+
statsClass: 'item-stats',
|
|
37
|
+
descriptionClass: 'item-description',
|
|
38
|
+
priceClass: 'item-price',
|
|
39
|
+
...options
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const sections = [];
|
|
43
|
+
|
|
44
|
+
// Item stats (weapons and wearables)
|
|
45
|
+
const stats = [];
|
|
46
|
+
|
|
47
|
+
// Weapon damage (no "when equipped" needed since weapons are used directly)
|
|
48
|
+
if (itemData.damage && itemData.damage !== 0) {
|
|
49
|
+
if (itemData.damageVariance && itemData.damageVariance !== 0) {
|
|
50
|
+
const min = Math.floor(itemData.damage * (1 - itemData.damageVariance));
|
|
51
|
+
const max = Math.floor(itemData.damage * (1 + itemData.damageVariance));
|
|
52
|
+
stats.push(`${min}-${max} damage`);
|
|
53
|
+
} else {
|
|
54
|
+
stats.push(`${itemData.damage} damage`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Wearable stats
|
|
59
|
+
const wearableStats = [];
|
|
60
|
+
if (itemData.damageBonus && itemData.damageBonus !== 0) {
|
|
61
|
+
wearableStats.push(`+${itemData.damageBonus} damage dealt`);
|
|
62
|
+
}
|
|
63
|
+
if (itemData.damageBonusPercent && itemData.damageBonusPercent !== 0) {
|
|
64
|
+
wearableStats.push(`+${itemData.damageBonusPercent}% damage dealt`);
|
|
65
|
+
}
|
|
66
|
+
if (itemData.damageReduction && itemData.damageReduction !== 0) {
|
|
67
|
+
wearableStats.push(`-${itemData.damageReduction} damage taken`);
|
|
68
|
+
}
|
|
69
|
+
if (itemData.damageReductionPercent && itemData.damageReductionPercent !== 0) {
|
|
70
|
+
wearableStats.push(`-${itemData.damageReductionPercent}% damage taken`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Collect all stat lines first
|
|
74
|
+
const allStatLines = [];
|
|
75
|
+
|
|
76
|
+
// Add wearable stats
|
|
77
|
+
if (wearableStats.length > 0) {
|
|
78
|
+
allStatLines.push(...wearableStats);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Add custom stat texts
|
|
82
|
+
if (itemData.statTexts && itemData.statTexts.length > 0) {
|
|
83
|
+
for (const statText of itemData.statTexts) {
|
|
84
|
+
const parsedStatText = parseText(statText);
|
|
85
|
+
allStatLines.push(parsedStatText);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Add header and stats together if we have stats
|
|
90
|
+
if (allStatLines.length > 0) {
|
|
91
|
+
if (itemData.statsHeader) {
|
|
92
|
+
const headerText = parseText(itemData.statsHeader);
|
|
93
|
+
stats.push(`<div class="stats-header">${headerText}</div>${allStatLines.join('<br>')}`);
|
|
94
|
+
} else {
|
|
95
|
+
stats.push(allStatLines.join('<br>'));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (stats.length > 0) {
|
|
100
|
+
sections.push(`<div class="${config.statsClass}">${stats.join('<br>')}</div>`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Item description
|
|
104
|
+
if (config.includeDescription && itemData.description) {
|
|
105
|
+
const parsedDescription = parseText(itemData.description);
|
|
106
|
+
sections.push(`<div class="${config.descriptionClass}">${parsedDescription}</div>`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Price information
|
|
110
|
+
if (config.includePricing) {
|
|
111
|
+
if (config.showBuyPrice && itemData.buyPrice !== undefined) {
|
|
112
|
+
const price = itemData.buyPrice || 0;
|
|
113
|
+
if (price > 0) {
|
|
114
|
+
sections.push(`<div class="${config.priceClass}">${config.buyPriceLabel}${price.toLocaleString()} gold</div>`);
|
|
115
|
+
} else {
|
|
116
|
+
sections.push(`<div class="${config.priceClass}">${config.notBuyableLabel}</div>`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (config.showSellPrice && itemData.sellPrice !== undefined) {
|
|
121
|
+
const price = itemData.sellPrice || 0;
|
|
122
|
+
if (price > 0) {
|
|
123
|
+
sections.push(`<div class="${config.priceClass}">${config.sellPriceLabel}${price.toLocaleString()} gold</div>`);
|
|
124
|
+
} else {
|
|
125
|
+
sections.push(`<div class="${config.priceClass}">${config.notSellableLabel}</div>`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return sections.join('');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function hasItemStats(itemData) {
|
|
134
|
+
return itemData.description ||
|
|
135
|
+
itemData.sellPrice !== undefined ||
|
|
136
|
+
itemData.buyPrice !== undefined ||
|
|
137
|
+
itemData.damageBonus !== undefined ||
|
|
138
|
+
itemData.damageBonusPercent !== undefined ||
|
|
139
|
+
itemData.damageReduction !== undefined ||
|
|
140
|
+
itemData.damageReductionPercent !== undefined ||
|
|
141
|
+
itemData.damage !== undefined ||
|
|
142
|
+
itemData.damageVariance !== undefined ||
|
|
143
|
+
(itemData.statTexts && itemData.statTexts.length > 0) ||
|
|
144
|
+
itemData.statsHeader;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Public API
|
|
148
|
+
return {
|
|
149
|
+
parseText: parseText,
|
|
150
|
+
generateItemStats: generateItemStats,
|
|
151
|
+
hasItemStats: hasItemStats
|
|
152
|
+
};
|
|
153
|
+
})();
|
|
154
|
+
</script>
|
|
155
|
+
|
|
156
|
+
<style>
|
|
157
|
+
/* Shared Item Stats Styles */
|
|
158
|
+
.item-stats {
|
|
159
|
+
margin-top: 6px;
|
|
160
|
+
font-size: 11px;
|
|
161
|
+
line-height: 1.4;
|
|
162
|
+
color: #7dd87d;
|
|
163
|
+
font-weight: 500;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.stats-header {
|
|
167
|
+
color: #999999;
|
|
168
|
+
font-weight: 500;
|
|
169
|
+
margin-bottom: 3px;
|
|
170
|
+
font-size: 11px;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.item-description {
|
|
174
|
+
color: #cccccc;
|
|
175
|
+
margin-top: 6px;
|
|
176
|
+
font-size: 11px;
|
|
177
|
+
line-height: 1.4;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.item-price {
|
|
181
|
+
color: #ffd700;
|
|
182
|
+
margin-top: 6px;
|
|
183
|
+
font-weight: 500;
|
|
184
|
+
font-size: 11px;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* Crafting-specific stat styles */
|
|
188
|
+
.crafting-item-stats {
|
|
189
|
+
margin-top: 4px;
|
|
190
|
+
font-size: 9px;
|
|
191
|
+
line-height: 1.3;
|
|
192
|
+
color: #7dd87d;
|
|
193
|
+
font-weight: 500;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.crafting-item-stats .stats-header {
|
|
197
|
+
color: #999999;
|
|
198
|
+
font-weight: 500;
|
|
199
|
+
margin-bottom: 2px;
|
|
200
|
+
font-size: 9px;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.crafting-item-description {
|
|
204
|
+
margin-top: 4px;
|
|
205
|
+
font-size: 9px;
|
|
206
|
+
line-height: 1.3;
|
|
207
|
+
color: var(--crafting-text-muted, #cccccc);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/* Mobile styles */
|
|
211
|
+
body.mobile .crafting-item-stats {
|
|
212
|
+
font-size: 8px;
|
|
213
|
+
margin-top: 3px;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
body.mobile .crafting-item-stats .stats-header {
|
|
217
|
+
font-size: 8px;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
body.mobile .crafting-item-description {
|
|
221
|
+
font-size: 8px;
|
|
222
|
+
margin-top: 3px;
|
|
223
|
+
}
|
|
224
|
+
</style>
|
|
@@ -24,6 +24,12 @@ window.ItemTooltips = (function() {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
function hasTooltipData(itemData) {
|
|
27
|
+
// Use shared ItemStats system if available, otherwise use basic check
|
|
28
|
+
if (window.ItemStats) {
|
|
29
|
+
return itemData.name || window.ItemStats.hasItemStats(itemData);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Fallback check if ItemStats not available
|
|
27
33
|
return itemData.name ||
|
|
28
34
|
itemData.description ||
|
|
29
35
|
itemData.sellPrice !== undefined ||
|
|
@@ -67,71 +73,27 @@ window.ItemTooltips = (function() {
|
|
|
67
73
|
sections.push(`<div class="tooltip-name">${itemData.name}</div>`);
|
|
68
74
|
}
|
|
69
75
|
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Wearable stats
|
|
85
|
-
const wearableStats = [];
|
|
86
|
-
if (itemData.damageBonus && itemData.damageBonus !== 0) {
|
|
87
|
-
wearableStats.push(`+${itemData.damageBonus} damage dealt`);
|
|
88
|
-
}
|
|
89
|
-
if (itemData.damageBonusPercent && itemData.damageBonusPercent !== 0) {
|
|
90
|
-
wearableStats.push(`+${itemData.damageBonusPercent}% damage dealt`);
|
|
91
|
-
}
|
|
92
|
-
if (itemData.damageReduction && itemData.damageReduction !== 0) {
|
|
93
|
-
wearableStats.push(`-${itemData.damageReduction} damage taken`);
|
|
94
|
-
}
|
|
95
|
-
if (itemData.damageReductionPercent && itemData.damageReductionPercent !== 0) {
|
|
96
|
-
wearableStats.push(`-${itemData.damageReductionPercent}% damage taken`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Collect all stat lines first
|
|
100
|
-
const allStatLines = [];
|
|
101
|
-
|
|
102
|
-
// Add wearable stats
|
|
103
|
-
if (wearableStats.length > 0) {
|
|
104
|
-
allStatLines.push(...wearableStats);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Add custom stat texts
|
|
108
|
-
if (itemData.statTexts && itemData.statTexts.length > 0) {
|
|
109
|
-
for (const statText of itemData.statTexts) {
|
|
110
|
-
const parsedStatText = parseText(statText);
|
|
111
|
-
allStatLines.push(parsedStatText);
|
|
76
|
+
// Use shared ItemStats system for consistent stat generation
|
|
77
|
+
if (window.ItemStats) {
|
|
78
|
+
const itemStatsHTML = window.ItemStats.generateItemStats(itemData, {
|
|
79
|
+
includeDescription: true,
|
|
80
|
+
includePricing: false,
|
|
81
|
+
statsClass: 'tooltip-stats',
|
|
82
|
+
descriptionClass: 'tooltip-description',
|
|
83
|
+
priceClass: 'tooltip-value'
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (itemStatsHTML) {
|
|
87
|
+
sections.push(itemStatsHTML);
|
|
112
88
|
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const headerText = parseText(itemData.statsHeader);
|
|
119
|
-
stats.push(`<div class="tooltip-stats-header">${headerText}</div>${allStatLines.join('<br>')}`);
|
|
120
|
-
} else {
|
|
121
|
-
stats.push(allStatLines.join('<br>'));
|
|
89
|
+
} else {
|
|
90
|
+
// Fallback: Item description only if ItemStats not available
|
|
91
|
+
if (itemData.description) {
|
|
92
|
+
const parsedDescription = parseText(itemData.description);
|
|
93
|
+
sections.push(`<div class="tooltip-description">${parsedDescription}</div>`);
|
|
122
94
|
}
|
|
123
95
|
}
|
|
124
96
|
|
|
125
|
-
if (stats.length > 0) {
|
|
126
|
-
sections.push(`<div class="tooltip-stats">${stats.join('<br>')}</div>`);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Item description
|
|
130
|
-
if (itemData.description) {
|
|
131
|
-
const parsedDescription = parseText(itemData.description);
|
|
132
|
-
sections.push(`<div class="tooltip-description">${parsedDescription}</div>`);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
97
|
// Price information
|
|
136
98
|
if (config.showBuyPrice && itemData.buyPrice !== undefined) {
|
|
137
99
|
const price = itemData.buyPrice || 0;
|
|
@@ -189,22 +151,31 @@ window.ItemTooltips = (function() {
|
|
|
189
151
|
.backpack-slot:hover .item-tooltip,
|
|
190
152
|
.backpack-hotbar-slot:hover .item-tooltip,
|
|
191
153
|
.backpack-wearable-slot:hover .item-tooltip,
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
154
|
+
.merchant-slot:hover .item-tooltip,
|
|
155
|
+
.merchant-hotbar-slot:hover .item-tooltip,
|
|
156
|
+
.crafting-slot:hover .item-tooltip,
|
|
157
|
+
.crafting-requirement-item:hover .item-tooltip,
|
|
158
|
+
.quests-reward-item:hover .item-tooltip,
|
|
159
|
+
/* Tooltip visibility on hover - Specific classes */
|
|
160
|
+
.backpack-slot:hover .backpack-item-tooltip,
|
|
161
|
+
.backpack-hotbar-slot:hover .backpack-item-tooltip,
|
|
162
|
+
.backpack-wearable-slot:hover .backpack-item-tooltip,
|
|
163
|
+
.merchant-slot:hover .merchant-item-tooltip,
|
|
164
|
+
.merchant-hotbar-slot:hover .merchant-item-tooltip,
|
|
165
|
+
.crafting-slot:hover .crafting-item-tooltip,
|
|
166
|
+
.crafting-requirement-item:hover .crafting-requirement-tooltip,
|
|
167
|
+
.quests-reward-item:hover .quests-reward-item-tooltip {
|
|
200
168
|
opacity: 1;
|
|
201
169
|
visibility: visible;
|
|
202
170
|
transform: translateY(-8px);
|
|
203
171
|
}
|
|
204
172
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
173
|
+
.item-tooltip-content,
|
|
174
|
+
.backpack-item-tooltip-content,
|
|
175
|
+
.merchant-item-tooltip-content,
|
|
176
|
+
.crafting-item-tooltip-content,
|
|
177
|
+
.crafting-requirement-tooltip-content,
|
|
178
|
+
.quests-reward-item-tooltip-content {
|
|
208
179
|
background: linear-gradient(145deg, #2a2a2a, #1e1e1e);
|
|
209
180
|
border: 2px solid #444;
|
|
210
181
|
border-radius: 8px;
|
|
@@ -225,9 +196,12 @@ window.ItemTooltips = (function() {
|
|
|
225
196
|
}
|
|
226
197
|
|
|
227
198
|
/* Tooltip Caret */
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
199
|
+
.item-tooltip-content::after,
|
|
200
|
+
.backpack-item-tooltip-content::after,
|
|
201
|
+
.merchant-item-tooltip-content::after,
|
|
202
|
+
.crafting-item-tooltip-content::after,
|
|
203
|
+
.crafting-requirement-tooltip-content::after,
|
|
204
|
+
.quests-reward-item-tooltip-content::after {
|
|
231
205
|
content: '';
|
|
232
206
|
position: absolute;
|
|
233
207
|
top: 100%;
|
|
@@ -237,9 +211,12 @@ window.ItemTooltips = (function() {
|
|
|
237
211
|
border-top-color: #444;
|
|
238
212
|
}
|
|
239
213
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
214
|
+
.item-tooltip-content::before,
|
|
215
|
+
.backpack-item-tooltip-content::before,
|
|
216
|
+
.merchant-item-tooltip-content::before,
|
|
217
|
+
.crafting-item-tooltip-content::before,
|
|
218
|
+
.crafting-requirement-tooltip-content::before,
|
|
219
|
+
.quests-reward-item-tooltip-content::before {
|
|
243
220
|
content: '';
|
|
244
221
|
position: absolute;
|
|
245
222
|
top: calc(100% - 2px);
|
|
@@ -247,8 +224,17 @@ window.ItemTooltips = (function() {
|
|
|
247
224
|
transform: translateX(-50%);
|
|
248
225
|
border: 6px solid transparent;
|
|
249
226
|
border-top-color: #2a2a2a;
|
|
250
|
-
|
|
251
|
-
|
|
227
|
+
z-index: 1;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/* Tooltip Content Sections */
|
|
231
|
+
.tooltip-name,
|
|
232
|
+
.backpack-tooltip-name,
|
|
233
|
+
.merchant-tooltip-name {
|
|
234
|
+
font-weight: 600;
|
|
235
|
+
color: #ffffff;
|
|
236
|
+
font-size: 12px;
|
|
237
|
+
}
|
|
252
238
|
|
|
253
239
|
/* Tooltip Content Sections */
|
|
254
240
|
.tooltip-name,
|
|
@@ -295,7 +281,12 @@ window.ItemTooltips = (function() {
|
|
|
295
281
|
}
|
|
296
282
|
|
|
297
283
|
/* Mobile - Hide tooltips on mobile devices */
|
|
298
|
-
body.mobile .item-tooltip
|
|
284
|
+
body.mobile .item-tooltip,
|
|
285
|
+
body.mobile .backpack-item-tooltip,
|
|
286
|
+
body.mobile .merchant-item-tooltip,
|
|
287
|
+
body.mobile .crafting-item-tooltip,
|
|
288
|
+
body.mobile .crafting-requirement-tooltip,
|
|
289
|
+
body.mobile .quests-reward-item-tooltip {
|
|
299
290
|
display: none;
|
|
300
291
|
}
|
|
301
292
|
|
|
@@ -1,31 +1,140 @@
|
|
|
1
1
|
{
|
|
2
|
-
"health":
|
|
3
|
-
"currentRegionId": "stalkhaven
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
"health": 130,
|
|
3
|
+
"currentRegionId": "stalkhaven",
|
|
4
|
+
"skillExperience": [
|
|
5
|
+
[
|
|
6
|
+
"exploration",
|
|
7
|
+
375
|
|
8
|
+
],
|
|
9
|
+
[
|
|
10
|
+
"agility",
|
|
11
|
+
79
|
|
12
|
+
],
|
|
13
|
+
[
|
|
14
|
+
"combat",
|
|
15
|
+
320
|
|
16
|
+
],
|
|
17
|
+
[
|
|
18
|
+
"foraging",
|
|
19
|
+
8
|
|
20
|
+
]
|
|
21
|
+
],
|
|
11
22
|
"backpack": {
|
|
12
|
-
"items": [
|
|
23
|
+
"items": [
|
|
24
|
+
{
|
|
25
|
+
"position": 0,
|
|
26
|
+
"itemId": "common_mushroom",
|
|
27
|
+
"quantity": 3
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"position": 1,
|
|
31
|
+
"itemId": "ratkin_tooth",
|
|
32
|
+
"quantity": 3
|
|
33
|
+
}
|
|
34
|
+
]
|
|
13
35
|
},
|
|
14
36
|
"hotbar": {
|
|
15
37
|
"items": [
|
|
16
38
|
{
|
|
17
39
|
"position": 0,
|
|
40
|
+
"itemId": "dull_sword"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"position": 2,
|
|
18
44
|
"itemId": "toy_sword"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"position": 3,
|
|
48
|
+
"itemId": "gold",
|
|
49
|
+
"quantity": 147
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"position": 1,
|
|
53
|
+
"itemId": "raw_hide",
|
|
54
|
+
"quantity": 2
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"position": 4,
|
|
58
|
+
"itemId": "ratkin_eyes"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"position": 5,
|
|
62
|
+
"itemId": "ratkin_tail",
|
|
63
|
+
"quantity": 2
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"position": 6,
|
|
67
|
+
"itemId": "ratkin_bones",
|
|
68
|
+
"quantity": 3
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"position": 7,
|
|
72
|
+
"itemId": "common_seeds",
|
|
73
|
+
"quantity": 4
|
|
19
74
|
}
|
|
20
75
|
]
|
|
21
76
|
},
|
|
22
77
|
"questLog": {
|
|
23
|
-
"quests": [
|
|
78
|
+
"quests": [
|
|
79
|
+
{
|
|
80
|
+
"questId": "welcome-to-stalkhaven",
|
|
81
|
+
"state": "completed",
|
|
82
|
+
"objectiveProgress": {
|
|
83
|
+
"talk-to-mark": 1
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"questId": "exploring-stalkhaven",
|
|
88
|
+
"state": "completed",
|
|
89
|
+
"objectiveProgress": {
|
|
90
|
+
"talk-to-mycelis": 1,
|
|
91
|
+
"talk-to-finn": 1,
|
|
92
|
+
"talk-to-sporn": 1,
|
|
93
|
+
"talk-to-mark": 1
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"questId": "tested-mettle",
|
|
98
|
+
"state": "completed",
|
|
99
|
+
"objectiveProgress": {
|
|
100
|
+
"kill-5-ratkin": 5,
|
|
101
|
+
"dodge-3-times": 3,
|
|
102
|
+
"talk-to-mark": 1
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"questId": "hammers-and-crafting",
|
|
107
|
+
"state": "active",
|
|
108
|
+
"objectiveProgress": {
|
|
109
|
+
"gather-materials": 2,
|
|
110
|
+
"craft-item": 0,
|
|
111
|
+
"talk-to-arden": 0
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"questId": "stalkhavens-outpost",
|
|
116
|
+
"state": "active",
|
|
117
|
+
"objectiveProgress": {
|
|
118
|
+
"talk-to-chanterelion": 0
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
]
|
|
24
122
|
},
|
|
25
123
|
"storage": {
|
|
26
124
|
"items": []
|
|
27
125
|
},
|
|
28
126
|
"wearables": {
|
|
29
|
-
"items": [
|
|
127
|
+
"items": [
|
|
128
|
+
{
|
|
129
|
+
"position": 1,
|
|
130
|
+
"itemId": "adventurer_tunic"
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
"currentRegionSpawnFacingAngle": 0,
|
|
135
|
+
"currentRegionSpawnPoint": {
|
|
136
|
+
"x": 1,
|
|
137
|
+
"y": 2,
|
|
138
|
+
"z": 40
|
|
30
139
|
}
|
|
31
140
|
}
|