Tiberium Alliances Formation Saver

Allows you to save attack formations

  1. // ==UserScript==
  2. // @name Tiberium Alliances Formation Saver
  3. // @description Allows you to save attack formations
  4. // @namespace https://prodgame*.alliances.commandandconquer.com/*/index.aspx*
  5. // @include https://prodgame*.alliances.commandandconquer.com/*/index.aspx*
  6. // @version 2.2
  7. // @author Panavia, KRS_L
  8. // ==/UserScript==
  9. (function () {
  10. var tafs_main = function () {
  11. var windowSaver;
  12.  
  13. function initialize() {
  14. console.log("Formation Saver Loaded");
  15.  
  16. qx.Class.define("webfrontend.gui.PlayArea.FormationSaver", {
  17. extend : qx.ui.container.Composite,
  18.  
  19. construct : function () {
  20. qx.ui.container.Composite.call(this);
  21. this.setLayout(new qx.ui.layout.Canvas());
  22. this.add(this.init());
  23. },
  24.  
  25. statics : {
  26. SaverCollapsedHeight : 48,
  27. SaverExpandedHeight : 245,
  28. },
  29.  
  30. properties : {
  31. expanded : {
  32. init : true,
  33. apply : "expand"
  34. },
  35. },
  36.  
  37. members : {
  38. buttonResize : null,
  39. containerContence : null,
  40. containerSaves : null,
  41. containerMain : null,
  42. buttonSave : null,
  43.  
  44. init : function () {
  45. this.buttonResize = new webfrontend.ui.SoundButton(null, "FactionUI/icons/icon_tracker_minimise.png").set({
  46. width : 20,
  47. height : 20,
  48. appearance : "button-notif-cat",
  49. center : true,
  50. allowGrowX : false
  51. });
  52. this.buttonResize.addListener("click", function (e) {
  53. this.setExpanded(!this.getExpanded());
  54. }, this);
  55. var ba = new qx.ui.container.Composite(new qx.ui.layout.HBox().set({
  56. alignY : "middle"
  57. })).set({
  58. margin : 0,
  59. marginLeft : 6,
  60. marginRight : 9
  61. });
  62. ba.add(this.buttonResize);
  63. var labelTitle = new qx.ui.basic.Label("<b>Saver</b>");
  64. labelTitle.set({
  65. marginLeft : 4,
  66. rich : true
  67. });
  68. labelTitle.setTextColor("#FFFFFF");
  69. ba.add(labelTitle);
  70. this.containerContence = new qx.ui.container.Composite(new qx.ui.layout.VBox().set({
  71. alignX : "center"
  72. })).set({
  73. allowGrowX : true,
  74. margin : 0
  75. });
  76.  
  77. containerSaves = new qx.ui.container.Composite(new qx.ui.layout.Grid(10, 2)).set({
  78. allowGrowX : true,
  79. marginLeft : 0,
  80. marginBottom : 5
  81. });
  82. this.containerContence.add(containerSaves);
  83.  
  84. buttonSave = new qx.ui.form.Button("Save");
  85. buttonSave.set({
  86. width : 50,
  87. appearance : "button-text-small",
  88. toolTipText : "Save attack formation",
  89. allowGrowX : false
  90. });
  91. buttonSave.addListener("click", this.save, this);
  92. this.containerContence.add(buttonSave);
  93.  
  94. this.containerMain = new qx.ui.container.Composite(new qx.ui.layout.VBox().set({
  95. alignX : "right"
  96. })).set({
  97. maxHeight : webfrontend.gui.PlayArea.FormationSaver.SaverExpandedHeight,
  98. width : 75,
  99. minHeight : 32,
  100. allowShrinkY : true,
  101. decorator : new qx.ui.decoration.Decorator().set({
  102. borderImage : "webfrontend/ui/common/bgr_mission_tracker.png"
  103. })
  104. });
  105. this.containerMain.add(ba);
  106. this.containerMain.add(this.containerContence, {
  107. flex : 1
  108. });
  109.  
  110. return this.containerMain;
  111. },
  112.  
  113. expand : function (bs) {
  114. if (!bs) {
  115. this.buttonResize.setIcon("FactionUI/icons/icon_tracker_maximise.png");
  116. this.containerMain.setMaxHeight(webfrontend.gui.PlayArea.FormationSaver.SaverCollapsedHeight);
  117. } else {
  118. this.buttonResize.setIcon("FactionUI/icons/icon_tracker_minimise.png");
  119. this.containerMain.setMaxHeight(webfrontend.gui.PlayArea.FormationSaver.SaverExpandedHeight);
  120. }
  121. },
  122.  
  123. update : function () {
  124. containerSaves.removeAll();
  125.  
  126. var playerCities = ClientLib.Data.MainData.GetInstance().get_Cities();
  127. var currentOwnCity = playerCities.get_CurrentOwnCity();
  128. var cityID = playerCities.get_CurrentCity().get_Id();
  129. var ownCityID = currentOwnCity.get_Id();
  130.  
  131. var formations = this.loadFormations();
  132. if (!formations) {
  133. return;
  134. }
  135. if (!formations[cityID]) {
  136. return;
  137. }
  138. if (!formations[cityID][ownCityID]) {
  139. return;
  140. }
  141.  
  142. var i = 0;
  143. for (var id in formations[cityID][ownCityID]) {
  144. if (id != 0) {
  145. i++;
  146. var formation = formations[cityID][ownCityID][id];
  147. var date = new Date(Number(formation.t));
  148. var toolTipText = "<div><span style='float: left'><b>" + formation.n + "</b></span><span style='float: right'>&nbsp;&nbsp;&nbsp;&nbsp;" + date.getHours() + ":" + (date.getMinutes() <= 9 ? "0" : "") + date.getMinutes() + " " + date.getDate() + "/" + (date.getMonth() + 1) + "</span></div><div style='clear: both;'></div>";
  149. if (formation.cy != null) {
  150. toolTipText += formation.cy + "% Construction Yard</br>" + formation.df + "% Defense Facility</br>" + formation.ts + "% Troop Strength</br>" + this.formatSecondsAsTime(formation.r) + " Repair Time";
  151. }
  152.  
  153. var labelLoad = new qx.ui.basic.Label(formation.n);
  154. labelLoad.set({
  155. width : 40,
  156. allowGrowX : false,
  157. toolTipText : toolTipText
  158. });
  159. labelLoad.setTextColor("#FFFFFF");
  160. labelLoad.addListener("click", this.clickLoad(formation), this);
  161. labelLoad.addListener("mouseover", this.mouseover(labelLoad, "#BBBBBB"), this);
  162. labelLoad.addListener("mouseout", this.mouseout(labelLoad, "#FFFFFF"), this);
  163. containerSaves.add(labelLoad, {
  164. row : i,
  165. column : 1
  166. });
  167.  
  168. var labelDelete = new qx.ui.basic.Label("<b>X</b>");
  169. labelDelete.set({
  170. width : 10,
  171. allowGrowX : false,
  172. rich : true,
  173. toolTipText : "Delete " + formation.n
  174. });
  175. labelDelete.setTextColor("#881717");
  176. labelDelete.addListener("click", this.clickDeleteF(cityID, ownCityID, id), this);
  177. labelDelete.addListener("mouseover", this.mouseover(labelDelete, "#550909"), this);
  178. labelDelete.addListener("mouseout", this.mouseover(labelDelete, "#881717"), this);
  179. containerSaves.add(labelDelete, {
  180. row : i,
  181. column : 2
  182. });
  183. }
  184. }
  185. },
  186.  
  187. mouseover : function (label, color) {
  188. return function () {
  189. label.setTextColor(color);
  190. }
  191. },
  192.  
  193. mouseout : function (label, color) {
  194. return function () {
  195. label.setTextColor(color);
  196. }
  197. },
  198.  
  199. save : function () {
  200. try {
  201. var playerCities = ClientLib.Data.MainData.GetInstance().get_Cities();
  202. var currentOwnCity = playerCities.get_CurrentOwnCity();
  203. var cityID = playerCities.get_CurrentCity().get_Id();
  204. var ownCityID = currentOwnCity.get_Id();
  205.  
  206. var newFormation = new Object();
  207. newFormation.t = new Date().getTime().toString();
  208. newFormation.n = "";
  209. newFormation.l = new Array();
  210.  
  211. var formation = currentOwnCity.get_CityArmyFormationsManager().GetFormationByTargetBaseId(cityID);
  212. var armyUnits = formation.get_ArmyUnits();
  213. if (armyUnits == null) {
  214. console.log("tafs Error: You must move a unit befor saving!");
  215. return;
  216. }
  217. armyUnits = armyUnits.l;
  218. for (var i in armyUnits) {
  219. var unit = armyUnits[i];
  220. newFormation.l[i] = new Object();
  221. newFormation.l[i].x = unit.get_CoordX();
  222. newFormation.l[i].y = unit.get_CoordY();
  223. newFormation.l[i].e = unit.get_Enabled();
  224. }
  225.  
  226. var formations = this.loadFormations();
  227. if (!formations) {
  228. formations = new Object();
  229. }
  230. if (!formations[cityID]) {
  231. formations[cityID] = new Object();
  232. }
  233. if (!formations[cityID][ownCityID]) {
  234. formations[cityID][ownCityID] = new Array();
  235. formations[cityID][ownCityID][0] = 0;
  236. }
  237. formations[cityID][ownCityID][0]++;
  238. newFormation.n = "Save " + formations[cityID][ownCityID][0];
  239.  
  240. formations[cityID][ownCityID].push(newFormation);
  241. this.saveFormations(formations);
  242.  
  243. windowSaver.update();
  244. } catch (e) {
  245. console.log(e);
  246. }
  247. },
  248.  
  249. clickLoad : function (newFormation) {
  250. return function () {
  251. this.load(newFormation);
  252. }
  253. },
  254.  
  255. load : function (newFormation) {
  256. try {
  257. var playerCities = ClientLib.Data.MainData.GetInstance().get_Cities();
  258. var currentOwnCity = playerCities.get_CurrentOwnCity();
  259. var cityID = playerCities.get_CurrentCity().get_Id();
  260.  
  261. var formation = currentOwnCity.get_CityArmyFormationsManager().GetFormationByTargetBaseId(cityID);
  262. var armyUnits = formation.get_ArmyUnits();
  263. if (armyUnits == null) {
  264. console.log("tafs Error: You must move a unit befor loading!");
  265. return;
  266. }
  267. armyUnits = armyUnits.l;
  268.  
  269. for (var i in newFormation.l) {
  270. var unitData = newFormation.l[i];
  271. armyUnits[i].MoveBattleUnit(unitData.x, unitData.y);
  272. if (unitData.e != null) {
  273. if (armyUnits[i].set_Enabled_Original) {
  274. armyUnits[i].set_Enabled_Original(unitData.e);
  275. } else {
  276. armyUnits[i].set_Enabled(unitData.e);
  277. }
  278. }
  279. }
  280.  
  281. //formation.set_CurrentTargetBaseId(cityID);
  282. } catch (e) {
  283. console.log(e);
  284. }
  285. },
  286.  
  287. clickDeleteF : function (cityID, ownCityID, id) {
  288. return function () {
  289. this.deleteF(cityID, ownCityID, id);
  290. }
  291. },
  292.  
  293. deleteF : function (cityID, ownCityID, id) {
  294. var formations = this.loadFormations();
  295. if (!formations || !formations[cityID] || !formations[cityID][ownCityID])
  296. return;
  297.  
  298. formations[cityID][ownCityID].splice(id, 1);
  299. if (formations[cityID][ownCityID].length <= 1) {
  300. delete formations[cityID][ownCityID];
  301. }
  302. var i
  303. for (i in formations[cityID]) {
  304. if (formations[cityID].hasOwnProperty(i)) {
  305. break;
  306. }
  307. }
  308. if (!i)
  309. delete formations[cityID];
  310.  
  311. this.saveFormations(formations);
  312.  
  313. windowSaver.update();
  314. },
  315.  
  316. saveFormations : function (formations) {
  317. var data = JSON.stringify(formations);
  318. localStorage.formations = data;
  319. },
  320.  
  321. loadFormations : function () {
  322. var formations = localStorage.formations;
  323. return formations && JSON.parse(formations);
  324. },
  325.  
  326. formatSecondsAsTime : function (secs, format) {
  327. var hr = Math.floor(secs / 3600);
  328. var min = Math.floor((secs - (hr * 3600)) / 60);
  329. var sec = Math.floor(secs - (hr * 3600) - (min * 60));
  330.  
  331. if (hr < 10) {
  332. hr = "0" + hr;
  333. }
  334. if (min < 10) {
  335. min = "0" + min;
  336. }
  337. if (sec < 10) {
  338. sec = "0" + sec;
  339. }
  340.  
  341. return hr + ':' + min + ':' + sec;
  342. },
  343. }
  344. })
  345.  
  346. windowSaver = new webfrontend.gui.PlayArea.FormationSaver();
  347. windowSaver.hide();
  348. qx.core.Init.getApplication().getPlayArea().add(windowSaver, {
  349. top : 55,
  350. right : -2
  351. });
  352.  
  353. if (!ClientLib.Data.MainData.GetInstance().get_Cities().__tafs__set_CurrentOwnCityId) {
  354. ClientLib.Data.MainData.GetInstance().get_Cities().__tafs__set_CurrentOwnCityId = ClientLib.Data.MainData.GetInstance().get_Cities().set_CurrentOwnCityId;
  355. }
  356. ClientLib.Data.MainData.GetInstance().get_Cities().set_CurrentOwnCityId = function (a) {
  357. this.__tafs__set_CurrentOwnCityId(a);
  358. updateView();
  359. }
  360.  
  361. if (!ClientLib.Data.MainData.GetInstance().get_Cities().__tafs__set_CurrentCityId) {
  362. ClientLib.Data.MainData.GetInstance().get_Cities().__tafs__set_CurrentCityId = ClientLib.Data.MainData.GetInstance().get_Cities().set_CurrentCityId;
  363. }
  364. ClientLib.Data.MainData.GetInstance().get_Cities().set_CurrentCityId = function (a) {
  365. this.__tafs__set_CurrentCityId(a);
  366. updateView();
  367. }
  368.  
  369. function updateView() {
  370. switch (qx.core.Init.getApplication().getPlayArea().getViewMode()) {
  371. case ClientLib.Data.PlayerAreaViewMode.pavmCombatSetupDefense:
  372. case ClientLib.Data.PlayerAreaViewMode.pavmCombatSetupBase:
  373. windowSaver.update();
  374. windowSaver.show();
  375. break;
  376. default:
  377. windowSaver.hide();
  378. }
  379.  
  380. }
  381. }
  382.  
  383. function tafs_checkIfLoaded() {
  384. try {
  385. if (typeof qx != 'undefined') {
  386. a = qx.core.Init.getApplication(); // application
  387. mb = qx.core.Init.getApplication().getMenuBar();
  388. if (a && mb) {
  389. initialize();
  390. } else
  391. window.setTimeout(tafs_checkIfLoaded, 1000);
  392. } else {
  393. window.setTimeout(tafs_checkIfLoaded, 1000);
  394. }
  395. } catch (e) {
  396. if (typeof console != 'undefined')
  397. console.log(e);
  398. else if (window.opera)
  399. opera.postError(e);
  400. else
  401. GM_log(e);
  402. }
  403. }
  404.  
  405. if (/commandandconquer\.com/i.test(document.domain)) {
  406. window.setTimeout(tafs_checkIfLoaded, 1000);
  407. }
  408. }
  409.  
  410. // injecting, because there seem to be problems when creating game interface with unsafeWindow
  411. var tafsScript = document.createElement("script");
  412. tafsScript.innerHTML = "(" + tafs_main.toString() + ")();";
  413. tafsScript.type = "text/javascript";
  414. if (/commandandconquer\.com/i.test(document.domain)) {
  415. document.getElementsByTagName("head")[0].appendChild(tafsScript);
  416. }
  417. })();