C&C:TA CNCOpt Link Button

Creates a "CNCOpt" button when selecting a base in Command & Conquer: Tiberium Alliances. The share button takes you to http://cncopt.com/ and fills in the selected base information so you can analyze or share the base.

  1. // ==UserScript==
  2. // @version 1.7.7
  3. // @name C&C:TA CNCOpt Link Button
  4. // @namespace http://cncopt.com/
  5. // @icon http://cncopt.com/favicon.ico
  6. // @description Creates a "CNCOpt" button when selecting a base in Command & Conquer: Tiberium Alliances. The share button takes you to http://cncopt.com/ and fills in the selected base information so you can analyze or share the base.
  7. // @include http*://prodgame*.alliances.commandandconquer.com/*/index.aspx*
  8. // @include http*://*.cncopt.com/*
  9. // @include http*://cncopt.com/*
  10. // @grant GM_log
  11. // @grant GM_setValue
  12. // @grant GM_getValue
  13. // @grant GM_registerMenuCommand
  14. // @grant GM_xmlhttpRequest
  15. // @grant GM_updatingEnabled
  16. // @grant unsafeWindow
  17. // @contributor PythEch (http://http://userscripts.org/users/220246)
  18. // @contributor jerbri (http://userscripts.org/users/507954)
  19. // ==/UserScript==
  20. /*
  21.  
  22. 2013-03-03: Special thanks to jerbri for fixing this up so it worked again!
  23. 2012-11-25: Special thanks to PythEch for fixing this up so it worked again!
  24.  
  25. */
  26. var scity = null;
  27. var tcity = null;
  28. var tbase = null;
  29. try {
  30. unsafeWindow.__cncopt_version = "1.7.7";
  31. (function () {
  32. var cncopt_main = function () {
  33.  
  34. var defense_unit_map = {
  35. /* GDI Defense Units */"GDI_Wall": "w",
  36. "GDI_Cannon": "c",
  37. "GDI_Antitank Barrier": "t",
  38. "GDI_Barbwire": "b",
  39. "GDI_Turret": "m",
  40. "GDI_Flak": "f",
  41. "GDI_Art Inf": "r",
  42. "GDI_Art Air": "e",
  43. "GDI_Art Tank": "a",
  44. "GDI_Def_APC Guardian": "g",
  45. "GDI_Def_Missile Squad": "q",
  46. "GDI_Def_Pitbull": "p",
  47. "GDI_Def_Predator": "d",
  48. "GDI_Def_Sniper": "s",
  49. "GDI_Def_Zone Trooper": "z",
  50. /* Nod Defense Units */"NOD_Def_Antitank Barrier": "t",
  51. "NOD_Def_Art Air": "e",
  52. "NOD_Def_Art Inf": "r",
  53. "NOD_Def_Art Tank": "a",
  54. "NOD_Def_Attack Bike": "p",
  55. "NOD_Def_Barbwire": "b",
  56. "NOD_Def_Black Hand": "z",
  57. "NOD_Def_Cannon": "c",
  58. "NOD_Def_Confessor": "s",
  59. "NOD_Def_Flak": "f",
  60. "NOD_Def_MG Nest": "m",
  61. "NOD_Def_Militant Rocket Soldiers": "q",
  62. "NOD_Def_Reckoner": "g",
  63. "NOD_Def_Scorpion Tank": "d",
  64. "NOD_Def_Wall": "w",
  65.  
  66. /* Forgotten Defense Units */"FOR_Wall": "w",
  67. "FOR_Barbwire_VS_Inf": "b",
  68. "FOR_Barrier_VS_Veh": "t",
  69. "FOR_Inf_VS_Inf": "g",
  70. "FOR_Inf_VS_Veh": "r",
  71. "FOR_Inf_VS_Air": "q",
  72. "FOR_Sniper": "n",
  73. "FOR_Mammoth": "y",
  74. "FOR_Veh_VS_Inf": "o",
  75. "FOR_Veh_VS_Veh": "s",
  76. "FOR_Veh_VS_Air": "u",
  77. "FOR_Turret_VS_Inf": "m",
  78. "FOR_Turret_VS_Inf_ranged": "a",
  79. "FOR_Turret_VS_Veh": "v",
  80. "FOR_Turret_VS_Veh_ranged": "d",
  81. "FOR_Turret_VS_Air": "f",
  82. "FOR_Turret_VS_Air_ranged": "e",
  83. "": ""
  84. };
  85.  
  86. var offense_unit_map = {
  87. /* GDI Offense Units */"GDI_APC Guardian": "g",
  88. "GDI_Commando": "c",
  89. "GDI_Firehawk": "f",
  90. "GDI_Juggernaut": "j",
  91. "GDI_Kodiak": "k",
  92. "GDI_Mammoth": "m",
  93. "GDI_Missile Squad": "q",
  94. "GDI_Orca": "o",
  95. "GDI_Paladin": "a",
  96. "GDI_Pitbull": "p",
  97. "GDI_Predator": "d",
  98. "GDI_Riflemen": "r",
  99. "GDI_Sniper Team": "s",
  100. "GDI_Zone Trooper": "z",
  101.  
  102. /* Nod Offense Units */"NOD_Attack Bike": "b",
  103. "NOD_Avatar": "a",
  104. "NOD_Black Hand": "z",
  105. "NOD_Cobra": "r",
  106. "NOD_Commando": "c",
  107. "NOD_Confessor": "s",
  108. "NOD_Militant Rocket Soldiers": "q",
  109. "NOD_Militants": "m",
  110. "NOD_Reckoner": "k",
  111. "NOD_Salamander": "l",
  112. "NOD_Scorpion Tank": "o",
  113. "NOD_Specter Artilery": "p",
  114. "NOD_Venom": "v",
  115. "NOD_Vertigo": "t",
  116. "": ""
  117. };
  118.  
  119.  
  120. function findTechLayout(city) {
  121. for (var k in city) {
  122. //console.log(typeof(city[k]), "1.city[", k, "]", city[k])
  123. if ((typeof (city[k]) == "object") && city[k] && 0 in city[k] && 8 in city[k]) {
  124. if ((typeof (city[k][0]) == "object") && city[k][0] && city[k][0] && 0 in city[k][0] && 15 in city[k][0]) {
  125. if ((typeof (city[k][0][0]) == "object") && city[k][0][0] && "BuildingIndex" in city[k][0][0]) {
  126. return city[k];
  127. }
  128. }
  129. }
  130. }
  131. return null;
  132. }
  133.  
  134. function findBuildings(city) {
  135. var cityBuildings = city.get_CityBuildingsData();
  136. for (var k in cityBuildings) {
  137. if (PerforceChangelist >= 376877) {
  138. if ((typeof (cityBuildings[k]) === "object") && cityBuildings[k] && "d" in cityBuildings[k] && "c" in cityBuildings[k] && cityBuildings[k].c > 0) {
  139. return cityBuildings[k].d;
  140. }
  141. } else {
  142. if ((typeof (cityBuildings[k]) === "object") && cityBuildings[k] && "l" in cityBuildings[k]) {
  143. return cityBuildings[k].l;
  144. }
  145. }
  146. }
  147. }
  148.  
  149. function isOffenseUnit(unit) {
  150. return (unit.get_UnitGameData_Obj().n in offense_unit_map);
  151. }
  152.  
  153. function isDefenseUnit(unit) {
  154. return (unit.get_UnitGameData_Obj().n in defense_unit_map);
  155. }
  156.  
  157. function getUnitArrays(city) {
  158. var ret = [];
  159. for (var k in city) {
  160. if ((typeof (city[k]) == "object") && city[k]) {
  161. for (var k2 in city[k]) {
  162. if (PerforceChangelist >= 376877) {
  163. if ((typeof (city[k][k2]) == "object") && city[k][k2] && "d" in city[k][k2]) {
  164. var lst = city[k][k2].d;
  165. if ((typeof (lst) == "object") && lst) {
  166. for (var i in lst) {
  167. if (typeof (lst[i]) == "object" && lst[i] && "get_CurrentLevel" in lst[i]) {
  168. ret.push(lst);
  169. }
  170. }
  171. }
  172. }
  173. } else {
  174. if ((typeof (city[k][k2]) == "object") && city[k][k2] && "l" in city[k][k2]) {
  175. var lst = city[k][k2].l;
  176. if ((typeof (lst) == "object") && lst) {
  177. for (var i in lst) {
  178. if (typeof (lst[i]) == "object" && lst[i] && "get_CurrentLevel" in lst[i]) {
  179. ret.push(lst);
  180. }
  181. }
  182. }
  183. }
  184. }
  185. }
  186. }
  187. }
  188. return ret;
  189. }
  190.  
  191. function getDefenseUnits(city) {
  192. var arr = getUnitArrays(city);
  193. for (var i = 0; i < arr.length; ++i) {
  194. for (var j in arr[i]) {
  195. if (isDefenseUnit(arr[i][j])) {
  196. return arr[i];
  197. }
  198. }
  199. }
  200. return [];
  201. }
  202.  
  203. function getOffenseUnits(city) {
  204. var arr = getUnitArrays(city);
  205. for (var i = 0; i < arr.length; ++i) {
  206. for (var j in arr[i]) {
  207. if (isOffenseUnit(arr[i][j])) {
  208. return arr[i];
  209. }
  210. }
  211. }
  212. return [];
  213. }
  214.  
  215.  
  216. function cncopt_create() {
  217. console.log("CNCOpt Link Button v" + window.__cncopt_version + " loaded");
  218. var cncopt = {
  219. selected_base: null,
  220. keymap: {
  221. /* GDI Buildings */"GDI_Accumulator": "a",
  222. "GDI_Refinery": "r",
  223. "GDI_Trade Center": "u",
  224. "GDI_Silo": "s",
  225. "GDI_Power Plant": "p",
  226. "GDI_Construction Yard": "y",
  227. "GDI_Airport": "d",
  228. "GDI_Barracks": "b",
  229. "GDI_Factory": "f",
  230. "GDI_Defense HQ": "q",
  231. "GDI_Defense Facility": "w",
  232. "GDI_Command Center": "e",
  233. "GDI_Support_Art": "z",
  234. "GDI_Support_Air": "x",
  235. "GDI_Support_Ion": "i",
  236. /* Forgotten Buildings */"FOR_Silo": "s",
  237. "FOR_Refinery": "r",
  238. "FOR_Tiberium Booster": "b",
  239. "FOR_Crystal Booster": "v",
  240. "FOR_Trade Center": "u",
  241. "FOR_Defense Facility": "w",
  242. "FOR_Construction Yard": "y",
  243. "FOR_Harvester_Tiberium": "h",
  244. "FOR_Defense HQ": "q",
  245. "FOR_Harvester_Crystal": "n",
  246. /* Nod Buildings */"NOD_Refinery": "r",
  247. "NOD_Power Plant": "p",
  248. "NOD_Harvester": "h",
  249. "NOD_Construction Yard": "y",
  250. "NOD_Airport": "d",
  251. "NOD_Trade Center": "u",
  252. "NOD_Defense HQ": "q",
  253. "NOD_Barracks": "b",
  254. "NOD_Silo": "s",
  255. "NOD_Factory": "f",
  256. "NOD_Harvester_Crystal": "n",
  257. "NOD_Command Post": "e",
  258. "NOD_Support_Art": "z",
  259. "NOD_Support_Ion": "i",
  260. "NOD_Accumulator": "a",
  261. "NOD_Support_Air": "x",
  262. "NOD_Defense Facility": "w",
  263. //"NOD_Tech Lab": "",
  264. //"NOD_Recruitment Hub": "X",
  265. //"NOD_Temple of Nod": "X",
  266.  
  267. /* GDI Defense Units */"GDI_Wall": "w",
  268. "GDI_Cannon": "c",
  269. "GDI_Antitank Barrier": "t",
  270. "GDI_Barbwire": "b",
  271. "GDI_Turret": "m",
  272. "GDI_Flak": "f",
  273. "GDI_Art Inf": "r",
  274. "GDI_Art Air": "e",
  275. "GDI_Art Tank": "a",
  276. "GDI_Def_APC Guardian": "g",
  277. "GDI_Def_Missile Squad": "q",
  278. "GDI_Def_Pitbull": "p",
  279. "GDI_Def_Predator": "d",
  280. "GDI_Def_Sniper": "s",
  281. "GDI_Def_Zone Trooper": "z",
  282. /* Nod Defense Units */"NOD_Def_Antitank Barrier": "t",
  283. "NOD_Def_Art Air": "e",
  284. "NOD_Def_Art Inf": "r",
  285. "NOD_Def_Art Tank": "a",
  286. "NOD_Def_Attack Bike": "p",
  287. "NOD_Def_Barbwire": "b",
  288. "NOD_Def_Black Hand": "z",
  289. "NOD_Def_Cannon": "c",
  290. "NOD_Def_Confessor": "s",
  291. "NOD_Def_Flak": "f",
  292. "NOD_Def_MG Nest": "m",
  293. "NOD_Def_Militant Rocket Soldiers": "q",
  294. "NOD_Def_Reckoner": "g",
  295. "NOD_Def_Scorpion Tank": "d",
  296. "NOD_Def_Wall": "w",
  297.  
  298. /* Forgotten Defense Units */"FOR_Wall": "w",
  299. "FOR_Barbwire_VS_Inf": "b",
  300. "FOR_Barrier_VS_Veh": "t",
  301. "FOR_Inf_VS_Inf": "g",
  302. "FOR_Inf_VS_Veh": "r",
  303. "FOR_Inf_VS_Air": "q",
  304. "FOR_Sniper": "n",
  305. "FOR_Mammoth": "y",
  306. "FOR_Veh_VS_Inf": "o",
  307. "FOR_Veh_VS_Veh": "s",
  308. "FOR_Veh_VS_Air": "u",
  309. "FOR_Turret_VS_Inf": "m",
  310. "FOR_Turret_VS_Inf_ranged": "a",
  311. "FOR_Turret_VS_Veh": "v",
  312. "FOR_Turret_VS_Veh_ranged": "d",
  313. "FOR_Turret_VS_Air": "f",
  314. "FOR_Turret_VS_Air_ranged": "e",
  315.  
  316. /* GDI Offense Units */"GDI_APC Guardian": "g",
  317. "GDI_Commando": "c",
  318. "GDI_Firehawk": "f",
  319. "GDI_Juggernaut": "j",
  320. "GDI_Kodiak": "k",
  321. "GDI_Mammoth": "m",
  322. "GDI_Missile Squad": "q",
  323. "GDI_Orca": "o",
  324. "GDI_Paladin": "a",
  325. "GDI_Pitbull": "p",
  326. "GDI_Predator": "d",
  327. "GDI_Riflemen": "r",
  328. "GDI_Sniper Team": "s",
  329. "GDI_Zone Trooper": "z",
  330.  
  331. /* Nod Offense Units */"NOD_Attack Bike": "b",
  332. "NOD_Avatar": "a",
  333. "NOD_Black Hand": "z",
  334. "NOD_Cobra": "r",
  335. "NOD_Commando": "c",
  336. "NOD_Confessor": "s",
  337. "NOD_Militant Rocket Soldiers": "q",
  338. "NOD_Militants": "m",
  339. "NOD_Reckoner": "k",
  340. "NOD_Salamander": "l",
  341. "NOD_Scorpion Tank": "o",
  342. "NOD_Specter Artilery": "p",
  343. "NOD_Venom": "v",
  344. "NOD_Vertigo": "t",
  345.  
  346. "<last>": "."
  347. },
  348. make_sharelink: function () {
  349. try {
  350. var selected_base = cncopt.selected_base;
  351. var city_id = selected_base.get_Id();
  352. var city = ClientLib.Data.MainData.GetInstance().get_Cities().GetCity(city_id);
  353. var own_city = ClientLib.Data.MainData.GetInstance().get_Cities().get_CurrentOwnCity();
  354. var alliance = ClientLib.Data.MainData.GetInstance().get_Alliance();
  355. var server = ClientLib.Data.MainData.GetInstance().get_Server();
  356. tbase = selected_base;
  357. tcity = city;
  358. scity = own_city;
  359. //console.log("Target City: ", city);
  360. //console.log("Own City: ", own_city);
  361. var link = "http://cncopt.com/?map=";
  362. link += "3|"; /* link version */
  363. switch (city.get_CityFaction()) {
  364. case 1:
  365. /* GDI */
  366. link += "G|";
  367. break;
  368. case 2:
  369. /* NOD */
  370. link += "N|";
  371. break;
  372. case 3:
  373. /* FOR faction - unseen, but in GAMEDATA */
  374. case 4:
  375. /* Forgotten Bases */
  376. case 5:
  377. /* Forgotten Camps */
  378. case 6:
  379. /* Forgotten Outposts */
  380. link += "F|";
  381. break;
  382. default:
  383. console.log("cncopt: Unknown faction: " + city.get_CityFaction());
  384. link += "E|";
  385. break;
  386. }
  387. switch (own_city.get_CityFaction()) {
  388. case 1:
  389. /* GDI */
  390. link += "G|";
  391. break;
  392. case 2:
  393. /* NOD */
  394. link += "N|";
  395. break;
  396. case 3:
  397. /* FOR faction - unseen, but in GAMEDATA */
  398. case 4:
  399. /* Forgotten Bases */
  400. case 5:
  401. /* Forgotten Camps */
  402. case 6:
  403. /* Forgotten Outposts */
  404. link += "F|";
  405. break;
  406. default:
  407. console.log("cncopt: Unknown faction: " + own_city.get_CityFaction());
  408. link += "E|";
  409. break;
  410. }
  411. link += city.get_Name() + "|";
  412. defense_units = []
  413. for (var i = 0; i < 20; ++i) {
  414. var col = [];
  415. for (var j = 0; j < 9; ++j) {
  416. col.push(null);
  417. }
  418. defense_units.push(col)
  419. }
  420. var defense_unit_list = getDefenseUnits(city);
  421. if (PerforceChangelist >= 376877) {
  422. for (var i in defense_unit_list) {
  423. var unit = defense_unit_list[i];
  424. defense_units[unit.get_CoordX()][unit.get_CoordY() + 8] = unit;
  425. }
  426. } else {
  427. for (var i = 0; i < defense_unit_list.length; ++i) {
  428. var unit = defense_unit_list[i];
  429. defense_units[unit.get_CoordX()][unit.get_CoordY() + 8] = unit;
  430. }
  431. }
  432.  
  433. offense_units = []
  434. for (var i = 0; i < 20; ++i) {
  435. var col = [];
  436. for (var j = 0; j < 9; ++j) {
  437. col.push(null);
  438. }
  439. offense_units.push(col)
  440. }
  441.  
  442. var offense_unit_list = getOffenseUnits(own_city);
  443. if (PerforceChangelist >= 376877) {
  444. for (var i in offense_unit_list) {
  445. var unit = offense_unit_list[i];
  446. offense_units[unit.get_CoordX()][unit.get_CoordY() + 16] = unit;
  447. }
  448. } else {
  449. for (var i = 0; i < offense_unit_list.length; ++i) {
  450. var unit = offense_unit_list[i];
  451. offense_units[unit.get_CoordX()][unit.get_CoordY() + 16] = unit;
  452. }
  453. }
  454.  
  455. var techLayout = findTechLayout(city);
  456. var buildings = findBuildings(city);
  457. for (var i = 0; i < 20; ++i) {
  458. row = [];
  459. for (var j = 0; j < 9; ++j) {
  460. var spot = i > 16 ? null : techLayout[j][i];
  461. var level = 0;
  462. var building = null;
  463. if (spot && spot.BuildingIndex >= 0) {
  464. building = buildings[spot.BuildingIndex];
  465. level = building.get_CurrentLevel();
  466. }
  467. var defense_unit = defense_units[j][i];
  468. if (defense_unit) {
  469. level = defense_unit.get_CurrentLevel();
  470. }
  471. var offense_unit = offense_units[j][i];
  472. if (offense_unit) {
  473. level = offense_unit.get_CurrentLevel();
  474. }
  475. if (level > 1) {
  476. link += level;
  477. }
  478.  
  479. switch (i > 16 ? 0 : city.GetResourceType(j, i)) {
  480. case 0:
  481. if (building) {
  482. var techId = building.get_MdbBuildingId();
  483. if (GAMEDATA.Tech[techId].n in cncopt.keymap) {
  484. link += cncopt.keymap[GAMEDATA.Tech[techId].n];
  485. } else {
  486. console.log("cncopt [5]: Unhandled building: " + techId, building);
  487. link += ".";
  488. }
  489. } else if (defense_unit) {
  490. if (defense_unit.get_UnitGameData_Obj().n in cncopt.keymap) {
  491. link += cncopt.keymap[defense_unit.get_UnitGameData_Obj().n];
  492. } else {
  493. console.log("cncopt [5]: Unhandled unit: " + defense_unit.get_UnitGameData_Obj().n);
  494. link += ".";
  495. }
  496. } else if (offense_unit) {
  497. if (offense_unit.get_UnitGameData_Obj().n in cncopt.keymap) {
  498. link += cncopt.keymap[offense_unit.get_UnitGameData_Obj().n];
  499. } else {
  500. console.log("cncopt [5]: Unhandled unit: " + offense_unit.get_UnitGameData_Obj().n);
  501. link += ".";
  502. }
  503. } else {
  504. link += ".";
  505. }
  506. break;
  507. case 1:
  508. /* Crystal */
  509. if (spot.BuildingIndex < 0) link += "c";
  510. else link += "n";
  511. break;
  512. case 2:
  513. /* Tiberium */
  514. if (spot.BuildingIndex < 0) link += "t";
  515. else link += "h";
  516. break;
  517. case 4:
  518. /* Woods */
  519. link += "j";
  520. break;
  521. case 5:
  522. /* Scrub */
  523. link += "h";
  524. break;
  525. case 6:
  526. /* Oil */
  527. link += "l";
  528. break;
  529. case 7:
  530. /* Swamp */
  531. link += "k";
  532. break;
  533. default:
  534. console.log("cncopt [4]: Unhandled resource type: " + city.GetResourceType(j, i));
  535. link += ".";
  536. break;
  537. }
  538. }
  539. }
  540. /* Tack on our alliance bonuses */
  541. if (alliance && scity.get_AllianceId() == tcity.get_AllianceId()) {
  542. link += "|" + alliance.get_POITiberiumBonus();
  543. link += "|" + alliance.get_POICrystalBonus();
  544. link += "|" + alliance.get_POIPowerBonus();
  545. link += "|" + alliance.get_POIInfantryBonus();
  546. link += "|" + alliance.get_POIVehicleBonus();
  547. link += "|" + alliance.get_POIAirBonus();
  548. link += "|" + alliance.get_POIDefenseBonus();
  549. }
  550. if (server.get_TechLevelUpgradeFactorBonusAmount() != 1.20) {
  551. link += "|newEconomy";
  552. }
  553. window.server = server;
  554. console.log("cbcopt: get_TechLevelUpgradeFactorBonusAmount = ", server.get_TechLevelUpgradeFactorBonusAmount())
  555.  
  556. //console.log(link);
  557. window.open(link, "_blank");
  558. } catch (e) {
  559. console.log("cncopt [1]: ", e);
  560. }
  561. }
  562. };
  563. if (!webfrontend.gui.region.RegionCityMenu.prototype.__cncopt_real_showMenu) {
  564. webfrontend.gui.region.RegionCityMenu.prototype.__cncopt_real_showMenu = webfrontend.gui.region.RegionCityMenu.prototype.showMenu;
  565. }
  566.  
  567. var check_ct = 0;
  568. var check_timer = null;
  569. var button_enabled = 123456;
  570. /* Wrap showMenu so we can inject our Sharelink at the end of menus and
  571. * sync Base object to our cncopt.selected_base variable */
  572. webfrontend.gui.region.RegionCityMenu.prototype.showMenu = function (selected_base) {
  573. try {
  574. var self = this;
  575. //console.log(selected_base);
  576. cncopt.selected_base = selected_base;
  577. if (this.__cncopt_initialized != 1) {
  578. this.__cncopt_initialized = 1;
  579. this.__cncopt_links = [];
  580. for (var i in this) {
  581. try {
  582. if (this[i] && this[i].basename == "Composite") {
  583. var link = new qx.ui.form.Button("CNCOpt", "http://cncopt.com/favicon.ico");
  584. link.addListener("execute", function () {
  585. var bt = qx.core.Init.getApplication();
  586. bt.getBackgroundArea().closeCityInfo();
  587. cncopt.make_sharelink();
  588. });
  589. this[i].add(link);
  590. this.__cncopt_links.push(link)
  591. }
  592. } catch (e) {
  593. console.log("cncopt [2]: ", e);
  594. }
  595. }
  596. }
  597. var tf = false;
  598. switch (selected_base.get_VisObjectType()) {
  599. case ClientLib.Vis.VisObject.EObjectType.RegionCityType:
  600. switch (selected_base.get_Type()) {
  601. case ClientLib.Vis.Region.RegionCity.ERegionCityType.Own:
  602. tf = true;
  603. break;
  604. case ClientLib.Vis.Region.RegionCity.ERegionCityType.Alliance:
  605. case ClientLib.Vis.Region.RegionCity.ERegionCityType.Enemy:
  606. tf = true;
  607. break;
  608. }
  609. break;
  610. case ClientLib.Vis.VisObject.EObjectType.RegionGhostCity:
  611. tf = false;
  612. console.log("cncopt: Ghost City selected.. ignoring because we don't know what to do here");
  613. break;
  614. case ClientLib.Vis.VisObject.EObjectType.RegionNPCBase:
  615. tf = true;
  616. break;
  617. case ClientLib.Vis.VisObject.EObjectType.RegionNPCCamp:
  618. tf = true;
  619. break;
  620. }
  621.  
  622. var orig_tf = tf;
  623.  
  624. function check_if_button_should_be_enabled() {
  625. try {
  626. tf = orig_tf;
  627. var selected_base = cncopt.selected_base;
  628. var still_loading = false;
  629. if (check_timer != null) {
  630. clearTimeout(check_timer);
  631. }
  632.  
  633. /* When a city is selected, the data for the city is loaded in the background.. once the
  634. * data arrives, this method is called again with these fields set, but until it does
  635. * we can't actually generate the link.. so this section of the code grays out the button
  636. * until the data is ready, then it'll light up. */
  637. if (selected_base && selected_base.get_Id) {
  638. var city_id = selected_base.get_Id();
  639. var city = ClientLib.Data.MainData.GetInstance().get_Cities().GetCity(city_id);
  640. //if (!city || !city.m_CityUnits || !city.m_CityUnits.m_DefenseUnits) {
  641. //console.log("City", city);
  642. //console.log("get_OwnerId", city.get_OwnerId());
  643. if (!city || city.get_OwnerId() == 0) {
  644. still_loading = true;
  645. tf = false;
  646. }
  647. } else {
  648. tf = false;
  649. }
  650. if (tf != button_enabled) {
  651. button_enabled = tf;
  652. for (var i = 0; i < self.__cncopt_links.length; ++i) {
  653. self.__cncopt_links[i].setEnabled(tf);
  654. }
  655. }
  656. if (!still_loading) {
  657. check_ct = 0;
  658. } else {
  659. if (check_ct > 0) {
  660. check_ct--;
  661. check_timer = setTimeout(check_if_button_should_be_enabled, 100);
  662. } else {
  663. check_timer = null;
  664. }
  665. }
  666. } catch (e) {
  667. console.log("cncopt [3]: ", e);
  668. tf = false;
  669. }
  670. }
  671.  
  672. check_ct = 50;
  673. check_if_button_should_be_enabled();
  674. } catch (e) {
  675. console.log("cncopt [3]: ", e);
  676. }
  677. this.__cncopt_real_showMenu(selected_base);
  678. }
  679. }
  680.  
  681.  
  682. /* Nice load check (ripped from AmpliDude's LoU Tweak script) */
  683. function cnc_check_if_loaded() {
  684. try {
  685. if (typeof qx != 'undefined') {
  686. a = qx.core.Init.getApplication(); // application
  687. if (a) {
  688. cncopt_create();
  689. } else {
  690. window.setTimeout(cnc_check_if_loaded, 1000);
  691. }
  692. } else {
  693. window.setTimeout(cnc_check_if_loaded, 1000);
  694. }
  695. } catch (e) {
  696. if (typeof console != 'undefined') console.log(e);
  697. else if (window.opera) opera.postError(e);
  698. else GM_log(e);
  699. }
  700. }
  701. if (/commandandconquer\.com/i.test(document.domain)) window.setTimeout(cnc_check_if_loaded, 1000);
  702. }
  703.  
  704. // injecting because we can't seem to hook into the game interface via unsafeWindow
  705. // (Ripped from AmpliDude's LoU Tweak script)
  706. var script_block = document.createElement("script");
  707. txt = cncopt_main.toString();
  708. script_block.innerHTML = "(" + txt + ")();";
  709. script_block.type = "text/javascript";
  710. if (/commandandconquer\.com/i.test(document.domain)) document.getElementsByTagName("head")[0].appendChild(script_block);
  711. })();
  712. } catch (e) {
  713. GM_log(e);
  714. }