// ==UserScript== // @name [Pokeclicker - Alucare.fr] Ajout Auto Clicker // @namespace Pokeclicker Scripts // @match https://www.pokeclicker.com/ // @grant none // @version 1.9 // @author Ephenia (Original/Credit: Ivan Lay, Novie53, andrew951) (Translate : Alucare.fr) // @description Cliquez sur les batailles de manière appropriée en fonction de l'état du jeu. Inclut également un bouton permettant d'activer ou de désactiver l'auto-clic et diverses statistiques utiles. Comprend également un combat de gym automatique et un donjon automatique avec différents modes, ainsi que la possibilité d'ajuster la vitesse à laquelle l'Auto Clicker peut cliquer sur un combat. // ==/UserScript== var clickState; var clickColor; var awaitAutoClick; var autoClickerLoop; var autoClickDPS; var clickDPS; var reqDPS; var enemySpeedRaw; var enemySpeed; var colorDPS; var allSelectedGym = 0; var gymState; var gymColor; var gymSelect; var dungeonState; var dungeonColor; var dungeonSelect; var foundBoss = false; var foundBossX; var foundBossY; var newSave; var delayAutoClick; var trainerCards; window.testDPS = 0; window.defeatDPS = 0; var battleView = document.getElementsByClassName('battle-view')[0]; function initAutoClicker() { if (clickState == "OFF") { clickColor = "danger" clickDPS = 0 } else { clickColor = "success" clickDPS = +localStorage.getItem('storedClickDPS'); } if (gymState == "OFF") { gymColor = "danger" } else { gymColor = "success" } if (dungeonState == "OFF") { dungeonColor = "danger" } else { dungeonColor = "success" } var elemAC = document.createElement("table"); elemAC.innerHTML = `
Click Attack Delay: ` + clickDelayFixed(1000 / delayAutoClick) + `/s
` battleView.before(elemAC) document.getElementById('gym-select').value = gymSelect; document.getElementById('dungeon-select').value = dungeonSelect; $("#auto-click-start").click(toggleAutoClick) $("#auto-gym-start").click(toggleAutoGym) $("#gym-select").change(changeSelectedGym) $("#auto-dungeon-start").click(toggleAutoDungeon) $("#dungeon-select").change(changeSelectedDungeon) document.getElementById('auto-click-delay').addEventListener('change', (event) => { changeClickDelay(event) }) addGlobalStyle('#auto-click-info { display: flex;flex-direction: row;justify-content: center; }'); addGlobalStyle('#auto-click-info > div { width: 33.3%; }'); addGlobalStyle('#dungeonMap { padding-bottom: 9.513%; }'); addGlobalStyle('#click-delay-cont { display: flex; flex-direction: column; align-items: stretch;}') if (clickState == "ON") { autoClicker(); calcClickDPS(); } overideClickAttack(); } function toggleAutoClick() { if (clickState == "OFF") { clickState = "ON" document.getElementById("auto-click-start").classList.remove('btn-danger'); document.getElementById("auto-click-start").classList.add('btn-success'); clickDPS = +localStorage.getItem('storedClickDPS'); autoClicker(); calcClickDPS(); } else { clickState = "OFF" document.getElementById("auto-click-start").classList.remove('btn-success'); document.getElementById("auto-click-start").classList.add('btn-danger'); clickDPS = 0; reqDPS = 0; enemySpeedRaw = 0; clearInterval(autoClickerLoop) clearInterval(autoClickDPS) } localStorage.setItem("autoClickState", clickState); document.getElementById('auto-click-start').innerHTML = `Auto Click [` + clickState + `]
Auto Click DPS:
`+ clickDPS.toLocaleString('en-US') + `
Req. DPS:
0
Enemy/s:
0
` } function toggleAutoGym() { if (gymState == "OFF") { gymState = "ON" document.getElementById("auto-gym-start").classList.remove('btn-danger'); document.getElementById("auto-gym-start").classList.add('btn-success'); } else { gymState = "OFF" document.getElementById("auto-gym-start").classList.remove('btn-success'); document.getElementById("auto-gym-start").classList.add('btn-danger'); } localStorage.setItem("autoGymState", gymState); document.getElementById('auto-gym-start').innerHTML = `Auto Gym [` + gymState + `]` } function toggleAutoDungeon() { if (dungeonState == "OFF") { dungeonState = "ON" document.getElementById("auto-dungeon-start").classList.remove('btn-danger'); document.getElementById("auto-dungeon-start").classList.add('btn-success'); } else { dungeonState = "OFF" document.getElementById("auto-dungeon-start").classList.remove('btn-success'); document.getElementById("auto-dungeon-start").classList.add('btn-danger'); } localStorage.setItem("autoDungeonState", dungeonState); document.getElementById('auto-dungeon-start').innerHTML = `Auto Dungeon [` + dungeonState + `]` } function changeSelectedGym() { if (gymSelect != +document.getElementById('gym-select').value) { gymSelect = +document.getElementById('gym-select').value localStorage.setItem("selectedGym", gymSelect); } } function changeSelectedDungeon() { if (dungeonSelect != +document.getElementById('dungeon-select').value) { dungeonSelect = +document.getElementById('dungeon-select').value localStorage.setItem("selectedDungeon", dungeonSelect); } } function getRandomInt(max) { return Math.floor(Math.random() * max); } function calcClickDPS() { autoClickDPS = setInterval(function () { const clickSec = testDPS; let enemyHealth; try { enemyHealth = Battle.enemyPokemon().maxHealth(); } catch (err) { enemyHealth = 0; } if (clickDPS != App.game.party.calculateClickAttack() * clickSec) { clickDPS = App.game.party.calculateClickAttack() * clickSec; document.getElementById('click-DPS').innerHTML = `Auto Click DPS:
` + Math.floor(clickDPS).toLocaleString('en-US'); +`
` localStorage.setItem('storedClickDPS', clickDPS) } if (reqDPS != enemyHealth * clickSec) { reqDPS = enemyHealth * clickSec; if (clickDPS >= reqDPS) { colorDPS = "greenyellow" } else { colorDPS = "darkred" } document.getElementById('req-DPS').innerHTML = `Req. DPS:
` + Math.ceil(reqDPS).toLocaleString('en-US'); +`
` } if (enemySpeedRaw != ((App.game.party.calculateClickAttack() * clickSec) / enemyHealth).toFixed(1)) { enemySpeed = ((App.game.party.calculateClickAttack() * clickSec) / enemyHealth); enemySpeedRaw = enemySpeed; if (isNaN(enemySpeedRaw) || enemySpeedRaw == 'Infinity' || Battle.catching()) { enemySpeed = 0; } if (enemySpeedRaw >= clickSec && enemySpeedRaw != 'Infinity' && !Battle.catching()) { enemySpeed = defeatDPS; } if (!Number.isInteger(enemySpeed) && enemySpeed != 0) { enemySpeed = enemySpeed.toFixed(1).toString().replace('.0', '') } document.getElementById('enemy-DPS').innerHTML = `Enemy/s:
` + enemySpeed + `
` } testDPS = 0; defeatDPS = 0; }, 1000); } function autoClicker() { autoClickerLoop = setInterval(function () { // Click while in a normal battle if (App.game.gameState == GameConstants.GameState.fighting) { Battle.clickAttack(); } //Auto Gym checking if (gymState == "ON") { autoGym(); } //Auto Dungeon checking if (dungeonState == "ON" && DungeonRunner.fighting() == false && DungeonBattle.catching() == false) { autoDungeon(); } //Reset the values for the boss coordinates if we timeout or turn off autoDungeon if ((dungeonState == "OFF" && foundBoss) || (dungeonState == "ON" && DungeonRunner.dungeonFinished() && foundBoss)){ foundBoss = false bossCoords.length = 0 } // Click while in a gym battle if (App.game.gameState === GameConstants.GameState.gym) { GymBattle.clickAttack(); } // Click while in "Tomporary Battle" (battle ultra wormhole) if (App.game.gameState === GameConstants.GameState.temporaryBattle) { TemporaryBattleBattle.clickAttack(); } // Click while in a dungeon - will also interact with non-battle tiles (e.g. chests) if (App.game.gameState === GameConstants.GameState.dungeon) { if (DungeonRunner.fighting() && !DungeonBattle.catching()) { DungeonBattle.clickAttack(); } } }, delayAutoClick); // The app hard-caps click attacks at 50 } function changeClickDelay(event) { const delay = +event.target.value; delayAutoClick = delay; localStorage.setItem("delayAutoClick", delay); overideClickAttack(); if (clickState == "ON") { clearInterval(autoClickerLoop); autoClicker(); } let clickSec = (1000 / delayAutoClick); document.getElementById('auto-click-delay-info').innerText = `Click Attack Delay: ` + clickDelayFixed(clickSec) + `/s` } function clickDelayFixed(int) { if (int != parseInt(int)) { int = int.toFixed(2) } return int; } function overideClickAttack() { // Overiding the game's function for Click Attack Battle.clickAttack = function() { // click attacks disabled and we already beat the starter if (App.game.challenges.list.disableClickAttack.active() && player.starter() != GameConstants.Starter.None) { return; } // TODO: figure out a better way of handling this // Limit click attack speed, Only allow 1 attack per 50ms (20 per second) const now = Date.now(); if (this.lastClickAttack > now - delayAutoClick) { return; } this.lastClickAttack = now; if (!this.enemyPokemon()?.isAlive()) { return; } GameHelper.incrementObservable(App.game.statistics.clickAttacks); this.enemyPokemon().damage(App.game.party.calculateClickAttack(true)); testDPS++; if (!this.enemyPokemon().isAlive()) { this.defeatPokemon(); defeatDPS++; } } } function autoGym() { if (player.town().content.length != 0) { //Might break in some towns, needs more testing if (player.town().content[0] instanceof Gym) { if (MapHelper.calculateTownCssClass(player.town().name) != "currentLocation") { MapHelper.moveToTown(player.town().name) } /*Don't think this can ever happen if (player.region != player.town().region) { player.region = player.town().region }*/ if (App.game.gameState != GameConstants.GameState.gym) { //Checking if Champion exists here and is unlocked let champUnlocked; try {champUnlocked = player.town().content[4].isUnlocked()} catch (err) { champUnlocked = false } //If "All" is selected and the Champion is unlocked, then go through list of league fully from 0-4 if (gymSelect === 5 && champUnlocked) { GymRunner.startGym(player.town().content[allSelectedGym]) allSelectedGym++ if(allSelectedGym === 5) { allSelectedGym = 0 } } else { //If the content is a Gym or league champion and we unlocked it we fight if ((player.town().content[gymSelect] instanceof Gym && player.town().content[gymSelect].isUnlocked()) || (player.town().content[gymSelect] instanceof Champion && player.town().content[gymSelect].isUnlocked())){ GymRunner.startGym(player.town().content[gymSelect]) } else { //Otherwise we try to fight the previous gyms (elite 4) for (var i = player.town().content.length - 1; i >= 0; i--){ if ((player.town().content[i] instanceof Gym && player.town().content[i].isUnlocked()) || (player.town().content[i] instanceof Champion && player.town().content[i].isUnlocked())){ GymRunner.startGym(player.town().content[i]) break; } } } } } } } } var bossCoords = [] function autoDungeon() { //Rewrite if (player.town().hasOwnProperty("dungeon") == true && player.town().dungeon !== undefined) { var getTokens = App.game.wallet.currencies[GameConstants.Currency.dungeonToken](); var dungeonCost = player.town().dungeon.tokenCost; if (MapHelper.calculateTownCssClass(player.town().name) != "currentLocation") { MapHelper.moveToTown(player.town().name) } //Don't think this condition is ever possible /*if (player.region != player.town().region) { player.region = player.town().region }*/ if (getTokens >= dungeonCost && App.game.gameState != GameConstants.GameState.dungeon) { DungeonRunner.initializeDungeon(player.town().dungeon) } if (App.game.gameState === GameConstants.GameState.dungeon) { var dungeonBoard = DungeonRunner.map.board(); //The boss can be found at any time if (foundBoss == false){ bossCoords = scan(dungeonBoard) } //Wander around until we can move to the boss tile //Pathfinding should be implemented here, A* looks like the best algorithm else if (foundBoss == true && dungeonSelect == 1){ wander(dungeonBoard, bossCoords) } else if (dungeonSelect == 0){ fullClear(dungeonBoard, bossCoords) } } } } function scan(dungeonBoard){ /*var bossCoords = [] var playerCoords = []*/ for (var i = 0; i < dungeonBoard.length; i++){ for (var j = 0; j