1-16 Table top Wound Tracker (Choose a Colour) - Yellow

Explore this product further
Browse similar items by category or seller.
Last price observation: 14 Jun 2026 00:21 UTC
1-16 Table top Wound Tracker (Choose a Colour) - Yellow
£2.99
Variations
  • InStock.net
  • @keyframes fadeInUp { } .discount-calculator h3, .discount-calculator label, .discount-calculator p, .discount-calculator .discount-calculator @media (max-width: 768px) { } Quantity Total Each (£) New Discounted Total (£) Saving (£) 1 £2.99 £2.99 – 3+ £2.84 £8.52 £0.45 / 5% Off 5+ £2.69 £13.46 £1.49 / 10% Off 10+ £2.54 £25.42 £4.49 / 15% Off 15+ £2.39 £35.88 £8.97 / 20% Off Multi-Buy Calculator Enter Quantity: Total Each: £2.99 New Discounted Total: £2.99 Savings: – 🔥 The Only Clickable Wound Tracker for Warhammer 40K Tired of losing track of wounds mid-game? This is the ONLY clickable wound tracker on the market – designed to lock each wound in place so nothing shifts when you pick it up or adjust your models. ✅ Why You'll Love It: 🔒 Secure click-to-lock mechanism – no more knocked dials or lost wounds 🔢 Clear, bold numbers – easy to read at a glance 🎯 Smooth & satisfying clicks – precise control over tracking 🧱 Durable and battle-ready – built to last through heavy use 🎨 Minimalist design – complements your painted armies perfectly 🛠️ Compatible with Warhammer 40K, Kill Team, AoS & more Whether you're fighting for glory at a tournament or battling friends at home, this wound tracker gives you the accuracy and confidence every commander needs. No more guesswork. No more accidental resets. Just reliable, click-by-click tracking. (() => { // --- Config --- const DISCOUNTS = [ { min: 15, rate: 0.20, label: "20% Off" }, { min: 10, rate: 0.15, label: "15% Off" }, { min: 5, rate: 0.10, label: "10% Off" }, { min: 3, rate: 0.05, label: "5% Off" }, { min: 1, rate: 0.00, label: "" }, ]; const currencyFormatter = new Intl.NumberFormat('en-GB', { style: 'currency', currency: 'GBP', minimumFractionDigits: 2 }); let currentVariantPrice = null; // in GBP (e.g., 12.99) // --- Price helpers --- function getDiscountForQty(qty) { for (const tier of DISCOUNTS) { if (qty >= tier.min) return tier; } ; } function readPriceFromDOM() { // Try a few common selectors used by Shopify themes const candidates = [ '[data-product-price]', '.price .price-item--regular', '.product__price .price-item--regular', '.price__regular .price-item', '[itemprop="price"]', '[data-price]' ]; for (const sel of candidates) { const el = document.querySelector(sel); if (el && el.textContent) { const raw = el.textContent.replace(/[^\d.,]/g, '').replace(',', '.'); const val = parseFloat(raw); if (!Number.isNaN(val)) return val; } } return null; } function readVariantFromJSON() { // Works on most OS 2.0 themes const jsonEl = document.querySelector('script[type="application/json"][data-product], script[id*="ProductJson"]'); if (!jsonEl) return null; try { const product = JSON.parse(jsonEl.textContent); const qsId = new URLSearchParams(location.search).get('variant'); if (qsId && product.variants) { const v = product.variants.find(v => String(v.id) === String(qsId)); if (v) return v; } // fallback: first available or first variant return (product.variants || []).find(v => v.available) || (product.variants || [])[0] || null; } } function getBasePriceGBP() { // 1) From live variant change listener if (typeof currentVariantPrice === 'number') return currentVariantPrice; // 2) From DOM price const domVal = readPriceFromDOM(); if (typeof domVal === 'number') return domVal; // 3) From product JSON const v = readVariantFromJSON(); if (v && typeof v.price === 'number') return v.price / 100; // JSON is in cents // 4) Fallback to your default return 2.99; } // --- Calculator binding --- function bindCalculator() { const qtyInput = document.getElementById('quantity'); const pricePerItemEl = document.getElementById('pricePerItem'); const totalPriceEl = document.getElementById('totalPrice'); const savingsEl = document.getElementById('savings'); if (!qtyInput || !pricePerItemEl || !totalPriceEl || !savingsEl) return; // Avoid double-binding after re-renders if (qtyInput.dataset.bound === '1') return; qtyInput.dataset.bound = '1'; const recalc = () => { const qty = Math.max(1, parseInt(qtyInput.value, 10) || 1); = getDiscountForQty(qty); const base = getBasePriceGBP(); const totalFull = base * qty; const discountAmount = totalFull * rate; const totalDiscounted = totalFull -