JaiminB

Autoplay Steam Salien Game 2018

Jun 24th, 2018
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name         Saliens bot
  3. // @namespace    http://tampermonkey.net/
  4. // @version      25
  5. // @description  Beat all the saliens levels
  6. // @author       https://github.com/meepen/salien-bot
  7. // @match        https://steamcommunity.com/saliengame
  8. // @match        https://steamcommunity.com/saliengame/
  9. // @match        https://steamcommunity.com/saliengame/play
  10. // @match        https://steamcommunity.com/saliengame/play/
  11. // @grant        none
  12. // Install tampermonkey in your browser and after that go to extension click on create new script and copy paste this code and save it
  13. // Now open your game and you are go to go
  14. // ==/UserScript==
  15.  
  16.  
  17. if (typeof GM_info !== "undefined" && (GM_info.scriptHandler || "Greasemonkey") == "Greasemonkey") {
  18.     alert("It's not possible to support Greasemonkey, please try Tampermonkey or ViolentMonkey.");
  19. }
  20.  
  21. (function(context) {
  22. "use strict";
  23.  
  24. const MAX_LEVEL = 13;
  25.  
  26. // reload automatically instead of clicking ok
  27. context.error = context.GameLoadError = function() {
  28.     window.location.reload();
  29. }
  30.  
  31. // when the error is fixed we should remove the following
  32. CSalien.prototype.UpdateCustomizations = function()
  33. {
  34.     this.SetBodyType(BODY_TYPES[gSalienData.body_type]);
  35.     this.LoadAttachments();
  36. }
  37. const APP = context.gApp;
  38. const GAME = context.gGame;
  39. const SERVER = context.gServer;
  40. const PIXI = context.PIXI;
  41.  
  42. SERVER._ReportScore = SERVER._ReportScore || SERVER.ReportScore;
  43. SERVER.ReportScore = function ReportScore(nScore, callback, error) {
  44.     return this._ReportScore(nScore, function ReportScore_callback(results) {
  45.         let response = results.response;
  46.         console.log(`Server reported level ${response.new_level} (${response.new_score} / ${response.next_level_score})`)
  47.         return callback(results);
  48.     }, function ReportScore_error() {
  49.         console.log(arguments);
  50.         if (error)
  51.             error.apply(null, arguments);
  52.     });
  53. }
  54.  
  55. const Option = function Option(name, def) {
  56.     if (window.localStorage[name] === undefined) {
  57.         context.localStorage[name] = def;
  58.     }
  59.     return context.localStorage[name];
  60. }
  61. Option("forceLevellingMode", false);
  62. const SetMouse = function SetMouse(x, y) {
  63.     APP.renderer.plugins.interaction.mouse.global.x = x;
  64.     APP.renderer.plugins.interaction.mouse.global.y = y;
  65. }
  66. const EnemyManager = function EnemyManager() {
  67.     return GAME.m_State.m_EnemyManager;
  68. }
  69. const AttackManager = function AttackManager() {
  70.     return GAME.m_State.m_AttackManager;
  71. }
  72.  
  73. let isJoining = false;
  74. const TryContinue = function TryContinue() {
  75.     let continued = false;
  76.     if (isJoining)
  77.         return continued;
  78.     if (GAME.m_State.m_VictoryScreen) {
  79.         GAME.m_State.m_VictoryScreen.children.forEach(function(child) {
  80.             if (child.visible && child.x == 155 && child.y == 300) {// TODO: not this
  81.                 continued = true;
  82.                 isJoining = true;
  83.                 setTimeout(() => {
  84.                     isJoining = false
  85.                 }, 6000);
  86.         setTimeout(() => {
  87.             child.pointertap();
  88.                 }, 5000);
  89.             }
  90.         })
  91.     }
  92.     if (GAME.m_State.m_LevelUpScreen) {
  93.         continued = false;
  94.         GAME.m_State.m_LevelUpScreen.children.forEach(function(child) {
  95.             if (child.visible && child.x == 155 && child.y == 300) {// TODO: not this
  96.                 continued = true;
  97.                 isJoining = true;
  98.                 child.pointertap();
  99.                 setTimeout(() => {
  100.                     isJoining = false
  101.                 }, 6000);
  102.         setTimeout(() => {
  103.             child.pointertap();
  104.                 }, 5000);
  105.             }
  106.         })
  107.     }
  108.     if (gServer.m_WebAPI && GAME.m_State instanceof CBootState) { // First screen
  109.         isJoining = true;
  110.         setTimeout(() => isJoining = false, 1000);
  111.         GAME.m_State.button.click();
  112.     }
  113.     if (GAME.m_State instanceof CPlanetSelectionState && !isJoining) { // Planet Selection
  114.         GAME.m_State.m_rgPlanetSprites[0].pointertap();
  115.         isJoining = true;
  116.         setTimeout(() => isJoining = false, 1000);
  117.         continued = true;
  118.     }
  119.     if (GAME.m_State instanceof CBattleSelectionState && !isJoining) {
  120.         let bestZoneIdx = GetBestZone();
  121.         if(bestZoneIdx) {
  122.             console.log("join to zone", bestZoneIdx);
  123.             isJoining = true;
  124.             GAME.m_State.m_Grid.click(bestZoneIdx % k_NumMapTilesW, (bestZoneIdx / k_NumMapTilesW) | 0);
  125.             setTimeout(() => isJoining = false, 1000);
  126.         }
  127.         else {
  128.             isJoining = true;
  129.             GAME.m_State.m_LeaveButton.click();
  130.             console.log("Leaving planet, no zones left");
  131.             setTimeout(() => {
  132.                 window.location.reload();
  133.             }, 1000);
  134.         }
  135.         console.log(bestZoneIdx);
  136.         return;
  137.     }
  138.     return continued;
  139. }
  140. const CanAttack = function CanAttack(attackname) {
  141.     let Manager = AttackManager().m_mapCooldowns.get(attackname);
  142.     let lastUsed = Manager.m_rtAttackLastUsed;
  143.     let canAttack = Manager.BAttack();
  144.     Manager.m_rtAttackLastUsed = lastUsed;
  145.     return canAttack;
  146. }
  147. const GetBestZone = function GetBestZone() {
  148.     let bestZoneIdx;
  149.     let highestDifficulty = -1;
  150.  
  151.     let isLevelling = context.gPlayerInfo.level < MAX_LEVEL || Option("forceLevellingMode");
  152.     let maxProgress = isLevelling ? 10000 : 0;
  153.  
  154.     for (let idx = 0; idx < GAME.m_State.m_Grid.m_Tiles.length; idx++) {
  155.         let zone = GAME.m_State.m_Grid.m_Tiles[idx].Info;
  156.         if (!zone.captured) {
  157.             if (zone.boss) {
  158.                 console.log(`zone ${idx} (${bestZoneIdx % k_NumMapTilesW}, ${(bestZoneIdx / k_NumMapTilesW) | 0}) with boss`);
  159.                 return idx;
  160.             }
  161.  
  162.             if(isLevelling) {
  163.                 if(zone.difficulty > highestDifficulty) {
  164.                     highestDifficulty = zone.difficulty;
  165.                     maxProgress = zone.progress;
  166.                     bestZoneIdx = idx;
  167.                 } else if(zone.difficulty < highestDifficulty) continue;
  168.  
  169.                 if(zone.progress < maxProgress) {
  170.                     maxProgress = zone.progress;
  171.                     bestZoneIdx = idx;
  172.                 }
  173.             } else {
  174.                 if(zone.progress > maxProgress) {
  175.                     maxProgress = zone.progress;
  176.                     bestZoneIdx = idx;
  177.                 }
  178.             }
  179.  
  180.         }
  181.     }
  182.  
  183.     if(bestZoneIdx !== undefined) {
  184.         console.log(`${GAME.m_State.m_PlanetData.state.name} zone ${bestZoneIdx} (${bestZoneIdx % k_NumMapTilesW}, ${(bestZoneIdx / k_NumMapTilesW) | 0}) progress: ${GAME.m_State.m_Grid.m_Tiles[bestZoneIdx].Info.progress} difficulty: ${GAME.m_State.m_Grid.m_Tiles[bestZoneIdx].Info.difficulty}`);
  185.     }
  186.  
  187.     return bestZoneIdx;
  188. }
  189. const GetBestPlanet = function GetBestPlanet() {
  190.     let bestPlanet;
  191.     let maxProgress = 0;
  192.  
  193.     if (!GAME.m_State.m_mapPlanets)
  194.         return;
  195.  
  196.     for (let planetKV of GAME.m_State.m_mapPlanets) {
  197.         let planet = planetKV[1];
  198.         if(planet.state.active && !planet.state.captured && planet.state.capture_progress > maxProgress) {
  199.             maxProgress = planet.state.capture_progress;
  200.             bestPlanet = planet;
  201.         }
  202.  
  203.     }
  204.  
  205.     if(bestPlanet) {
  206.         console.log(`selecting planet ${bestPlanet.state.name} with progress: ${bestPlanet.state.capture_progress}`);
  207.         return bestPlanet.id;
  208.     }
  209. }
  210.  
  211. // Let's challenge ourselves to be human here!
  212. const CLICKS_PER_SECOND = 15;
  213.  
  214. const InGame = function InGame() {
  215.     return GAME.m_State.m_bRunning;
  216. }
  217.  
  218. const WORST_SCORE = -1 / 0;
  219. const START_POS = APP.renderer.width;
  220.  
  221.  
  222. const EnemySpeed = function EnemySpeed(enemy) {
  223.     return enemy.m_Sprite.vx;
  224. }
  225. const EnemyDistance = function EnemyDistance(enemy) {
  226.     return (enemy.m_Sprite.x - k_nDamagePointx) / (START_POS - k_nDamagePointx);
  227. }
  228.  
  229. const EnemyCenter = function EnemyCenter(enemy) {
  230.     return [
  231.         enemy.m_Sprite.x + enemy.m_Sprite.width / 2,
  232.         enemy.m_Sprite.y + enemy.m_Sprite.height / 2
  233.     ];
  234. }
  235.  
  236. const BlackholeOfEnemy = function BlackholeOfEnemy(enemy) {
  237.     for(var [_, blackhole] of AttackManager().m_mapBlackholes) {
  238.         // Check if enemy is very close to blackhole
  239.         if ( EnemyCenter(enemy)[0] < blackhole.x || EnemyCenter(enemy)[0] > blackhole.x ||
  240.              EnemyCenter(enemy)[1] < blackhole.y || EnemyCenter(enemy)[1] > blackhole.y ) {
  241.             return blackhole;
  242.         }
  243.     }
  244.     return null;
  245. }
  246.  
  247. class Attack {
  248.     constructor() {
  249.         this.nextAttackDelta = 0;
  250.     }
  251.     shouldAttack(delta, enemies) {
  252.         throw new Error("shouldAttack not implemented");
  253.     }
  254.     process(enemies) {
  255.         throw new Error("process not implemented");
  256.     }
  257.     getAttackName() {
  258.         throw new Error("no current attack name");
  259.     }
  260.     canAttack() {
  261.         return CanAttack(this.getAttackName());
  262.     }
  263.     getAttackData() {
  264.         return AttackManager().m_AttackData[this.getAttackName()];
  265.     }
  266. }
  267.  
  268. // Basic clicking attack, attack closest
  269. class ClickAttack extends Attack {
  270.     shouldAttack(delta) {
  271.         // Can't do basic attack when station is down
  272.         if (GAME.m_State.m_PlayerHealth <= 0)
  273.             return false;
  274.         this.nextAttackDelta -= delta;
  275.         return this.nextAttackDelta <= 0;;
  276.     }
  277.     score(enemy) {
  278.         if (enemy.m_bDead)
  279.             return WORST_SCORE;
  280.         return 1 - EnemyDistance(enemy);
  281.     }
  282.     process(enemies) {
  283.         let target, target_score = WORST_SCORE;
  284.  
  285.         enemies.forEach((enemy) => {
  286.             if (!enemy.m_Sprite.visible)
  287.                 return;
  288.             let now_score = this.score(enemy);
  289.             if (now_score > target_score) {
  290.                 target = enemy, target_score = now_score;
  291.             }
  292.         });
  293.  
  294.         if (target)
  295.             this.attack(target);
  296.     }
  297.     attack(enemy) {
  298.         enemy.m_Sprite.pointertap();
  299.         this.nextAttackDelta = 1 / CLICKS_PER_SECOND;
  300.     }
  301. }
  302.  
  303. class ProjectileAttack extends Attack {
  304.     targetPosition(target) {
  305.         return EnemyCenter(target);
  306.     }
  307.     shouldAttack(delta) {
  308.         return CanAttack(this.getAttackName());
  309.     }
  310.     score(enemy) {
  311.         if (enemy.m_bDead)
  312.             return WORST_SCORE;
  313.         return enemy.m_nHealth;
  314.     }
  315.     process(enemies) {
  316.         let target, target_score = WORST_SCORE;
  317.  
  318.         enemies.forEach((enemy) => {
  319.             if (!enemy.m_Sprite.visible)
  320.                 return;
  321.             let now_score = this.score(enemy);
  322.             if (now_score > target_score) {
  323.                 target = enemy, target_score = now_score;
  324.             }
  325.         });
  326.  
  327.         if (target) {
  328.             this.attack.apply(this, this.targetPosition(target));
  329.         }
  330.     }
  331.     attack(x, y) {
  332.         SetMouse(x, y)
  333.         AttackManager().m_mapKeyCodeToAttacks.get(this.getAttackData().keycode)()
  334.     }
  335. }
  336.  
  337. // the '1' button (SlimeAttack PsychicAttack BeastAttack - depends on body type of your salien)
  338. class SpecialAttack extends ProjectileAttack {
  339.  
  340.     targetPosition(target) {
  341.         var finalTargetPosition = EnemyCenter(target);
  342.  
  343.         // SpecialAttack's projectile is quite slow, so we need to aim ahead of the target
  344.         finalTargetPosition[0] += 50*EnemySpeed(target);
  345.  
  346.         // If target is stuck in blackhole, shoot at black hole instead
  347.         var blackhole = BlackholeOfEnemy(target);
  348.         if(blackhole != null) {
  349.             finalTargetPosition = [blackhole.x, blackhole.y];
  350.         }
  351.  
  352.         return finalTargetPosition;
  353.     }
  354.  
  355.     getAttackName() {
  356.         if (gSalien.m_BodyType == "slime")
  357.             return "slimeattack";
  358.         else if (gSalien.m_BodyType == "beast")
  359.             return "beastattack";
  360.         else
  361.             return "psychicattack";
  362.     }
  363. }
  364.  
  365. class BombAttack extends ProjectileAttack {
  366.     getAttackName() {
  367.         return "explosion";
  368.     }
  369. }
  370. class BlackholeAttack extends ProjectileAttack {
  371.     getAttackName() {
  372.         return "blackhole";
  373.     }
  374. }
  375. class MeteorAttack extends ProjectileAttack {
  376.     getAttackName() {
  377.         return "boulder";
  378.     }
  379. }
  380.  
  381. class FreezeAttack extends Attack {
  382.     getCurrent() {
  383.         return "flashfreeze";
  384.     }
  385.     shouldAttack(delta, enemies) {
  386.         let shouldAttack = false;
  387.         if (CanAttack(this.getCurrent())) {
  388.             enemies.forEach((enemy) => {
  389.                 if (EnemyDistance(enemy) <= 0.05) {
  390.                     shouldAttack = true;
  391.                 }
  392.             });
  393.         }
  394.         return shouldAttack;
  395.     }
  396.     getData() {
  397.         return AttackManager().m_AttackData[this.getCurrent()];
  398.     }
  399.     process() {
  400.         AttackManager().m_mapKeyCodeToAttacks.get(this.getData().keycode)()
  401.     }
  402. }
  403.  
  404. let attacks = [
  405.     new ClickAttack(),
  406.     new SpecialAttack(),
  407.     new FreezeAttack(),
  408.     new BombAttack(),
  409.     new MeteorAttack(),
  410.     new BlackholeAttack()
  411. ]
  412.  
  413. if (context.BOT_FUNCTION) {
  414.     APP.ticker.remove(context.BOT_FUNCTION);
  415.     context.BOT_FUNCTION = undefined;
  416. }
  417.  
  418. let reloadingPage = false;
  419.  
  420. context.BOT_FUNCTION = function ticker(delta) {
  421.     delta /= 100;
  422.  
  423.     let difficulties = PIXI.loader.resources['level_config'];
  424.     if (difficulties)
  425.         for (let difficulty in difficulties.data) {
  426.             let freq = difficulties.data[difficulty].enemies.spawn_frequency;
  427.             freq.min = freq.max;
  428.         }
  429.  
  430.     let buttonsOnErrorMessage = document.getElementsByClassName("btn_grey_white_innerfade btn_medium");
  431.     if(buttonsOnErrorMessage[0] != null) {
  432.         if (!reloadingPage) {
  433.             setTimeout(() => buttonsOnErrorMessage[0].click(), 1000);
  434.         }
  435.  
  436.         return;
  437.     }
  438.  
  439.     if (GAME.m_IsStateLoading) {
  440.         return;
  441.     }
  442.  
  443.     if (!InGame()) {
  444.         if (TryContinue()) {
  445.             console.log("continued!");
  446.         }
  447.         return;
  448.     }
  449.  
  450.  
  451.  
  452.     let state = EnemyManager();
  453.  
  454.     let enemies = state.m_rgEnemies;
  455.  
  456.     for (let attack of attacks)
  457.         if (attack.shouldAttack(delta, enemies))
  458.             attack.process(enemies);
  459.  
  460. }
  461.  
  462.  
  463. APP.ticker.add(context.BOT_FUNCTION);
  464.  
  465. })(window);
Add Comment
Please, Sign In to add comment