x0
x0
LOGISTICS DOCTRINE
COOLDOWN • 0s
FORTIFY
Durability doctrine for hard sectors. • Stabilize frontline ships during contact. • Protect shields while repositioning.
SWITCH COOLDOWN
01
50
SYSTEMS
STATS
No selection
Select an actor, enemy, or solar object.
CHIPS 0/0
ENERGY
FLEET
00
SYSTEMS
No selection
Click a ship, enemy, or object.
function _ivGrantReward_IntelArchive(sx, sy){ try{ if (typeof spawnLootPickup !== "function") return false; // 2 rare chips, no duplicates when possible const rareKinds = [ "chip_rapid_reload_rare", "chip_wing_restoration_rare", "chip_point_defense_rare", "chip_barrage_rare", "chip_afterburn_rare", "chip_flux_tuning_rare", "chip_phase_rare", "chip_guard_link_rare", "chip_hypercoil_rare", "chip_salvage_matrix_rare" ]; const pool = rareKinds.slice(); for (let i = 0; i < 2; i++){ let kind = null; if (pool.length){ const idx = (Math.random() * pool.length) | 0; kind = pool.splice(idx, 1)[0]; } const ang = (i / 2) * Math.PI * 2; try{ spawnLootPickup("chip", 1, sx + Math.cos(ang) * 0.18, sy + Math.sin(ang) * 0.18, true, kind); }catch(_){ try{ spawnLootPickup("chip", 1, sx, sy, true, kind); }catch(__){} } } return true; }catch(_){} return false; } function _ivGrantReward_AdvancedDepot(sx, sy){ try{ if (typeof spawnLootPickup !== "function") return false; // Stronger outcomes only: // - 55% T2 module (Absorption or Missile Depot) // - 45% Level 3 core module bundle if (Math.random() < 0.55){ const t2Kinds = ["absorption_module", "missile_depot"]; const k = t2Kinds[(Math.random() * t2Kinds.length) | 0]; try{ spawnLootPickup(k, 1, sx, sy); return true; }catch(_){} } const lvl3Kinds = [ "damage_module", "shield_module", "armor_module", "repair_module", "shield_generator", "reactor_module" ]; const k = lvl3Kinds[(Math.random() * lvl3Kinds.length) | 0]; // qty=3 so it materially reads as a level-3 style reward in this game's module economy try{ spawnLootPickup(k, 3, sx, sy); return true; }catch(_){} }catch(_){} return false; } /* index2003_6: always-on battle overlay diagnostic - Ignores Navigator state entirely - Visible in battle grid view only - Draws fixed corner label + giant mothership marker */ const navigatorDebugFxCanvas = document.createElement("canvas"); navigatorDebugFxCanvas.id = "navigatorDebugFxCanvas"; navigatorDebugFxCanvas.style.position = "fixed"; navigatorDebugFxCanvas.style.left = "0"; navigatorDebugFxCanvas.style.top = "0"; navigatorDebugFxCanvas.style.width = "100vw"; navigatorDebugFxCanvas.style.height = "100vh"; navigatorDebugFxCanvas.style.pointerEvents = "none"; navigatorDebugFxCanvas.style.zIndex = "99999"; navigatorDebugFxCanvas.style.background = "transparent"; try{ document.body.appendChild(navigatorDebugFxCanvas); }catch(_){ } function _navigatorDebugStandaloneGetTarget(){ try{ if (typeof isSolarView !== "undefined" && isSolarView) return null; const moth = ((typeof actors !== "undefined" && actors && typeof playerMothershipId !== "undefined" && playerMothershipId) ? actors.get(playerMothershipId) : null); if (!moth) return null; if (Number.isFinite(moth.row) && Number.isFinite(moth.col) && typeof actorCenterPx === "function"){ const sr = Math.max(1, Number(moth.spanRows || 1)); const sc = Math.max(1, Number(moth.spanCols || 1)); const c = actorCenterPx(Number(moth.row)||0, Number(moth.col)||0, sr, sc); if (c && Number.isFinite(c.x) && Number.isFinite(c.y)) return { actor:moth, x:c.x, y:c.y, source:'grid' }; } if (moth.mesh && typeof worldToScreen === "function"){ const p = worldToScreen(moth.mesh.position); if (p && Number.isFinite(p.x) && Number.isFinite(p.y)) return { actor:moth, x:p.x, y:p.y, source:'mesh' }; } }catch(_){ } return null; } function _navigatorDebugStandaloneDraw(now){ try{ const cv = navigatorDebugFxCanvas; if (!cv) return; const dpr = window.devicePixelRatio || 1; const wantW = Math.max(1, Math.round(window.innerWidth * dpr)); const wantH = Math.max(1, Math.round(window.innerHeight * dpr)); if (cv.width !== wantW || cv.height !== wantH){ cv.width = wantW; cv.height = wantH; } const ctx = cv.getContext('2d'); if (!ctx) return; ctx.setTransform(1,0,0,1,0,0); ctx.clearRect(0,0,cv.width,cv.height); const battleOnly = !(typeof isSolarView !== "undefined" && isSolarView); if (!battleOnly) return; const tgt = _navigatorDebugStandaloneGetTarget(); // fixed corner label proves the overlay itself is visible ctx.save(); ctx.fillStyle = 'rgba(0,0,0,0.78)'; ctx.fillRect(18*dpr, 18*dpr, 390*dpr, 110*dpr); ctx.strokeStyle = 'rgba(56,189,248,1.0)'; ctx.lineWidth = 3*dpr; ctx.strokeRect(18*dpr, 18*dpr, 390*dpr, 110*dpr); ctx.fillStyle = 'rgba(186,230,253,1.0)'; ctx.textAlign = 'left'; ctx.textBaseline = 'top'; ctx.font = `${Math.max(22, Math.round(22*dpr))}px sans-serif`; ctx.fillText('BATTLE DEBUG OVERLAY ACTIVE', 34*dpr, 34*dpr); ctx.font = `${Math.max(16, Math.round(16*dpr))}px sans-serif`; ctx.fillText(`solar=${(typeof isSolarView !== "undefined" && isSolarView) ? 'yes' : 'no'} target=${tgt ? 'yes' : 'no'} src=${tgt ? tgt.source : 'none'}`, 34*dpr, 72*dpr); ctx.restore(); if (!tgt) return; const actor = tgt.actor || null; const span = Math.max(1, Number((actor && Math.max(actor.spanRows||1, actor.spanCols||1)) || 2)); const baseCell = (typeof cellSize === 'number' && cellSize > 0) ? cellSize : 40; const ox = tgt.x * dpr; const oy = tgt.y * dpr; const R = Math.max(120, baseCell * (2.8 + span * 1.0)) * dpr; const rot = (now * 0.001) % (Math.PI * 2); ctx.save(); ctx.globalCompositeOperation = 'source-over'; const g = ctx.createRadialGradient(ox, oy, R*0.04, ox, oy, R); g.addColorStop(0.00, 'rgba(56,189,248,0.42)'); g.addColorStop(0.50, 'rgba(56,189,248,0.18)'); g.addColorStop(1.00, 'rgba(56,189,248,0.00)'); ctx.fillStyle = g; ctx.beginPath(); ctx.arc(ox, oy, R, 0, Math.PI*2); ctx.fill(); ctx.strokeStyle = 'rgba(56,189,248,1.0)'; ctx.lineWidth = Math.max(8, 10*dpr); ctx.beginPath(); ctx.arc(ox, oy, R*0.92, 0, Math.PI*2); ctx.stroke(); ctx.strokeStyle = 'rgba(186,230,253,1.0)'; ctx.lineWidth = Math.max(4, 5*dpr); ctx.beginPath(); ctx.arc(ox, oy, R*0.64, 0, Math.PI*2); ctx.stroke(); ctx.save(); ctx.translate(ox, oy); ctx.rotate(rot); ctx.strokeStyle = 'rgba(56,189,248,0.98)'; ctx.lineWidth = Math.max(4, 5*dpr); ctx.beginPath(); ctx.moveTo(-R*1.02, 0); ctx.lineTo(R*1.02, 0); ctx.moveTo(0, -R*1.02); ctx.lineTo(0, R*1.02); ctx.stroke(); ctx.restore(); ctx.fillStyle = 'rgba(255,255,255,0.98)'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.font = `${Math.max(28, Math.round(28*dpr))}px sans-serif`; ctx.fillText('MOTHERSHIP', ox, oy); ctx.restore(); }catch(_){ } } function _navigatorDebugStandaloneTick(now){ try{ _navigatorDebugStandaloneDraw(now || ((performance && performance.now) ? performance.now() : Date.now())); }catch(_){ } try{ window.requestAnimationFrame(_navigatorDebugStandaloneTick); }catch(_){ } } try{ window.requestAnimationFrame(_navigatorDebugStandaloneTick); }catch(_){ } /* index2003_11: late-bound battle DOM diagnostic using real live hooks */ (function(){ function ensureLateDebugUi(){ let panel = document.getElementById('vvBattleDomDebugPanel_late'); if(!panel){ panel = document.createElement('div'); panel.id = 'vvBattleDomDebugPanel_late'; panel.style.cssText = 'position:fixed;left:16px;top:220px;z-index:2147483647;background:rgba(0,0,0,0.88);color:#86efac;border:2px solid #22c55e;padding:10px 12px;font:900 16px/1.35 Arial,sans-serif;white-space:pre-line;pointer-events:none;border-radius:12px;box-shadow:0 8px 24px rgba(0,0,0,0.6)'; panel.textContent = 'LATE BATTLE DOM DEBUG\nbooting...'; document.body.appendChild(panel); } let marker = document.getElementById('vvBattleDomMarker_late'); if(!marker){ marker = document.createElement('div'); marker.id = 'vvBattleDomMarker_late'; marker.style.cssText = 'position:fixed;left:-9999px;top:-9999px;width:140px;height:140px;transform:translate(-50%,-50%);border:8px solid rgba(34,197,94,0.98);border-radius:9999px;box-shadow:0 0 24px rgba(34,197,94,0.8), inset 0 0 24px rgba(34,197,94,0.25);pointer-events:none;z-index:2147483647;background:rgba(34,197,94,0.08)'; let label = document.createElement('div'); label.textContent = 'LATE'; label.style.cssText = 'position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);color:white;font:900 24px/1 Arial,sans-serif;text-shadow:0 2px 8px #000'; marker.appendChild(label); document.body.appendChild(marker); } return {panel, marker}; } function startLateDebug(){ const ui = ensureLateDebugUi(); const panel = ui.panel, marker = ui.marker; function txt(s){ panel.textContent = s; } function hide(){ marker.style.left='-9999px'; marker.style.top='-9999px'; } function tick(){ try{ const haveSolar = (typeof isSolarView !== 'undefined'); const battle = haveSolar ? (!isSolarView) : 'undef'; const haveNavFn = (typeof _relayNavigatorPackageActive === 'function'); const nav = haveNavFn ? !!(typeof _relayHumanNavigatorPackageActive === "function" ? _relayHumanNavigatorPackageActive() : (_relayNavigatorPackageActive() && _relayActivePackageVariantId() === "human")) : 'no fn'; let moth = null; if (typeof getMothershipActor === 'function') moth = getMothershipActor(); if (!moth && typeof actors !== 'undefined' && actors && typeof actors.get === 'function') moth = actors.get('mothership') || null; const found = !!moth; const mesh = !!(moth && moth.mesh); const row = (moth && Number.isFinite(moth.row)) ? moth.row : 'n/a'; const col = (moth && Number.isFinite(moth.col)) ? moth.col : 'n/a'; let sx = 'n/a', sy = 'n/a', anchor = 'none'; if (battle === true && moth && typeof worldToScreenOnBoard === 'function'){ try{ const x = (moth.mesh && moth.mesh.position) ? Number(moth.mesh.position.x||0) : 0; const y = (moth.mesh && moth.mesh.position) ? Number(moth.mesh.position.y||0) : 0; const p = worldToScreenOnBoard(x, y); if (p && Number.isFinite(p.x) && Number.isFinite(p.y)){ sx = Math.round(p.x); sy = Math.round(p.y); anchor = 'worldToScreenOnBoard'; marker.style.left = sx + 'px'; marker.style.top = sy + 'px'; } else hide(); }catch(_){ hide(); } } else { hide(); } txt(`LATE BATTLE DOM DEBUG\nhave isSolarView: ${haveSolar}\nbattle: ${battle}\nhave nav fn: ${haveNavFn}\nnavigator active: ${nav}\nmothership found: ${found}\nmesh found: ${mesh}\nrow,col: ${row},${col}\nscreen: ${sx},${sy}\nanchor: ${anchor}`); }catch(err){ txt(`LATE BATTLE DOM DEBUG\nERROR\n${err && err.message ? err.message : String(err)}`); hide(); } requestAnimationFrame(tick); } requestAnimationFrame(tick); } let __lateDebugStarted = false; function bootLateDebug(){ if (__lateDebugStarted) return; __lateDebugStarted = true; setTimeout(startLateDebug, 1200); } if (document.readyState === 'complete' || document.readyState === 'interactive') { bootLateDebug(); } else { document.addEventListener('DOMContentLoaded', bootLateDebug, {once:true}); window.addEventListener('load', bootLateDebug, {once:true}); } /* Prevent achievement/intel/logo images from being natively draggable so drag gestures continue scrolling the surrounding menu panels instead of dragging the PNG off-page. */ (function setupNonDraggableMenuImages(){ const NO_DRAG_SELECTOR = 'img.mvvLogo, img.mvvAchIcon, img.vvMajorAchIcon, img.vvAchUnlockIcon, img.mvvIntelGlyphImg'; function applyNoDrag(root){ try{ const scope = (root && root.querySelectorAll) ? root : document; scope.querySelectorAll(NO_DRAG_SELECTOR).forEach((img)=>{ try{ img.setAttribute('draggable', 'false'); }catch(_){ } try{ img.draggable = false; }catch(_){ } }); }catch(_){ } } applyNoDrag(document); document.addEventListener('dragstart', (ev)=>{ const t = ev && ev.target; if (t && t.matches && t.matches(NO_DRAG_SELECTOR)) { ev.preventDefault(); } }, true); try{ const mo = new MutationObserver((mutations)=>{ for (const m of mutations){ if (!m || !m.addedNodes) continue; for (const node of m.addedNodes){ if (node && node.nodeType === 1) applyNoDrag(node); } } }); mo.observe(document.documentElement || document.body, { childList:true, subtree:true }); }catch(_){ } })(); setTimeout(bootLateDebug, 1800); })();