Advertisement
Arxero

Untitled

Jun 30th, 2018
176
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 32.47 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Ensingm2 Salien Game Idler
  3. // @namespace https://github.com/ensingm2/saliengame_idler
  4. // @version 0.0.1
  5. // @author ensingm2
  6. // @match *://steamcommunity.com/saliengame/play
  7. // @match *://steamcommunity.com/saliengame/play/
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. // This is the zone you want to attack (Optional, otherwise picks one for you).
  12. var target_zone = -1;
  13.  
  14. // Variables. Don't change these unless you know what you're doing.
  15. var real_round_length = 120; // Round Length of a real game (In Seconds, for calculating score)
  16. var resend_frequency = 110; // Frequency at which we can say we finished a round (May be different than real length)
  17. var update_length = 1; // How long to wait between updates (In Seconds)
  18. var loop_rounds = true;
  19. var language = "english"; // Used when POSTing scores
  20. var access_token = "";
  21. var current_game_id = undefined;
  22. var current_game_start = undefined; // Timestamp for when the current game started
  23. var time_passed_ms = 0;
  24. var current_timeout = undefined;
  25. var max_retry = 5; // Max number of retries to send requests
  26. var auto_first_join = true; // Automatically join the best zone at first
  27. var current_planet_id = undefined;
  28. var last_update_grid = undefined; // Last time we updated the grid (to avoid too frequent calls)
  29. var check_game_state = undefined; // Check the state of the game script and unlock it if needed (setInterval)
  30. var auto_switch_planet = {
  31. "active": true, // Automatically switch to the best planet available (true : yes, false : no)
  32. "current_difficulty": undefined,
  33. "wanted_difficulty": 3, // Difficulty prefered. Will check planets if the current one differs
  34. "rounds_before_check": 3, // If we're not in a wanted difficulty zone, we start a planets check in this amount of rounds
  35. "current_round": 0
  36. };
  37. var gui; //local gui variable
  38. var start_button = false; // is start button already pressed?
  39. var animations_enabled = true;
  40.  
  41. class BotGUI {
  42. constructor(state) {
  43. console.log('GUI Has been created');
  44.  
  45. this.state = state;
  46.  
  47. this.createStatusWindow();
  48. this.createProgressBar();
  49. }
  50.  
  51. createStatusWindow() {
  52. if(document.getElementById('salienbot_gui')) {
  53. return false;
  54. }
  55.  
  56. var $statusWindow = $J([
  57. '<div id="salienbot_gui" style="background: #191919; z-index: 1; border: 3px solid #83d674; padding: 20px; margin: 15px; width: 300px; transform: translate(0, 0);">',
  58. '<h1><a href="https://github.com/ensingm2/saliengame_idler/">Salien Game Idler</a></h1>',
  59. '<p style="margin-top: -.8em; font-size: .75em"><span id="salienbot_status"></span></p>', // Running or stopped
  60. '<p><b>Task:</b> <span id="salienbot_task">Initializing</span></p>', // Current task
  61. `<p><b>Target Zone:</b> <span id="salienbot_zone">None</span></p>`,
  62. `<p style="display: none;" id="salienbot_zone_difficulty_div"><b>Zone Difficulty:</b> <span id="salienbot_zone_difficulty"></span> (<span id="salienbot_zone_score"></span>xp/round)</p>`,
  63. '<p><b>Level:</b> <span id="salienbot_level">' + this.state.level + '</span> &nbsp;&nbsp;&nbsp;&nbsp; <b>EXP:</b> <span id="salienbot_exp">' + this.state.exp + " / " + this.state.next_level_exp + '</span></p>',
  64. '<p><b>Lvl Up In:</b> <span id="salienbot_esttimlvl"></span></p>',
  65. '<p><input id="planetSwitchCheckbox" type="checkbox"/> Automatic Planet Switching</p>',
  66. '<p><input id="animationsCheckbox" type="checkbox"/> Hide Game (Improves Performance)</p>',
  67. '</div>'
  68. ].join(''))
  69.  
  70. $J('#salien_game_placeholder').append( $statusWindow )
  71. }
  72.  
  73. createProgressBar() {
  74. this.progressbar = new CProgressBar(63);
  75. this.progressbar.x = 2
  76. this.progressbar.y = 48
  77. }
  78.  
  79. updateStatus(running) {
  80. const statusTxt = running ? '<span style="color: green;">✓ Running</span>' : '<span style="color: red;">✗ Stopped</span>';
  81.  
  82. $J('#salienbot_status').html(statusTxt);
  83. }
  84.  
  85. updateTask(status, log_to_console) {
  86. if(log_to_console || log_to_console === undefined)
  87. console.log(status);
  88. document.getElementById('salienbot_task').innerText = status;
  89. }
  90.  
  91. updateExp(exp) {
  92. document.getElementById('salienbot_exp').innerText = exp;
  93. }
  94.  
  95. updateLevel(level) {
  96. document.getElementById('salienbot_level').innerText = level;
  97. }
  98.  
  99. updateEstimatedTime(secondsLeft) {
  100. let date = new Date(null);
  101. date.setSeconds(secondsLeft);
  102. var result = date.toISOString().substr(8, 11).split(/[T:]/);
  103.  
  104. var days = result[0]-1;
  105. var hours = result[1];
  106. var minutes = result[2];
  107. var seconds = result[3];
  108.  
  109. var timeTxt = "";
  110. if(days > 0)
  111. timeTxt += days + "d ";
  112. if(hours > 0 || timeTxt.length > 0)
  113. timeTxt += hours + "h ";
  114. if(minutes > 0 || timeTxt.length > 0)
  115. timeTxt += minutes + "m ";
  116.  
  117. timeTxt += seconds + "s";
  118.  
  119. document.getElementById('salienbot_esttimlvl').innerText = timeTxt;
  120. }
  121.  
  122. updateZone(zone, progress, difficulty) {
  123. var printString = zone;
  124. if(progress !== undefined)
  125. printString += " (" + (progress * 100).toFixed(2) + "% Complete)"
  126. if(progress === undefined) {
  127. $J("#salienbot_zone_difficulty_div").hide();
  128. difficulty = "";
  129. }
  130. else {
  131. $J("#salienbot_zone_difficulty_div").show();
  132. gGame.m_State.m_Grid.m_Tiles[target_zone].addChild(this.progressbar)
  133.  
  134. document.getElementById('salienbot_zone_score').innerText = get_max_score(zone);
  135. }
  136.  
  137. document.getElementById('salienbot_zone').innerText = printString;
  138. document.getElementById('salienbot_zone_difficulty').innerText = difficulty;
  139. }
  140. };
  141.  
  142. function initGUI(){
  143. if (!gGame.m_State || gGame.m_State instanceof CBootState || gGame.m_IsStateLoading){
  144. if(gGame.m_State && !gGame.m_IsStateLoading && !start_button){
  145. start_button = true;
  146. console.log("clicking button");
  147. gGame.m_State.button.click();
  148. }
  149. setTimeout(function() { initGUI(); }, 100);
  150. } else {
  151. console.log(gGame);
  152. gui = new BotGUI({
  153. level: gPlayerInfo.level,
  154. exp: gPlayerInfo.score,
  155. next_level_exp: gPlayerInfo.next_level_score
  156. });
  157.  
  158. // Set our onclicks
  159.  
  160. $J('#animationsCheckbox').change(function() {
  161. INJECT_toggle_animations(!this.checked);
  162. });
  163. $J('#animationsCheckbox').prop('checked', !animations_enabled);
  164.  
  165. $J('#planetSwitchCheckbox').change(function() {
  166. auto_switch_planet.active = this.checked;
  167. });
  168. $J('#planetSwitchCheckbox').prop('checked', auto_switch_planet.active);
  169.  
  170.  
  171. // Run the global initializer, which will call the function for whichever screen you're in
  172. INJECT_init();
  173. }
  174. };
  175.  
  176. function calculateTimeToNextLevel() {
  177. const nextScoreAmount = get_max_score(target_zone);
  178. const missingExp = Math.ceil((gPlayerInfo.next_level_score - gPlayerInfo.score) / nextScoreAmount) * nextScoreAmount;
  179. const roundTime = resend_frequency + update_length;
  180.  
  181. const secondsLeft = missingExp / nextScoreAmount * roundTime - time_passed_ms / 1000;
  182.  
  183. return secondsLeft;
  184. }
  185.  
  186. // Handle AJAX errors to avoid the script to be locked by a single API error
  187. function ajaxErrorHandling(ajaxObj, params, messagesArray) {
  188. ajaxObj.tryCount++;
  189. if (ajaxObj.tryCount <= ajaxObj.retryLimit) {
  190. var currentTask = "Retrying in 5s to " + messagesArray[0] + " (Retry #" + ajaxObj.tryCount + "). Error: " + params.xhr.status + ": " + params.thrownError;
  191. gui.updateTask(currentTask);
  192. setTimeout(function() { $J.ajax(ajaxObj); }, 5000);
  193. }
  194. else {
  195. var currentTask = "Error " + messagesArray[1] + ": " + params.xhr.status + ": " + params.thrownError + " (Max retries reached).";
  196. gui.updateTask(currentTask);
  197. }
  198. }
  199.  
  200. // Check the state of the game script and unlock it if needed
  201. function checkUnlockGameState() {
  202. if (current_game_start === undefined)
  203. return;
  204. var now = new Date().getTime();
  205. var timeDiff = (now - current_game_start) / 1000;
  206. var maxWait = 300; // Time (in seconds) to wait until we try to unlock the script
  207. if (timeDiff < maxWait)
  208. return;
  209. gui.updateTask("Detected the game script is locked. Trying to unlock it.");
  210. if (auto_switch_planet.active == true) {
  211. CheckSwitchBetterPlanet(true);
  212. } else {
  213. SwitchNextZone(0, true);
  214. }
  215. }
  216.  
  217. // Grab the user's access token
  218. var INJECT_get_access_token = function() {
  219. $J.ajax({
  220. async: false,
  221. type: "GET",
  222. url: "https://steamcommunity.com/saliengame/gettoken",
  223. success: function(data) {
  224. if(data.token != undefined) {
  225. console.log("Got access token: " + data.token);
  226. access_token = data.token;
  227. }
  228. else {
  229. console.log("Failed to retrieve access token.")
  230. access_token = undefined;
  231. }
  232. }
  233. });
  234. }
  235.  
  236. // Make the call to start a round, and kick-off the idle process
  237. var INJECT_start_round = function(zone, access_token, attempt_no) {
  238. if(attempt_no === undefined)
  239. attempt_no = 0;
  240.  
  241. // Leave the game if we're already in one.
  242. if(current_game_id !== undefined) {
  243. gui.updateTask("Previous game detected. Ending it.", true);
  244. INJECT_leave_round();
  245. }
  246.  
  247. // Send the POST to join the game.
  248. $J.ajax({
  249. async: false,
  250. type: "POST",
  251. url: "https://community.steam-api.com/ITerritoryControlMinigameService/JoinZone/v0001/",
  252. data: { access_token: access_token, zone_position: zone },
  253. tryCount : 0,
  254. retryLimit : max_retry,
  255. success: function(data, textStatus, jqXHR) {
  256. if( $J.isEmptyObject(data.response) ) {
  257. // Check if the zone is completed
  258. INJECT_update_grid(false); // Error handling set to false to avoid too much parallel calls with the setTimeout below
  259. if(window.gGame.m_State.m_Grid.m_Tiles[zone].Info.captured || attempt_no >= max_retry) {
  260. if (auto_switch_planet.active == true)
  261. CheckSwitchBetterPlanet();
  262. else
  263. SwitchNextZone();
  264. }
  265. else {
  266. // Check header error for an eventual lock inside a game area
  267. var errorId = jqXHR.getResponseHeader('x-eresult');
  268. if (errorId == 11) {
  269. var gameIdStuck = jqXHR.getResponseHeader('x-error_message').match(/\d+/)[0];
  270. console.log("Stuck in the previous game area. Leaving it.");
  271. current_game_id = gameIdStuck;
  272. INJECT_leave_round();
  273. } else {
  274. console.log("Error getting zone response (on start):",data);
  275. }
  276. gui.updateTask("Waiting 5s and re-sending join attempt (Attempt #" + (attempt_no + 1) + ").");
  277. clearTimeout(current_timeout);
  278. current_timeout = setTimeout(function() { INJECT_start_round(zone, access_token, attempt_no+1); }, 5000);
  279. }
  280. }
  281. else {
  282. console.log("Round successfully started in zone #" + zone);
  283. console.log(data);
  284.  
  285. // Set target
  286. target_zone = zone;
  287.  
  288. // Update the GUI
  289. gui.updateStatus(true);
  290. gui.updateZone(zone, data.response.zone_info.capture_progress, data.response.zone_info.difficulty);
  291. gui.updateEstimatedTime(calculateTimeToNextLevel());
  292.  
  293. current_game_id = data.response.zone_info.gameid;
  294. current_game_start = new Date().getTime();
  295.  
  296. if (auto_switch_planet.active == true) {
  297. if (auto_switch_planet.current_difficulty != data.response.zone_info.difficulty)
  298. auto_switch_planet.current_round = 0; // Difficulty changed, reset rounds counter before new planet check
  299.  
  300. auto_switch_planet.current_difficulty = data.response.zone_info.difficulty;
  301.  
  302. if (auto_switch_planet.current_difficulty < auto_switch_planet.wanted_difficulty) {
  303. if (auto_switch_planet.current_round >= auto_switch_planet.rounds_before_check) {
  304. auto_switch_planet.current_round = 0;
  305. CheckSwitchBetterPlanet(true);
  306. } else {
  307. auto_switch_planet.current_round++;
  308. }
  309. }
  310. }
  311.  
  312. INJECT_wait_for_end(resend_frequency);
  313. }
  314. },
  315. error: function (xhr, ajaxOptions, thrownError) {
  316. var messagesArray = ["start the round", "starting round"];
  317. var ajaxParams = {
  318. xhr: xhr,
  319. ajaxOptions: ajaxOptions,
  320. thrownError: thrownError
  321. };
  322. ajaxErrorHandling(this, ajaxParams, messagesArray);
  323. }
  324. });
  325. }
  326.  
  327. // Update time remaining, and wait for the round to complete.
  328. var INJECT_wait_for_end = function() {
  329. var now = new Date().getTime();
  330. time_passed_ms = now - current_game_start;
  331. var time_remaining_ms = (resend_frequency*1000) - time_passed_ms;
  332. var time_remaining = Math.round(time_remaining_ms/1000);
  333.  
  334. // Update GUI
  335. gui.updateTask("Waiting " + Math.max(time_remaining, 0) + "s for round to end", false);
  336. gui.updateStatus(true);
  337. if (target_zone != -1)
  338. gui.updateEstimatedTime(calculateTimeToNextLevel());
  339. gui.progressbar.SetValue(time_passed_ms/(resend_frequency*1000));
  340.  
  341. // Wait
  342. var wait_time = update_length*1000;
  343. var callback;
  344.  
  345. // use absolute timestamps to calculate if the game is over, since setTimeout timings are not always reliable
  346. if(time_remaining_ms <= 0) {
  347. callback = function() { INJECT_end_round(); };
  348. }
  349. else {
  350. callback = function() { INJECT_wait_for_end(); };
  351. }
  352.  
  353. // Set the timeout
  354. clearTimeout(current_timeout);
  355. current_timeout = setTimeout(callback, wait_time);
  356. }
  357.  
  358. // Send the call to end a round, and restart if needed.
  359. var INJECT_end_round = function(attempt_no) {
  360. if(attempt_no === undefined)
  361. attempt_no = 0;
  362.  
  363. // Grab the max score we're allowed to send
  364. var score = get_max_score();
  365.  
  366. // Update gui
  367. gui.updateTask("Ending Round");
  368.  
  369. // Post our "Yay we beat the level" call
  370. $J.ajax({
  371. async: false,
  372. type: "POST",
  373. url: "https://community.steam-api.com/ITerritoryControlMinigameService/ReportScore/v0001/",
  374. data: { access_token: access_token, score: score, language: language },
  375. tryCount : 0,
  376. retryLimit : max_retry,
  377. success: function(data) {
  378. if( $J.isEmptyObject(data.response) ) {
  379. // Check if the zone is completed
  380. INJECT_update_grid(false); // Error handling set to false to avoid too much parallel calls with the setTimeout below
  381. if(window.gGame.m_State.m_Grid.m_Tiles[target_zone].Info.captured || attempt_no >= max_retry) {
  382. if (auto_switch_planet.active == true)
  383. CheckSwitchBetterPlanet();
  384. else
  385. SwitchNextZone();
  386. }
  387. else {
  388. console.log("Error getting zone response (on end):",data);
  389. gui.updateTask("Waiting 5s and re-sending score (Attempt #" + (attempt_no + 1) + ").");
  390. clearTimeout(current_timeout);
  391. current_timeout = setTimeout(function() { INJECT_end_round(attempt_no+1); }, 5000);
  392. }
  393. }
  394. else {
  395. console.log("Successfully finished the round and got expected data back:");
  396. console.log("Level: ", data.response.new_level, "\nEXP: ", data.response.new_score);
  397. console.log(data);
  398.  
  399. // Update the player info
  400. INJECT_update_player_info();
  401.  
  402. // Update GUI
  403. gui.updateLevel(data.response.new_level);
  404. gui.updateExp(data.response.new_score + " / " + data.response.next_level_score);
  405. gui.updateEstimatedTime(calculateTimeToNextLevel());
  406. gui.updateZone("None");
  407.  
  408. // Restart the round if we have that variable set
  409. if(loop_rounds) {
  410. current_game_id = undefined;
  411. INJECT_start_round(target_zone, access_token)
  412. }
  413. }
  414. },
  415. error: function (xhr, ajaxOptions, thrownError) {
  416. var messagesArray = ["end the round", "ending round"];
  417. var ajaxParams = {
  418. xhr: xhr,
  419. ajaxOptions: ajaxOptions,
  420. thrownError: thrownError
  421. };
  422. ajaxErrorHandling(this, ajaxParams, messagesArray);
  423. }
  424. });
  425. }
  426.  
  427. // Leave an existing game
  428. var INJECT_leave_round = function() {
  429. if(current_game_id === undefined)
  430. return;
  431.  
  432. console.log("Leaving game: " + current_game_id);
  433.  
  434. // Cancel timeouts
  435. clearTimeout(current_timeout);
  436.  
  437. // POST to the endpoint
  438. $J.ajax({
  439. async: false,
  440. type: "POST",
  441. url: "https://community.steam-api.com/IMiniGameService/LeaveGame/v0001/",
  442. data: { access_token: access_token, gameid: current_game_id },
  443. tryCount : 0,
  444. retryLimit : max_retry,
  445. success: function(data) {},
  446. error: function (xhr, ajaxOptions, thrownError) {
  447. var messagesArray = ["leave the round", "leaving round"];
  448. var ajaxParams = {
  449. xhr: xhr,
  450. ajaxOptions: ajaxOptions,
  451. thrownError: thrownError
  452. };
  453. ajaxErrorHandling(this, ajaxParams, messagesArray);
  454. }
  455. });
  456.  
  457. // Clear the current game ID var
  458. current_game_id = undefined;
  459.  
  460. // Update the GUI
  461. gui.updateTask("Left Zone #" + target_zone);
  462. gui.updateStatus(false);
  463.  
  464. target_zone = -1;
  465. }
  466.  
  467. // returns 0 for easy, 1 for medium, 2 for hard
  468. var INJECT_get_difficulty = function(zone_id) {
  469. return window.gGame.m_State.m_PlanetData.zones[zone_id].difficulty;
  470. }
  471.  
  472. // Updates the player info
  473. // Currently unused. This was meant to hopefully update the UI.
  474. var INJECT_update_player_info = function() {
  475. gServer.GetPlayerInfo(
  476. function( results ) {
  477. gPlayerInfo = results.response;
  478. },
  479. function(){}
  480. );
  481. }
  482.  
  483. // Update the zones of the grid (map) on the current planet
  484. var INJECT_update_grid = function(error_handling) {
  485. if(current_planet_id === undefined)
  486. return;
  487. if (error_handling === undefined)
  488. error_handling = true;
  489.  
  490. // Skip update if a previous successful one happened in the last 8s
  491. if (last_update_grid !== undefined) {
  492. var last_update_diff = new Date().getTime() - last_update_grid;
  493. if ((last_update_diff / 1000) < 8)
  494. return;
  495. }
  496.  
  497. gui.updateTask('Updating grid', true);
  498.  
  499. // GET to the endpoint
  500. $J.ajax({
  501. async: false,
  502. type: "GET",
  503. url: "https://community.steam-api.com/ITerritoryControlMinigameService/GetPlanet/v0001/",
  504. data: { id: current_planet_id },
  505. tryCount : 0,
  506. retryLimit : max_retry,
  507. success: function(data) {
  508. window.gGame.m_State.m_PlanetData = data.response.planets[0];
  509. window.gGame.m_State.m_PlanetData.zones.forEach( function ( zone ) {
  510. window.gGame.m_State.m_Grid.m_Tiles[zone.zone_position].Info.progress = zone.capture_progress;
  511. window.gGame.m_State.m_Grid.m_Tiles[zone.zone_position].Info.captured = zone.captured;
  512. window.gGame.m_State.m_Grid.m_Tiles[zone.zone_position].Info.difficulty = zone.difficulty;
  513. });
  514. last_update_grid = new Date().getTime();
  515. console.log("Successfully updated map data on planet: " + current_planet_id);
  516. },
  517. error: function (xhr, ajaxOptions, thrownError) {
  518. if (error_handling == true) {
  519. var messagesArray = ["update the grid", "updating the grid"];
  520. var ajaxParams = {
  521. xhr: xhr,
  522. ajaxOptions: ajaxOptions,
  523. thrownError: thrownError
  524. };
  525. ajaxErrorHandling(this, ajaxParams, messagesArray);
  526. }
  527. }
  528. });
  529. }
  530.  
  531. // Defaults to max score of current zone & full round duration if no params are given
  532. function get_max_score(zone, round_duration) {
  533. // defaults
  534. if(zone === undefined)
  535. zone = target_zone;
  536. if(round_duration === undefined)
  537. round_duration = real_round_length;
  538.  
  539. var difficulty = INJECT_get_difficulty(zone);
  540. var score = 5 * round_duration * Math.pow(2, (difficulty-1));
  541.  
  542. return score;
  543. }
  544.  
  545. // Get the best zone available
  546. function GetBestZone() {
  547. var bestZoneIdx;
  548. var highestDifficulty = -1;
  549.  
  550. gui.updateTask('Getting best zone');
  551.  
  552. for (var idx = 0; idx < window.gGame.m_State.m_Grid.m_Tiles.length; idx++) {
  553. var zone = window.gGame.m_State.m_Grid.m_Tiles[idx].Info;
  554. if (!zone.captured && !zone.boss && zone.progress > 0) {
  555. /*if (zone.boss) {
  556. console.log("Zone " + idx + " with boss. Switching to it.");
  557. return idx;
  558. }*/
  559.  
  560. if(zone.difficulty > highestDifficulty) {
  561. highestDifficulty = zone.difficulty;
  562. maxProgress = zone.progress;
  563. bestZoneIdx = idx;
  564. } else if(zone.difficulty < highestDifficulty) continue;
  565.  
  566. if(zone.progress < maxProgress) {
  567. maxProgress = zone.progress;
  568. bestZoneIdx = idx;
  569. }
  570. }
  571. }
  572.  
  573. if(bestZoneIdx !== undefined) {
  574. console.log(`${window.gGame.m_State.m_PlanetData.state.name} - Zone ${bestZoneIdx} Progress: ${window.gGame.m_State.m_Grid.m_Tiles[bestZoneIdx].Info.progress} Difficulty: ${window.gGame.m_State.m_Grid.m_Tiles[bestZoneIdx].Info.difficulty}`);
  575. }
  576.  
  577. return bestZoneIdx;
  578. }
  579.  
  580. // Get the best planet available
  581. function GetBestPlanet() {
  582. // No need to move if we're already in a zone with the wanted difficulty
  583. if(auto_switch_planet.current_difficulty == auto_switch_planet.wanted_difficulty)
  584. return current_planet_id;
  585. var bestPlanetId = undefined;
  586. var activePlanetsScore = [];
  587. var planetsMaxDifficulty = [];
  588. var maxScore = 0;
  589. var numberErrors = 0;
  590.  
  591. gui.updateStatus('Getting best planet');
  592.  
  593. // GET to the endpoint
  594. $J.ajax({
  595. async: false,
  596. type: "GET",
  597. url: "https://community.steam-api.com/ITerritoryControlMinigameService/GetPlanets/v0001/",
  598. tryCount : 0,
  599. retryLimit : max_retry,
  600. success: function(data) {
  601. data.response.planets.forEach( function(planet) {
  602. if (planet.state.active == true && planet.state.captured == false)
  603. activePlanetsScore[planet.id] = 0;
  604. planetsMaxDifficulty[planet.id] = 0;
  605. });
  606. },
  607. error: function (xhr, ajaxOptions, thrownError) {
  608. var messagesArray = ["get active planets", "getting active planets"];
  609. var ajaxParams = {
  610. xhr: xhr,
  611. ajaxOptions: ajaxOptions,
  612. thrownError: thrownError
  613. };
  614. ajaxErrorHandling(this, ajaxParams, messagesArray);
  615. }
  616. });
  617.  
  618. // GET the score of each active planet
  619. Object.keys(activePlanetsScore).forEach ( function (planet_id) {
  620. // GET to the endpoint
  621. $J.ajax({
  622. async: false,
  623. type: "GET",
  624. url: "https://community.steam-api.com/ITerritoryControlMinigameService/GetPlanet/v0001/",
  625. data: { id: planet_id },
  626. success: function(data) {
  627. data.response.planets[0].zones.forEach( function ( zone ) {
  628. if (zone.difficulty >= 1 && zone.difficulty <= 7 && zone.captured == false) {
  629. var zoneProgress = (zone.capture_progress === undefined) ? 0 : zone.capture_progress;
  630. var zoneScore = Math.ceil(Math.pow(10, (zone.difficulty - 1) * 2) * (1 - zoneProgress));
  631. activePlanetsScore[planet_id] += isNaN(zoneScore) ? 0 : zoneScore;
  632. if (zone.difficulty > planetsMaxDifficulty[planet_id])
  633. planetsMaxDifficulty[planet_id] = zone.difficulty;
  634. }
  635. });
  636. },
  637. error: function() {
  638. numberErrors++;
  639. }
  640. });
  641. if (activePlanetsScore[planet_id] > maxScore) {
  642. maxScore = activePlanetsScore[planet_id];
  643. bestPlanetId = planet_id;
  644. }
  645. });
  646. console.log(activePlanetsScore);
  647.  
  648. // Check if the maximum difficulty available on the best planet is the same as the current one
  649. // If yes, no need to move. Except if max difficulty = 1 and score <= 20, we'll rush it for a new planet
  650. if ((current_planet_id in activePlanetsScore) && planetsMaxDifficulty[bestPlanetId] <= auto_switch_planet.current_difficulty) {
  651. var lowScorePlanet = activePlanetsScore.findIndex(function(score) { return score <= 20; });
  652. if (planetsMaxDifficulty[bestPlanetId] == 1 && lowScorePlanet !== -1) {
  653. return lowScorePlanet;
  654. } else {
  655. return current_planet_id;
  656. }
  657. }
  658.  
  659. // Prevent a planet switch if :
  660. // (there were >= 2 errors while fetching planets OR if there's an error while fetching the current planet score)
  661. // AND the max difficulty available on best planet found is <= current difficulty
  662. if ((numberErrors >= 2 || ((current_planet_id in activePlanetsScore) && activePlanetsScore[current_planet_id] == 0)) && planetsMaxDifficulty[bestPlanetId] <= auto_switch_planet.current_difficulty)
  663. return null;
  664.  
  665. return bestPlanetId;
  666. }
  667.  
  668. // Switch to the next zone when one is completed
  669. function SwitchNextZone(attempt_no, planet_call) {
  670. if(attempt_no === undefined)
  671. attempt_no = 0;
  672. if (planet_call === undefined)
  673. planet_call = false;
  674.  
  675. INJECT_update_grid();
  676. var next_zone = GetBestZone();
  677.  
  678. if (next_zone !== undefined) {
  679. if (next_zone != target_zone) {
  680. console.log("Found new best zone: " + next_zone);
  681. INJECT_start_round(next_zone, access_token, attempt_no);
  682. } else {
  683. console.log("Current zone #" + target_zone + " is already the best. No need to switch.");
  684. //if (planet_call === true)
  685. INJECT_start_round(target_zone, access_token, attempt_no);
  686. }
  687. } else {
  688. if (auto_switch_planet.active == true) {
  689. console.log("There are no more zones, the planet must be completed. Searching a new one.");
  690. CheckSwitchBetterPlanet();
  691. } else {
  692. INJECT_leave_round();
  693. INJECT_update_grid();
  694. console.log("There are no more zones, the planet must be completed. You'll need to choose another planet!");
  695. target_zone = -1;
  696. INJECT_leave_planet();
  697. }
  698. }
  699. }
  700.  
  701. // Check & switch for a potentially better planet, start to the best available zone
  702. function CheckSwitchBetterPlanet(difficulty_call) {
  703. if (difficulty_call === undefined)
  704. difficulty_call = false;
  705.  
  706. var best_planet = GetBestPlanet();
  707.  
  708. var now = new Date().getTime();
  709. var lastGameStart = (current_game_start === undefined) ? now : current_game_start;
  710. var timeDiff = (now - lastGameStart) / 1000;
  711.  
  712. if (best_planet !== undefined && best_planet !== null && best_planet != current_planet_id) {
  713. console.log("Planet #" + best_planet + " has higher XP potential. Switching to it. Bye planet #" + current_planet_id);
  714. INJECT_switch_planet(best_planet, function() {
  715. target_zone = GetBestZone();
  716. INJECT_start_round(target_zone, access_token);
  717. });
  718. } else if (best_planet == current_planet_id) {
  719. if ((timeDiff >= 8 && difficulty_call == true) || difficulty_call == false)
  720. SwitchNextZone(0, difficulty_call);
  721. } else if (best_planet === null) {
  722. console.log("Too many errors while searching a better planet. Let's continue on the current zone.");
  723. if ((timeDiff >= 8 && difficulty_call == true) || difficulty_call == false)
  724. INJECT_start_round(target_zone, access_token);
  725. } else {
  726. console.log("There's no planet better than the current one.");
  727. }
  728. }
  729.  
  730. var INJECT_switch_planet = function(planet_id, callback) {
  731. // ONLY usable from battle selection, if at planet selection, run join instead
  732. if(gGame.m_State instanceof CPlanetSelectionState)
  733. join_planet_helper(planet_id);
  734. if(!(gGame.m_State instanceof CBattleSelectionState))
  735. return;
  736.  
  737. gui.updateTask("Attempting to move to Planet #" + planet_id);
  738.  
  739. // Leave our current round if we haven't.
  740. INJECT_leave_round();
  741.  
  742. // Leave the planet
  743. INJECT_leave_planet(function() {
  744. // Join Planet
  745. join_planet_helper(planet_id);
  746. });
  747.  
  748. function wait_for_state_load() {
  749. if(gGame.m_IsStateLoading || gGame.m_State instanceof CPlanetSelectionState) {
  750. clearTimeout(current_timeout);
  751. current_timeout = setTimeout(function() { wait_for_state_load(); }, 50);
  752. }
  753. else
  754. callback();
  755. }
  756.  
  757. function join_planet_helper(planet_id) {
  758. // Make sure the planet_id is valid (or we'll error out)
  759. var valid_planets = gGame.m_State.m_rgPlanets;
  760. var found = false;
  761. for(var i=0; i<valid_planets.length; i++)
  762. if (valid_planets[i].id == planet_id)
  763. found = true;
  764. if(!found) {
  765. gui.updateTask("Attempted to switch to an invalid planet. Please choose a new one.");
  766. gui.updateStatus(false);
  767. return;
  768. }
  769.  
  770. INJECT_join_planet(planet_id,
  771. function ( response ) {
  772. gGame.ChangeState( new CBattleSelectionState( planet_id ) );
  773. wait_for_state_load();
  774. },
  775. function ( response ) {
  776. ShowAlertDialog( 'Join Planet Error', 'Failed to join planet. Please reload your game or try again shortly.' );
  777. });
  778. }
  779. }
  780.  
  781. // Leave the planet
  782. var INJECT_leave_planet = function(callback) {
  783. if(typeof callback !== 'function')
  784. callback = function() {};
  785.  
  786. function wait_for_state_load() {
  787. if(gGame.m_IsStateLoading || gGame.m_State instanceof CBattleSelectionState) {
  788. clearTimeout(current_timeout);
  789. current_timeout = setTimeout(function() { wait_for_state_load(); }, 50);
  790. }
  791. else {
  792. // Clear the current planet ID var
  793. current_planet_id = undefined;
  794.  
  795. INJECT_init();
  796.  
  797. // Restore old animation state
  798. INJECT_toggle_animations(anim_state);
  799.  
  800. callback();
  801. }
  802. }
  803.  
  804. // Cancel timeouts
  805. clearTimeout(current_timeout);
  806.  
  807. // Leave our current round if we haven't.
  808. INJECT_leave_round();
  809.  
  810. // Temporarily enable animations
  811. var anim_state = animations_enabled;
  812. INJECT_toggle_animations(true);
  813.  
  814. // (Modified) Default Code
  815. gAudioManager.PlaySound( 'ui_select_backwards' );
  816. gServer.LeaveGameInstance(
  817. gGame.m_State.m_PlanetData.id,
  818. function() {
  819. gGame.ChangeState( new CPlanetSelectionState() );
  820. // Wait for the new state to load, then hook in
  821. wait_for_state_load();
  822. }
  823. );
  824. }
  825.  
  826. var INJECT_join_planet = function(planet_id, success_callback, error_callback) {
  827. if(typeof success_callback !== 'function')
  828. success_callback = function() {};
  829. if(typeof error_callback !== 'function')
  830. error_callback = function() {};
  831.  
  832. function wait_for_state_load() {
  833. if(gGame.m_IsStateLoading || gGame.m_State instanceof CPlanetSelectionState) {
  834. clearTimeout(current_timeout);
  835. current_timeout = setTimeout(function() { wait_for_state_load(); }, 50);
  836. }
  837. else {
  838. current_planet_id = planet_id;
  839. INJECT_init();
  840.  
  841. // Restore old animation state
  842. INJECT_toggle_animations(anim_state);
  843. }
  844. }
  845.  
  846. // Modified Default code
  847. var rgParams = {
  848. id: planet_id,
  849. access_token: access_token
  850. };
  851.  
  852. // Temporarily enable animations
  853. var anim_state = animations_enabled;
  854. INJECT_toggle_animations(true);
  855.  
  856. $J.ajax({
  857. async: false,
  858. url: window.gServer.m_WebAPI.BuildURL( 'ITerritoryControlMinigameService', 'JoinPlanet', true ),
  859. method: 'POST',
  860. data: rgParams
  861. }).success( function( results, textStatus, request ) {
  862. if ( request.getResponseHeader( 'x-eresult' ) == 1 ) {
  863. success_callback( results );
  864. // Wait for the new state to load, then hook in
  865. wait_for_state_load();
  866. }
  867. else {
  868. console.log(results, textStatus, request);
  869. error_callback();
  870. }
  871. }).fail( error_callback );
  872. }
  873.  
  874. var INJECT_init_battle_selection = function() {
  875. // Update the GUI
  876. gui.updateStatus(true);
  877. gui.updateTask("Initializing Battle Selection Menu.");
  878.  
  879. // Check the game state for hangups occasionally
  880. if (check_game_state !== undefined)
  881. clearInterval(check_game_state);
  882. check_game_state = setInterval(checkUnlockGameState, 60000);
  883.  
  884. // Auto join best zone at first
  885. if (auto_first_join == true) {
  886. firstJoin();
  887. function firstJoin() {
  888. // Wait for state & access_token
  889. if(access_token === undefined || gGame === undefined || gGame.m_IsStateLoading || gGame.m_State instanceof CPlanetSelectionState) {
  890. clearTimeout(current_timeout);
  891. current_timeout = setTimeout(function() { firstJoin(); }, 100);
  892. console.log("waiting");
  893. return;
  894. }
  895.  
  896. current_planet_id = window.gGame.m_State.m_PlanetData.id;
  897.  
  898. var first_zone;
  899. if(target_zone === -1)
  900. first_zone = GetBestZone();
  901. else
  902. first_zone = target_zone
  903.  
  904. if(access_token === undefined)
  905. INJECT_get_access_token();
  906.  
  907. INJECT_start_round(first_zone, access_token);
  908. }
  909. }
  910.  
  911. // Overwrite join function so clicking on a grid square will run our code instead
  912. gServer.JoinZone = function (zone_id, callback, error_callback) {
  913. current_planet_id = window.gGame.m_State.m_PlanetData.id;
  914. INJECT_start_round(zone_id, access_token);
  915. }
  916.  
  917. // Hook the Grid click function
  918. var grid_click_default = gGame.m_State.m_Grid.click;
  919. gGame.m_State.m_Grid.click = function(tileX, tileY) {
  920. // Get the selected zone ID
  921. var zoneIdx = _GetTileIdx( tileX, tileY );
  922.  
  923. // Return if it's the current zone (Don't want clicking on same zone to leave/rejoin)
  924. if(target_zone === zoneIdx)
  925. return;
  926.  
  927. // Return if it's a completed zone
  928. if(window.gGame.m_State.m_Grid.m_Tiles[zoneIdx].Info.captured) {
  929. console.log("Manually selected zone already captured. Returning.");
  930. return;
  931. }
  932.  
  933. // Update the GUI
  934. gui.updateTask("Attempting manual switch to Zone #" + zoneIdx);
  935. gui.progressbar.parent.removeChild(gui.progressbar)
  936.  
  937. // Leave existing round
  938. INJECT_leave_round();
  939.  
  940. // Join new round
  941. INJECT_start_round(zoneIdx, access_token);
  942. }
  943.  
  944. // Hook the Leave Planet Button
  945. gGame.m_State.m_LeaveButton.click = function(btn) {
  946. INJECT_leave_planet();
  947. };
  948. }
  949.  
  950. var INJECT_init_planet_selection = function() {
  951. gui.updateStatus(true);
  952. gui.updateTask("Initializing Planet Selection Menu.");
  953.  
  954. // Hook the Join Planet Function
  955. gServer.JoinPlanet = function(planet_id, success_callback, error_callback) {
  956. INJECT_join_planet(planet_id, success_callback, error_callback);
  957. }
  958.  
  959. // Update GUI
  960. gui.updateStatus(false);
  961. gui.updateTask("At Planet Selection");
  962. gui.updateZone("None");
  963. };
  964.  
  965. var INJECT_init = function() {
  966. if (gGame.m_State instanceof CBattleSelectionState)
  967. INJECT_init_battle_selection();
  968. else if (gGame.m_State instanceof CPlanetSelectionState)
  969. INJECT_init_planet_selection();
  970. };
  971.  
  972. var INJECT_toggle_animations = function(enabled) {
  973.  
  974. if(enabled)
  975. {
  976. // Show canvas
  977. $J("canvas").show();
  978. // Enable animations
  979. gApp.ticker.start();
  980. }
  981. else
  982. {
  983. // Hide canvas
  984. $J("canvas").hide();
  985. // Disable animations
  986. gApp.ticker.stop();
  987. }
  988. animations_enabled=enabled;
  989. };
  990.  
  991. // Run initialization code on load
  992. $J(document).ready(function() {
  993. // Auto-grab the access token
  994. INJECT_get_access_token();
  995.  
  996. // Call our global init function
  997. initGUI();
  998. })
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement