Bullet Despawn Marker

Marks the position where the most recent normal bullet despawned.

// ==UserScript==
// @name         Bullet Despawn Marker
// @namespace    https://tanktrouble.com/
// @version      1.1
// @description  Marks the position where the most recent normal bullet despawned.
// @author       Gentleman (#878689)
// @license      GPL-3.0
// @match        https://tanktrouble.com/*
// @match        https://beta.tanktrouble.com/*
// @match        https://cdn.tanktrouble.com/*
// @grant        none
// @run-at       document-start
// ==/UserScript==
!function(){"use strict";console.log("[Bullet Despawn Marker] Bullet despawn marker loaded"),function(t,e){const n=t.split("."),o=n.pop();let s=window;for(const t of n)"object"==typeof s[t]&&null!==s[t]||(s[t]={}),s=s[t];Object.defineProperty(s,o,{configurable:!0,enumerable:!0,set(n){if(!n?.method)return console.log(`[Bullet Despawn Marker] ${t} has no methods to patch`),void Object.defineProperty(s,o,{value:n,writable:!0,configurable:!0});n.method=new Proxy(n.method,{apply(t,n,[o,s]){const i=e(o,s);return Reflect.apply(t,n,[o,i])}}),Object.defineProperty(s,o,{value:n,writable:!0,configurable:!0}),console.log(`[Bullet Despawn Marker] ${t} successfully patched`)},get(){}})}("Game.UIGameState",((t,e)=>{switch(t){case"create":return function(){e.call(this),this.golfGroup=this.game.add.group(this.gameGroup),this.golfMarkers=[],this.golfLabels=[],this.golfProjectiles={};for(let t=0;t<UIConstants.PROJECTILE_POOL_SIZE/5;++t){const t=new UIProjectileImage(this.game,this.gameController);t.exists=!1,t.alpha=.6,this.golfGroup.add(t),this.golfMarkers.push(t);const e=32,n=8,o=1/this.golfGroup.worldScale.x,s=this.game.add.text(0,0,"",{font:e*o+"px TankTrouble",fill:"#ffffff",stroke:"#000000",strokeThickness:n*o});s.anchor.set(0,.5),s.exists=!1,s.alpha=.6,this.golfGroup.add(s),this.golfLabels.push(s)}};case"_cleanUp":return function(){e.call(this),this.golfMarkers.forEach((t=>t.retire())),this.golfLabels.forEach((t=>{t.kill(),t.setText("")})),this.golfProjectiles={}};case"_roundEventHandler":return function(t,n,o,s){switch(o){case RoundModel._EVENTS.PROJECTILE_TIMEOUT:{const e=t.gameController.getProjectile(s);if(e.getType()===Constants.WEAPON_TYPES.BULLET){const n=e.getPlayerId(),o=t.golfProjectiles[n];o&&(o.marker.retire(),o.label.kill(),delete t.golfProjectiles[n]);const s=t.golfMarkers.find((t=>!t.exists)),i=t.golfLabels.find((t=>!t.exists));if(s&&i){const o=UIUtils.mpx(e.getX()),l=UIUtils.mpx(e.getY());s.spawn(o,l,e.getId(),"bullet"),i.reset(o+10,l),i.setText(n),i.exists=!0,i.visible=!0,t.golfProjectiles[n]={marker:s,label:i},Backend.getInstance().getPlayerDetails((t=>{"object"==typeof t&&i.setText(t.getUsername())}),null,null,n,Caches.getPlayerDetailsCache())}}t._removeProjectile(s),t._spawnProjectilePuffs(s);break}default:return e.call(this,t,n,o,s)}};default:return e}}));class t{constructor(t=5){this.initialCountdown=t,this.countdown=t,this.currentSecond=-1,this.timeoutId=null,this.expected=0,this.running=!1,document.getElementById("bdm-start").onclick=()=>this.start(),document.getElementById("bdm-stop").onclick=()=>this.stop(),document.getElementById("bdm-reset").onclick=()=>this.reset(),this.display()}chat(t){ClientManager.getClient().chat(t)}display(){const t=document.getElementById("bdm-timer");t&&(t.textContent=this.countdown.toFixed(2))}tick(){const t=performance.now()-this.expected,e=document.getElementById("bdm-toggle")?.checked;this.countdown-=.025,this.countdown<0&&(this.countdown=0),this.display();const n=Math.ceil(this.countdown);n!==this.currentSecond&&this.countdown>0?(this.currentSecond=n,e&&n<=5&&this.chat(`${n}`)):this.countdown<=0&&0!==this.currentSecond&&(this.currentSecond=0,e&&this.chat("Go!")),this.countdown>0?(this.expected+=25,this.timeoutId=setTimeout((()=>this.tick()),Math.max(0,25-t))):this.running=!1}start(){this.running||(this.expected=performance.now()+25,this.countdown===this.initialCountdown&&(this.currentSecond=-1),this.running=!0,this.tick())}stop(){clearTimeout(this.timeoutId),this.running=!1}reset(){this.stop(),this.countdown=this.initialCountdown,this.currentSecond=-1,this.display()}}document.addEventListener("DOMContentLoaded",(()=>{const e=document.createElement("style");e.textContent='#bdm-stopwatch{background:#000;color:#fff}#bdm-stopwatch .content{padding:4px}#bdm-timer{font-size:24px;margin:8px 0}.bdm-buttons{display:flex;flex-direction:column;align-items:center;gap:6px;margin-bottom:8px}.bdm-buttons button{width:75%;padding:4px 0;font-size:12px}#bdm-start{background:linear-gradient(to bottom,#00d084,#00b76b)}#bdm-stop{background:linear-gradient(to bottom,#ff4e50,#c0392b)}#bdm-reset{background:linear-gradient(to bottom,#dfe6e9,#b2bec3);color:#2c3e50}#bdm-label input[type="checkbox"]{display:none}#bdm-label{display:flex;align-items:flex-start;justify-content:flex-start;font-size:10px}#bdm-label span{text-align:left}#bdm-label input[type="checkbox"]+span::before{content:"";border:3px solid #b2bec3;transition:border 0.5s;border-radius:6px;width:16px;height:16px;line-height:16px;text-align:center;font-size:20px;vertical-align:middle;display:inline-block;margin-right:6px}#bdm-label input[type="checkbox"]:checked+span::before{content:\'\\00D7\';border-color:#00d084}',document.head.appendChild(e);const n=document.createElement("div");n.id="bdm-stopwatch",n.className="snippet",n.innerHTML="<div class=content><div class=header>Countdown</div><div id=bdm-timer>5.00</div><div class=bdm-buttons><button id=bdm-start>Start</button> <button id=bdm-stop>Stop</button> <button id=bdm-reset>Reset</button></div><label id=bdm-label><input checked id=bdm-toggle type=checkbox> <span>Send msgs to chat</span></label></div>";const o=new MutationObserver((()=>{const e=document.getElementById("messagesSnippet");if(e&&e.parentNode){e.parentNode.insertBefore(n,e.nextSibling);new t;o.disconnect()}}));o.observe(document.body,{childList:!0,subtree:!0})}))}();