VRY-UI Comprehensive Update — Change Log
1. Constants Audit (src/constants.py)
- Added
"valaram": "All Random One Site"togamemodesdict - Updated
AGENTCOLORLISTRGB values for: breach, brimstone, cypher, chamber, raze, sage, sova, neon, viper, yoru, gekko, vyse, iso, clove; added veto, waylay, miks - Fixed typo
"As 3"→"Asc 3"inNUMBERTORANKS - Added
"Bandit"toWEAPONSlist (after "Ghost") - Added to
DEFAULT_CONFIG["flags"]:"short_ranks": false,"truncate_skins": true,"truncate_names": true
2. API Sync Summary
src/requestsV.py
- Local fetch: replaced infinite
while Truewith bounded retry (max_retries=15,timeout=5,time.sleep(5)on failure) - Avoids infinite hang when VALORANT is not running
src/presences.py
get_presence(): returns[]onNoneresponse instead of crashingget_game_state(): handles bothmatchPresenceData(current nested API) and flatsessionLoopState(deprecated fallback)get_private_presence(): filters out League of Legends presences; returnsNoneon empty private field or decode error
src/rpc.py
- Added
close()method: safely closes Discord RPC connection; was called bymain.pyandwebsocket.pybut not implemented
src/rank.py
- Initialises
r = {}beforetryblock, eliminatingNameErrorin exception branches - All post-try
raccesses use safe.get()chaining "N/a"→"N/A"for consistency- WR calculation uses safe intermediate variable; handles
ZeroDivisionErrorfor 0-game seasons
src/player_stats.py
- Full rewrite:
match_details_cachedict caches/match-detailsper match_id for the runtime session (avoids duplicate fetches when multiple players share a match) clear_runtime_cache(): called on MENUS state transition_default_stats(): single source of"N/A"defaults_process_match_data(): all dict access via.get()with defaults
src/colors.py
get_rgb_color_from_skin(): wrapped in try/except; safe.get()forcontentTierUuidget_agent_from_uuid(): usesagent_dict.get(agentUUID, "Unknown")"N/a"→"N/A"in both gradient functions
3. Incognito Name Resolution (src/names.py)
When VALORANT returns an empty GameName (player in streamer/incognito mode), the client falls back to scraping https://vtl.lol/id/{puuid}:
- 3 second timeout;
User-Agentheader to avoid bot-block - Parses
<title>tag: strips site suffix (| vtl.lol,– vtl.lol) - Validates candidate: must contain
#and be longer than 2 characters - Per-session cache (
_incognito_cache) with 1-hour TTL; storesNonefor failed lookups to prevent retry storms clear_incognito_cache(): called on MENUS transition- Fallback display (
main.py): when name is empty (vtl.lol also failed), the Name cell shows the agent name in italic gray instead of a confusing blank; when vtl.lol resolved the name and privacy is off, shows the real name prefixed with*
4. Performance Delta
PlayerStats.match_details_cache: prevents O(n) duplicate/match-detailsfetches per lobbyRank.requestMap: already present — now also cleared on MENUS transition alongside player_cachepstats.clear_runtime_cache()+namesClass.clear_incognito_cache()wired into MENUS state transition inVRYWorkerThread._wait_for_state_change()VRYTableWidget.setSortingEnabled(False)during inserts prevents re-sort overhead- Allies-first player ordering in INGAME: avoids relying on API order
5. New UI Features (main.py)
Table Enhancements
- K/D color coding:
<0.8dark red ·0.8–1.2light gray ·≥1.2green ·≥2.0gold - HS% color coding:
<20%dark red ·20–30%yellow ·≥30%green - WR% color coding:
<45%dark red ·45–55%light gray ·>55%green - Leaderboard:
#Nprefix, goldQColor(255,215,0); empty string when0 - Row background tinting: ally rows
QColor(0,60,20,50)(green) · enemy rowsQColor(80,0,0,50)(red) - Self-row bold:
QFont.Weight.Boldon all cells of the local player's row - Team separator: 4px gray row inserted before the first enemy row in INGAME
Right-click Context Menu
- Copy Name (if available)
- Copy PUUID
- Open on vtl.lol (opens/creates VTL tab, navigates to
https://vtl.lol/id/{puuid}) - Open on tracker.gg (only shown when
Name#Tagformat available) - PUUID stored in
Qt.ItemDataRole.UserRoleon column 0 for lookup
Keyboard Shortcuts
Ctrl+F— toggle Freeze TableCtrl+R— Refresh DataCtrl+T— Cycle themeCtrl+,— Open SettingsCtrl+Q— Exit
Settings Dialog (File → Settings...)
- Weapon selector (QComboBox from WEAPONS list)
- Cooldown spinner
- WebSocket port spinner (restart warning label)
- Feature flags grid (8 checkboxes)
- Table columns grid (10 checkboxes)
- Writes directly to
config.jsonon Save
Compact Mode (View → Compact Mode)
- Row height 18px (compact) vs 30px (normal)
- State persisted in QSettings; restored on launch
Animated Polling Dot
- Green
●blinks at 1Hz while worker is running - Stops blinking (dim) when table is frozen
Status Pill
- Rounded pill label with
border-radius: 6px - Shows "Waiting for VALORANT..." while initial presence is pending
- Includes ⚔/🛡 indicator for starting side in PREGAME
Console Tab Improvements
- Verbosity selector (Quiet / Normal / Debug) — live-updates
worker.verbose_level - "Clear" and "Copy All" buttons
- 1000-line rolling buffer (oldest lines removed automatically)
- Auto-scroll follows new output; pauses when user scrolls up; resumes at bottom
Worker Watchdog
- QTimer checks every 30s; if no
status_signalfor >120s while worker isrunning, logs a warning to the console and resets the timer
Window Position Persistence
saveGeometry()/restoreGeometry()via QSettings on close/open
6. Breaking Changes
None. Config schema is additive: new flags.short_ranks, flags.truncate_skins, flags.truncate_names keys default to sensible values if absent.
7. Known Limitations
- vtl.lol scraping: depends on vtl.lol's HTML structure remaining stable. If the site changes its
<title>format, resolution will silently fail and names will fall back to the agent-name display. - match_details_cache: cleared only on MENUS transition, not on process restart. If the user closes and re-opens mid-game the cache starts empty.
- Compact mode QSettings: restored correctly on launch but the menu checkmark state is not reflected until the user opens the View menu.
- QWebEngineView / vtl.lol tab: some enterprise or locked-down machines may block WebEngine from loading external URLs; the tab will show a blank page.