Setup your own virtual shooting range
Where the competition requires overpriced custom hardware, Interactive Gun Range is designed to work withΒ affordable hardware you can buy easily. Through our affiliate program, we offer pre-tested high-quality hardware through the Amazon affiliate program, tested by the developers personally, to ensure the best chance of compatibility. Or try out what you already have. If it works, let us know!
Get Started
After ordering what you need, download the software.
System
Gun
Display
document.addEventListener('DOMContentLoaded', function() {
// π Grab all 4 accordion sections
const systemSection = document.querySelector('#accordion-system');
const gunSection = document.querySelector('#accordion-gun');
const displaySection = document.querySelector('#accordion-display');
const hardwareSection = document.querySelector('#accordion-hardware');
// π― Grab title text + store start content
const systemTitle = systemSection.querySelector('.e-n-accordion-item-title-text');
const systemTitleStartContent = systemTitle.textContent.trim();
const gunTitle = gunSection.querySelector('.e-n-accordion-item-title-text');
const gunTitleStartContent = gunTitle.textContent.trim();
const displayTitle = displaySection.querySelector('.e-n-accordion-item-title-text');
const displayTitleStartContent = displayTitle.textContent.trim();
// βοΈ Store user picks
let system = '';
let gun = '';
let display = '';
// π Close Gun, Display, Hardware by default
[gunSection, displaySection, hardwareSection].forEach(sec => sec.removeAttribute('open'));
// π Stop users opening sections out of order
document.querySelectorAll('.e-n-accordion-item-title').forEach(title => {
title.addEventListener('click', e => {
const parent = title.closest('.e-n-accordion-item');
if (!parent.classList.contains('selected') && !parent.classList.contains('section-open')) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
}
}, true);
});
// β
Reset helpers
const resetVisibility = () => {
document.querySelectorAll('.hardware-option').forEach(opt => opt.style.display = '');
document.querySelectorAll('.gun-option').forEach(opt => opt.style.display = '');
};
const hideItems = (selector, items) => {
items.forEach(name => {
const el = document.querySelector(`${selector}[data-val='"${name}"']`);
if (el) el.style.display = 'none';
});
};
const deselect = (section) => {
section.classList.remove('selected');
section.removeAttribute('open');
section.querySelectorAll('.accordion-item-selected').forEach(opt => opt.classList.remove('accordion-item-selected'));
};
const resetTabTitle = (section) => {
if (section === systemSection) systemTitle.textContent = systemTitleStartContent;
if (section === gunSection) gunTitle.textContent = gunTitleStartContent;
if (section === displaySection) displayTitle.textContent = displayTitleStartContent;
if (section === hardwareSection) ; // no title to reset here
};
const resetTabValue = (section) => {
if (section === systemSection) system = '';
if (section === gunSection) gun = '';
if (section === displaySection) display = '';
};
systemSection.querySelector('.e-n-accordion-item-title')?.addEventListener('click', () => {
if (!systemSection.classList.contains('selected')) return;
document.querySelectorAll('.accordion-item-selected').forEach(opt => opt.classList.remove('accordion-item-selected'));
document.querySelectorAll('.e-n-accordion-item').forEach(opt => (opt.classList.remove('selected')));
document.querySelectorAll('.e-n-accordion-item').forEach(opt => (opt.classList.remove('section-open')));
resetTabTitle(systemSection);
resetTabValue(systemSection);
resetTabTitle(gunSection);
resetTabValue(gunSection);
resetTabTitle(displaySection);
resetTabValue(displaySection);
resetTabTitle(hardwareSection);
resetTabValue(hardwareSection);
resetVisibility();
});
gunSection.querySelector('.e-n-accordion-item-title')?.addEventListener('click', () => {
if (!gunSection.classList.contains('selected')) return;
gunSection.querySelectorAll('.accordion-item-selected').forEach(opt => opt.classList.remove('accordion-item-selected'));
gunSection.classList.remove('selected');
gunSection.classList.remove('section-open');
displaySection.querySelectorAll('.accordion-item-selected').forEach(opt => opt.classList.remove('accordion-item-selected'));
displaySection.classList.remove('selected');
displaySection.classList.remove('section-open');
hardwareSection.querySelectorAll('.accordion-item-selected').forEach(opt => opt.classList.remove('accordion-item-selected'));
hardwareSection.classList.remove('selected');
hardwareSection.classList.remove('section-open');
resetTabTitle(gunSection);
resetTabValue(gunSection);
resetTabTitle(displaySection);
resetTabValue(displaySection);
resetTabTitle(hardwareSection);
resetTabValue(hardwareSection);
resetVisibility();
hideItems('.hardware-option', rules.hardware.system[systemSection.querySelector('.accordion-item-selected').dataset.val.replace(/"|"/g, '')] || []);
});
displaySection.querySelector('.e-n-accordion-item-title')?.addEventListener('click', () => {
if (!displaySection.classList.contains('selected')) return;
displaySection.querySelectorAll('.accordion-item-selected').forEach(opt => opt.classList.remove('accordion-item-selected'));
displaySection.classList.remove('selected');
displaySection.classList.remove('section-open');
hardwareSection.querySelectorAll('.accordion-item-selected').forEach(opt => opt.classList.remove('accordion-item-selected'));
hardwareSection.classList.remove('selected');
hardwareSection.classList.remove('section-open');
resetTabTitle(displaySection);
resetTabValue(displaySection);
resetTabTitle(hardwareSection);
resetTabValue(hardwareSection);
resetVisibility();
hideItems('.hardware-option', rules.hardware.system[systemSection.querySelector('.accordion-item-selected').dataset.val.replace(/"|"/g, '')] || []);
hideItems('.gun-option', rules.gun.system[systemSection.querySelector('.accordion-item-selected').dataset.val.replace(/"|"/g, '')] || []);
hideItems('.hardware-option', rules.hardware.gun[gunSection.querySelector('.accordion-item-selected').dataset.val.replace(/"|"/g, '')] || []);
});
// π Rules for hiding
const rules = {
hardware: {
system: {
PC: [
'Highwings HDMI Cable 15FT',
'Lightning to HDMI Adapter for iPhone',
'Anker USB C to HDMI'
],
Mac: [
'Highwings HDMI Cable 15FT',
'Lightning to HDMI Adapter for iPhone',
'Anker USB C to HDMI',
'Your own lightgun'
],
'Android phone': [
'Any webcam',
'High performance webcam',
'Lightning to HDMI Adapter for iPhone',
'Your own lightgun'
],
iPhone: [
'Any webcam',
'High performance webcam',
'Anker USB C to HDMI',
'Your own lightgun'
],
},
gun: {
'Glock': [
'Mantis Blackbeard X',
'Strikeman Laser Cartridge',
'SIRT Pistol',
'Any webcam',
'Your own lightgun'
],
'AR-15': [
'DryFireMag plus Laser',
'Strikeman Laser Cartridge',
'SIRT Pistol',
'High performance webcam',
'Your own lightgun'
],
SIRT: [
'DryFireMag plus Laser',
'Mantis Blackbeard X',
'Strikeman Laser Cartridge',
'High performance webcam',
'Your own lightgun',
],
'Your own lightgun': [
'Sensyne Tripod',
'Highwings HDMI Cable 15FT',
'DryFireMag plus Laser',
'Lightning to HDMI Adapter for iPhone',
'High performance webcam',
'Any webcam',
'Mantis Blackbeard X',
'Strikeman Laser Cartridge',
'SIRT Pistol',
'Anker USB C to HDMI',
'Matte Screen Protector for TV'
],
'Other gun': [
'High performance webcam',
'SIRT Pistol',
'Your own lightgun',
'DryFireMag plus Laser',
'Mantis Blackbeard X',
]
},
display: {
Projector: ['Matte Screen Protector for TV'],
'Computer monitor': ['Matte Screen Protector for TV']
}
},
gun: {
system: {
Mac: ['Your own lightgun'],
'Android phone': ['Your own lightgun'],
iPhone: ['Your own lightgun']
}
}
};
// π Pickers
document.querySelectorAll('.system-option').forEach(btn => {
btn.addEventListener('click', () => {
const caption = btn.querySelector('.widget-image-caption.wp-caption-text');
system = caption ? caption.textContent.trim() : '';
const systemDataVal = btn.dataset.val.replace(/"|"/g, '');
document.querySelectorAll('.system-option').forEach(opt => opt.classList.remove('accordion-item-selected'));
btn.classList.add('accordion-item-selected');
systemTitle.textContent = `${systemTitleStartContent}: ${system}`;
systemSection.classList.add('selected');
gunSection.classList.add('section-open');
gunSection.querySelector('.e-n-accordion-item-title').click();
deselect(displaySection);
deselect(hardwareSection);
resetTabTitle(gunSection);
resetTabTitle(displaySection);
resetTabValue(gunSection);
resetTabValue(displaySection);
resetVisibility();
hideItems('.hardware-option', rules.hardware.system[systemDataVal] || []);
hideItems('.gun-option', rules.gun.system[systemDataVal] || []);
});
});
document.querySelectorAll('.gun-option').forEach(btn => {
btn.addEventListener('click', () => {
const caption = btn.querySelector('.widget-image-caption.wp-caption-text');
gun = caption ? caption.textContent.trim() : '';
const gunDataVal = btn.dataset.val.replace(/"|"/g, '');
document.querySelectorAll('.gun-option').forEach(opt => opt.classList.remove('accordion-item-selected'));
btn.classList.add('accordion-item-selected');
gunTitle.textContent = `${gunTitleStartContent}: ${gun}`;
gunSection.classList.add('selected');
gunSection.classList.remove('section-open');
displaySection.classList.add('section-open');
displaySection.querySelector('.e-n-accordion-item-title').click();
deselect(hardwareSection);
resetTabTitle(displaySection);
resetTabValue(displaySection);
hideItems('.hardware-option', rules.hardware.gun[gunDataVal] || []);
});
});
document.querySelectorAll('.display-option').forEach(btn => {
btn.addEventListener('click', () => {
const caption = btn.querySelector('.widget-image-caption.wp-caption-text');
display = caption ? caption.textContent.trim() : '';
const displayDataVal = btn.dataset.val.replace(/"|"/g, '');
document.querySelectorAll('.display-option').forEach(opt => opt.classList.remove('accordion-item-selected'));
btn.classList.add('accordion-item-selected');
displayTitle.textContent = `${displayTitleStartContent}: ${display}`;
displaySection.classList.add('selected');
displaySection.classList.remove('section-open');
hardwareSection.classList.add('section-open');
"{=0}"
hardwareSection.querySelector('.e-n-accordion-item-title').click();
hideItems('.hardware-option', rules.hardware.display[displayDataVal] || []);
});
});
});