Skip to content

Commit bc35598

Browse files
author
web3blind
committed
Fix quest limit and mobile tray UX
1 parent edf3218 commit bc35598

11 files changed

Lines changed: 95 additions & 36 deletions

File tree

app/css/main.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,3 +1817,13 @@ body,
18171817
color: var(--color-text-muted);
18181818
font-size: 0.85rem;
18191819
}
1820+
1821+
1822+
.quest-limit-note {
1823+
margin: var(--space-sm) 0;
1824+
padding: var(--space-sm);
1825+
border: 1px solid var(--color-border);
1826+
border-radius: var(--radius-sm);
1827+
background: var(--color-surface-2);
1828+
color: var(--color-text-muted);
1829+
}

app/index.html

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<link rel="icon" type="image/png" sizes="192x192" href="assets/icons/viz-magic-192.png?v=20260712c">
1414
<link rel="icon" type="image/png" sizes="512x512" href="assets/icons/viz-magic-512.png?v=20260712c">
1515
<link rel="apple-touch-icon" href="assets/icons/viz-magic-192.png?v=20260712c">
16-
<link rel="stylesheet" href="css/main.css?v=20260712i">
16+
<link rel="stylesheet" href="css/main.css?v=20260712j">
1717
<link rel="stylesheet" href="css/themes.css">
1818
<link rel="stylesheet" href="css/accessibility.css">
1919
</head>
@@ -120,8 +120,8 @@
120120
<script src="js/config.js?v=20260712a"></script>
121121

122122
<!-- I18n -->
123-
<script src="js/i18n/ru.js?v=20260712j"></script>
124-
<script src="js/i18n/en.js?v=20260712j"></script>
123+
<script src="js/i18n/ru.js?v=20260712k"></script>
124+
<script src="js/i18n/en.js?v=20260712k"></script>
125125

126126
<!-- Utilities -->
127127
<script src="js/utils/helpers.js?v=20260621l"></script>
@@ -165,7 +165,7 @@
165165
<script src="js/engine/marketplace.js"></script>
166166
<script src="js/engine/checkpoint.js"></script>
167167
<script src="js/engine/block-processor.js"></script>
168-
<script src="js/engine/world-events.js?v=20260712g"></script>
168+
<script src="js/engine/world-events.js?v=20260712h"></script>
169169
<script src="js/engine/world-boss.js"></script>
170170
<script src="js/engine/quest-system.js?v=20260621e"></script>
171171
<script src="js/engine/loci.js"></script>
@@ -186,7 +186,7 @@
186186
<script src="js/ui/screens/landing.js"></script>
187187
<script src="js/ui/screens/login.js?v=20260711a"></script>
188188
<script src="js/ui/screens/onboarding.js"></script>
189-
<script src="js/ui/screens/home.js?v=20260712g"></script>
189+
<script src="js/ui/screens/home.js?v=20260712h"></script>
190190
<script src="js/ui/screens/character.js?v=20260621l"></script>
191191
<script src="js/ui/screens/hunt.js"></script>
192192
<script src="js/ui/screens/inventory.js?v=20260621l"></script>
@@ -197,11 +197,11 @@
197197
<script src="js/ui/screens/map.js?v=20260621h"></script>
198198
<script src="js/ui/screens/marketplace.js?v=20260621k"></script>
199199
<script src="js/ui/screens/crafting.js?v=20260621j"></script>
200-
<script src="js/ui/screens/quests.js?v=20260621n"></script>
200+
<script src="js/ui/screens/quests.js?v=20260712a"></script>
201201
<script src="js/ui/screens/world-boss.js"></script>
202202
<script src="js/ui/screens/settings.js?v=20260712b"></script>
203203
<script src="js/ui/screens/help.js?v=20260712a"></script>
204-
<script src="js/ui/screens/leaderboard.js"></script>
204+
<script src="js/ui/screens/leaderboard.js?v=20260712c"></script>
205205
<script src="js/ui/screens/temple.js?v=20260712c"></script>
206206

207207
<!-- Main App Controller (must be last) -->

app/js/engine/world-events.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ var WorldEvents = (function() {
118118
},
119119
{
120120
id: 'mirror_fog',
121-
icon: '\uD83E\uDE9E',
121+
icon: '\uD83C\uDF2B\uFE0F',
122122
summaryKey: 'weather_mirror_fog',
123123
effectKey: 'weather_mirror_fog_effect',
124124
creatureAttackMod: 1000,

app/js/i18n/en.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,10 @@ var LangEN = {
886886
quest_none_available: 'No available quests.',
887887
quest_none_completed: 'No completed quests.',
888888
quest_login_required: 'Enter the World to view quests.',
889+
quest_active_count: 'Active quests: {count} of {max}. If the limit is full, complete or abandon a quest before accepting a new prophecy.',
890+
quest_limit_reached_short: 'Quest limit reached: no more than five quests at once.',
891+
quest_limit_reached_daily: 'You cannot accept the prophecy now: you already have five active quests. Complete or abandon one quest first.',
892+
quest_limit_reached_toast: 'No more than five quests at once. Complete or abandon one quest first.',
889893
quest_accept: 'Accept',
890894
quest_accepted: 'Quest accepted!',
891895
quest_already_accepted: 'Already accepted',

app/js/i18n/ru.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,10 @@ var LangRU = {
886886
quest_none_available: 'Нет доступных заданий.',
887887
quest_none_completed: 'Нет выполненных заданий.',
888888
quest_login_required: 'Войдите в Мир для просмотра заданий.',
889+
quest_active_count: 'Активных заданий: {count} из {max}. Если лимит заполнен, выполни или откажись от задания, чтобы принять новое пророчество.',
890+
quest_limit_reached_short: 'Лимит заданий заполнен: не больше пяти заданий в одни руки.',
891+
quest_limit_reached_daily: 'Сейчас нельзя принять пророчество: у тебя уже пять активных заданий. Выполни или откажись от одного задания — и пророчество станет доступно.',
892+
quest_limit_reached_toast: 'Не больше пяти заданий в одни руки. Выполни или откажись от одного задания.',
889893
quest_accept: 'Принять',
890894
quest_accepted: 'Задание принято!',
891895
quest_already_accepted: 'Уже принято',

app/js/ui/components/nav.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ var NavComponent = (function() {
2020
{ id: 'crafting', icon: '\uD83D\uDD28', label: t('nav_crafting') },
2121
{ id: 'character', icon: '🧙', label: t('nav_character') },
2222
{ id: 'temple', icon: '\u26EA', label: t('nav_temple') },
23-
{ id: 'help', icon: '❓', label: t('nav_help') },
2423
{ id: 'leaderboard', icon: '\uD83C\uDFC6', label: t('nav_leaderboard') }
2524
];
2625

app/js/ui/screens/home.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ var HomeScreen = (function() {
4242
'<h1>' + t('home_welcome') + ', ' + Helpers.escapeHtml(character.name) + '</h1>' +
4343
'<p>' + Helpers.classIcon(character.className) + ' ' + t('class_' + character.className) +
4444
' \u2022 ' + t('home_level') + ' ' + character.level + '</p>' +
45-
ProgressBar.create({id:'hp-bar', label:'HP', value:character.hp, max:character.maxHp, displayValue:hpShown, displayMax:HOME_HP_DISPLAY_MAX, color:'#e53935'}) +
46-
ProgressBar.create({id:'xp-bar', label:'XP', value:xpCurrent, max:xpNeeded, displayValue:xpShown, displayMax:HOME_XP_DISPLAY_MAX, color:'#ffc107'}) +
45+
ProgressBar.create({id:'hp-bar', label:'HP', value:character.hp, max:character.maxHp, displayValue:hpShown, displayMax:HOME_HP_DISPLAY_MAX, color:'#e53935'}) +
46+
ProgressBar.create({id:'xp-bar', label:'XP', value:xpCurrent, max:xpNeeded, displayValue:xpShown, displayMax:HOME_XP_DISPLAY_MAX, color:'#ffc107'}) +
4747
ProgressBar.create({id:'mana-bar', label:'⚡ ' + t('home_mana'), value:0, max:100, color:'#2196f3'}) +
4848
'<button class="help-tip-btn" aria-label="' + t('help_tip_mana') + '" ' +
4949
'title="' + t('help_tip_mana') + '" ' +

app/js/ui/screens/leaderboard.js

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,9 @@ var LeaderboardScreen = (function() {
4747
}
4848
}
4949

50-
if (typeof BattleNarrator !== 'undefined' && BattleNarrator.isEnabled()) {
51-
if (myRank > 0) {
52-
BattleNarrator.announce(
53-
t('narrator_leaderboard_rank', { rank: myRank, total: rows.length }),
54-
'polite'
55-
);
56-
} else if (rows.length > 0) {
57-
BattleNarrator.announce(t('leaderboard_not_ranked'), 'polite');
58-
}
59-
}
50+
// Keep BattleNarrator combat-only. Leaderboard rank is shown in the page
51+
// itself; speaking it through speechSynthesis caused repeated/stuck audio
52+
// on some mobile screen-reader/browser combinations.
6053

6154
var rankBanner = '';
6255
if (myRank > 0) {

app/js/ui/screens/quests.js

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,10 @@ var QuestsScreen = (function() {
9191
return '<div class="empty-state">' + t('quest_no_active') + '</div>';
9292
}
9393

94-
var html = '<ul class="quest-list" role="list">';
94+
var limit = QuestSystem.MAX_ACTIVE_QUESTS || 5;
95+
var html = '<p class="quest-limit-note" role="status">' +
96+
t('quest_active_count', { count: quests.length, max: limit }) + '</p>' +
97+
'<ul class="quest-list" role="list">';
9598
for (var i = 0; i < quests.length; i++) {
9699
html += _renderQuestCard(quests[i], t, true);
97100
}
@@ -107,7 +110,7 @@ var QuestsScreen = (function() {
107110

108111
var html = '<ul class="quest-list" role="list">';
109112
for (var i = 0; i < quests.length; i++) {
110-
html += _renderAvailableCard(quests[i], t);
113+
html += _renderAvailableCard(quests[i], t, playerQuests);
111114
}
112115
html += '</ul>';
113116
return html;
@@ -157,9 +160,14 @@ var QuestsScreen = (function() {
157160
}
158161
}
159162

160-
if (!isAccepted) {
163+
var limit = QuestSystem.MAX_ACTIVE_QUESTS || 5;
164+
var isFull = (playerQuests.active || []).length >= limit;
165+
if (!isAccepted && !isFull) {
161166
html += '<button class="btn btn-primary btn-glow quest-accept-btn" data-quest-id="' + prophecy.id + '" data-daily="true">' +
162167
t('quest_accept') + '</button>';
168+
} else if (!isAccepted && isFull) {
169+
html += '<p class="quest-limit-note" role="status">' + t('quest_limit_reached_daily') + '</p>' +
170+
'<button class="btn btn-primary btn-glow" disabled aria-disabled="true">' + t('quest_accept') + '</button>';
163171
} else {
164172
html += '<p class="quest-accepted-label">\u2714 ' + t('quest_already_accepted') + '</p>';
165173
}
@@ -236,7 +244,7 @@ var QuestsScreen = (function() {
236244
return html;
237245
}
238246

239-
function _renderAvailableCard(quest, t) {
247+
function _renderAvailableCard(quest, t, playerQuests) {
240248
var html = '<li class="quest-card quest-available" role="listitem">';
241249
html += '<div class="quest-card-header">';
242250
html += '<span class="quest-type-badge">' + t('quest_type_' + quest.type) + '</span>';
@@ -264,8 +272,15 @@ var QuestsScreen = (function() {
264272
}
265273
}
266274

267-
html += '<button class="btn btn-primary btn-sm quest-accept-btn" data-quest-id="' + quest.id + '">' +
268-
t('quest_accept') + '</button>';
275+
var limit = QuestSystem.MAX_ACTIVE_QUESTS || 5;
276+
var isFull = playerQuests && playerQuests.active && playerQuests.active.length >= limit;
277+
if (isFull) {
278+
html += '<p class="quest-limit-note" role="status">' + t('quest_limit_reached_short') + '</p>' +
279+
'<button class="btn btn-primary btn-sm" disabled aria-disabled="true">' + t('quest_accept') + '</button>';
280+
} else {
281+
html += '<button class="btn btn-primary btn-sm quest-accept-btn" data-quest-id="' + quest.id + '">' +
282+
t('quest_accept') + '</button>';
283+
}
269284
html += '</li>';
270285
return html;
271286
}
@@ -286,6 +301,12 @@ var QuestsScreen = (function() {
286301
}
287302

288303
if (questData) {
304+
var limit = QuestSystem.MAX_ACTIVE_QUESTS || 5;
305+
if ((playerQuests.active || []).length >= limit) {
306+
Toast.info(Helpers.t('quest_limit_reached_toast'));
307+
render();
308+
return;
309+
}
289310
_broadcastQuestAction('accept', questId, isDaily, blockNum);
290311
}
291312
});
@@ -321,6 +342,16 @@ var QuestsScreen = (function() {
321342
data.daily_block = dailyBlock || 0;
322343
}
323344

345+
if (kind === 'accept') {
346+
var state = StateEngine.getState();
347+
var userForLimit = VizAccount.getCurrentUser();
348+
var active = state.quests && state.quests[userForLimit] && state.quests[userForLimit].active ? state.quests[userForLimit].active : [];
349+
if (active.length >= (QuestSystem.MAX_ACTIVE_QUESTS || 5)) {
350+
Toast.info(Helpers.t('quest_limit_reached_toast'));
351+
return;
352+
}
353+
}
354+
324355
VizBroadcast.questAction(type, data, function(err, result) {
325356
if (err) {
326357
Toast.error(Helpers.t('error_network'));
@@ -343,7 +374,11 @@ var QuestsScreen = (function() {
343374
}
344375

345376
if (!event) {
346-
Toast.error(Helpers.t('error_network'));
377+
if (kind === 'accept') {
378+
Toast.info(Helpers.t('quest_limit_reached_toast'));
379+
} else {
380+
Toast.error(Helpers.t('error_network'));
381+
}
347382
return;
348383
}
349384

app/sw.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Viz Magic — Service Worker
2-
var CACHE_NAME = 'viz-magic-v43';
2+
var CACHE_NAME = 'viz-magic-v44';
33
var ASSETS = [
44
'/',
55
'/index.html',

0 commit comments

Comments
 (0)