KOCAttack - Extra Features!

Same as the original Kingdoms of Camelot Attack script, but with extra features.

  1. // ==UserScript==
  2. // @name KOCAttack - Extra Features!
  3. // @version 0.9.7.4
  4. // @namespace KOCAttack-Extra
  5. // @homepage http://userscripts.org/scripts/show/89473
  6. // @description Same as the original Kingdoms of Camelot Attack script, but with extra features.
  7.  
  8. // @include *apps.facebook.com/kingdomsofcamelot*
  9. // @include *kingdomsofcamelot.com/*main_src.php*
  10. // @include *kingdomsofcamelot.com/*newgame_src.php*
  11. // @include *facebook.com/connect/uiserver.php*
  12. // @include *kingdomsofcamelot.com/*standAlone.php*
  13.  
  14. // ==/UserScript==
  15.  
  16.  
  17. var KOCAversion = '0.9.7.4';
  18.  
  19. // Override the default alert functionality of the web browser (which causes the script to pause)
  20. // Instead of displaying alert popups, messages will be displayed in the firefox console
  21. unsafeWindow.alert = function(message) {
  22. console.info("Javascript Alert: "+message);
  23. if(typeof(GM_log)=="function"){
  24. GM_log("Javascript Alert: "+message);
  25. }
  26. }
  27. alert = unsafeWindow.alert;
  28.  
  29. // String prototypes
  30. String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }
  31. String.prototype.StripQuotes = function() {
  32. return this.replace(/"/g,'');
  33. };
  34.  
  35.  
  36. // Quick is_int function for javascript
  37. function is_int(value){
  38. if((parseFloat(value) == parseInt(value)) && !isNaN(value)){
  39. return true;
  40. } else {
  41. return false;
  42. }
  43. }
  44.  
  45. /*
  46. // Array remove function (found at http://ejohn.org/blog/javascript-array-remove/)
  47. Examples:
  48. Remove the second item from the array:
  49. ArrayRemoveItem(array, 1);
  50. Remove the second-to-last item from the array:
  51. ArrayRemoveItem(array, -2);
  52. Remove the second and third items from the array:
  53. ArrayRemoveItem(array, 1,2);
  54. Remove the last and second-to-last items from the array:
  55. ArrayRemoveItem(array, -2,-1);
  56. */
  57. ArrayRemoveItem = function(array, from, to) {
  58. var rest = array.slice((to || from) + 1 || array.length);
  59. array.length = from < 0 ? array.length + from : from;
  60. return array.push.apply(array, rest);
  61. };
  62.  
  63. if(!this.JSON2){JSON2={};}
  64. (function(){function f(n){return n<10?'0'+n:n;}
  65. if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return this.getUTCFullYear()+'-'+
  66. f(this.getUTCMonth()+1)+'-'+
  67. f(this.getUTCDate())+'T'+
  68. f(this.getUTCHours())+':'+
  69. f(this.getUTCMinutes())+':'+
  70. f(this.getUTCSeconds())+'Z';};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};}
  71. var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
  72. function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);}
  73. if(typeof rep==='function'){value=rep.call(holder,key,value);}
  74. switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
  75. gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||'null';}
  76. v=partial.length===0?'[]':gap?'[\n'+gap+
  77. partial.join(',\n'+gap)+'\n'+
  78. mind+']':'['+partial.join(',')+']';gap=mind;return v;}
  79. if(rep&&typeof rep==='object'){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==='string'){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}
  80. v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+
  81. mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}}
  82. if(typeof JSON2.stringify!=='function'){JSON2.stringify=function(value,replacer,space){var i;gap='';indent='';if(typeof space==='number'){for(i=0;i<space;i+=1){indent+=' ';}}else if(typeof space==='string'){indent=space;}
  83. rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');}
  84. return str('',{'':value});};}
  85. if(typeof JSON2.parse!=='function'){JSON2.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==='object'){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete value[k];}}}}
  86. return reviver.call(holder,key,value);}
  87. cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\\u'+
  88. ('0000'+a.charCodeAt(0).toString(16)).slice(-4);});}
  89. if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof reviver==='function'?walk({'':j},''):j;}
  90. throw new SyntaxError('JSON.parse');};}})();
  91.  
  92. if(!this.GM_log) {
  93. GM_log=function(m) {
  94. console.log(m);
  95. }
  96. GM_registerMenuCommand=function(text,f) {
  97. }
  98. }
  99.  
  100. if(!this.unsafeWindow) {
  101. //~~~ need helper to return values?
  102. unsafeWindow={};
  103. }
  104.  
  105.  
  106. function inspect(obj, maxLevels, level){
  107. var str = '', type, msg;
  108.  
  109. // Start Input Validations
  110. // Don't touch, we start iterating at level zero
  111. if(level == null) level = 0;
  112.  
  113. // At least you want to show the first level
  114. if(maxLevels == null) maxLevels = 1;
  115. if(maxLevels < 1)
  116. return '<font color="red">Error: Levels number must be > 0</font>';
  117.  
  118. // We start with a non null object
  119. if(obj == null)
  120. return '<font color="red">Error: Object <b>NULL</b></font>';
  121. // End Input Validations
  122.  
  123. // Each Iteration must be indented
  124. str += '<ul>';
  125.  
  126. // Start iterations for all objects in obj
  127. for(property in obj)
  128. {
  129. try
  130. {
  131. // Show "property" and "type property"
  132. type = typeof(obj[property]);
  133. str += '<li>(' + type + ') ' + property +
  134. ( (obj[property]==null)?(': <b>null</b>'):(': '+obj[property])) + '</li>';
  135.  
  136. // We keep iterating if this property is an Object, non null
  137. // and we are inside the required number of levels
  138. if((type == 'object') && (obj[property] != null) && (level+1 < maxLevels))
  139. str += inspect(obj[property], maxLevels, level+1);
  140. }
  141. catch(err)
  142. {
  143. // Is there some properties in obj we can't access? Print it red.
  144. if(typeof(err) == 'string') msg = err;
  145. else if(err.message) msg = err.message;
  146. else if(err.description) msg = err.description;
  147. else msg = 'Unknown';
  148.  
  149. str += '<li><font color="red">(Error) ' + property + ': ' + msg +'</font></li>';
  150. }
  151. }
  152.  
  153. // Close indent
  154. str += '</ul>';
  155.  
  156. return str;
  157. }
  158.  
  159. function MinDigits(num,digits) {
  160. while((""+num).length<digits) {
  161. num="0"+num;
  162. }
  163. return num;
  164. };
  165. function SecsToStr(secs) {
  166. secs=Math.floor(secs);
  167. return Math.floor(secs/60/60/24%60)+
  168. ":"+MinDigits(Math.floor(secs/60/60%60),2)+
  169. ":"+MinDigits(Math.floor(secs/60%60),2);
  170. // ":"+MinDigits(Math.floor(secs%60),2);
  171. };
  172.  
  173.  
  174. var nHtml={
  175. FindByXPath:function(obj,xpath,nodetype) {
  176. if(!nodetype){
  177. nodetype = XPathResult.FIRST_ORDERED_NODE_TYPE;
  178. }
  179. try {
  180. var q=document.evaluate(xpath,obj,null,nodetype,null);
  181. } catch(e) {
  182. GM_log('bad xpath:'+xpath);
  183. }
  184. if(nodetype == XPathResult.FIRST_ORDERED_NODE_TYPE){
  185. if(q && q.singleNodeValue) { return q.singleNodeValue; }
  186. }else{
  187. if(q){
  188. return q;
  189. }
  190. }
  191. return null;
  192. },
  193. ClickWin:function(win,obj,evtName) {
  194. var evt = win.document.createEvent("MouseEvents");
  195. evt.initMouseEvent(evtName, true, true, win,
  196. 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  197. return !obj.dispatchEvent(evt);
  198. },
  199. Click:function(obj) {
  200. return this.ClickWin(window,obj,'click');
  201. },
  202. ClickTimeout:function(obj,millisec) {
  203. window.setTimeout(function() {
  204. return nHtml.ClickWin(window,obj,'click');
  205. },millisec+Math.floor(Math.random()*500));
  206. },
  207.  
  208. SetSelect:function(obj,v) {
  209. for(var o=0; o<obj.options.length; o++) {
  210. if(v==obj.options[o].value) { obj.options[o].selected=true; return true; }
  211. }
  212. return false;
  213. }
  214.  
  215. };
  216.  
  217. function ById(id) {
  218. return document.getElementById(id);
  219. }
  220.  
  221. function ByName(name) {
  222. return document.getElementsByName(name);
  223. }
  224.  
  225. function AddText(box1,txt) {
  226. var txtObj;
  227. box1.appendChild(txtObj=document.createTextNode(txt));
  228. return txtObj;
  229. }
  230.  
  231. function AddHtml(box1,txt) {
  232. var txtObj;
  233. var sp=document.createElement('span');
  234. sp.innerHTML=txt;
  235. box1.appendChild(sp);
  236. return txtObj;
  237. }
  238.  
  239. function getAttackTypeSelected (){
  240. if (document.getElementById('modal_attack_tab_4').className == 'selected') // attack
  241. return 0;
  242. if (document.getElementById('modal_attack_tab_1').className == 'selected') // transport
  243. return 1;
  244. if (document.getElementById('modal_attack_tab_3').className == 'selected') // scout
  245. return 2;
  246. if (document.getElementById('modal_attack_tab_2').className == 'selected') // reinforce
  247. return 3;
  248. if (document.getElementById('modal_attack_tab_5').className == 'selected') // reassign
  249. return 4;
  250. return null;
  251. }
  252.  
  253. var KOCAttack={
  254. startListenTime:null,
  255. prevAttack:{'x':"350",'y':'350'},
  256. options:null,
  257. iframeCommunicator:{},
  258. isChrome:navigator.userAgent.toLowerCase().indexOf('chrome') > -1,
  259. valuesCache:{},
  260. seed:{},
  261. currentPage:null,
  262.  
  263. DoUnsafeWindow:function(func, execute_by_embed) {
  264. if(this.isChrome || execute_by_embed) {
  265. var scr=document.createElement('script');
  266. scr.innerHTML=func;
  267. document.body.appendChild(scr);
  268. } else {
  269. try {
  270. eval("unsafeWindow."+func);
  271. } catch (error) {
  272. this.Log("A javascript error has occurred when executing a function via DoUnsafeWindow. Error description: "+error.description);
  273. }
  274. }
  275. },
  276.  
  277. GetSeed:function() {
  278. return unsafeWindow.seed;
  279. },
  280. ShowImportExportBox:function() {
  281. var div=ById('ImportExportBoxDiv');
  282. if(!div) {
  283. div=document.createElement('div');
  284. div.id='KOCAttackViewAttacks';
  285. div.style.zIndex=100000;
  286. div.style.position='absolute';
  287. div.style.left='8px';
  288. div.style.top='8px';
  289. div.style.backgroundColor='#fff';
  290. div.style.border='3px solid #888';
  291. div.style.padding='10px';
  292. document.body.appendChild(div);
  293. }
  294. div.innerHTML = '';
  295. var m = '<a id="ImportBoxCancel" class="button20"><span>Close</span></a>';
  296. m += '<a id="ImportData" class="button20"><span>Import</span></a>';
  297. m += '<a id="ExportData" class="button20"><span>Export</span></a>&nbsp;';
  298. var cities=this.GetSeed().cities;
  299. //WinLog.write(inspect(cities));
  300. var citysel ='<select id=srcCity>';
  301. //citysel += '<option value=All>All Cities</option>';
  302. for(var c=0; c<cities.length; c++) {
  303. citysel += '<option value="'+cities[c][0]+'">'+cities[c][1]+'</option>';
  304. }
  305. citysel += '<option value=options>Options</option>';
  306. citysel += '</select>';
  307. m += citysel;
  308. m += '<br><textarea id="ImportExportArea" rows=25 cols=60></textarea>';
  309. div.innerHTML = m;
  310. ById('ImportBoxCancel').addEventListener('click',function() {
  311. div.innerHTML = '';
  312. div.style.display='none';
  313. },false);
  314. ById('ImportData').addEventListener('click',function() {
  315.  
  316. },false);
  317. ById('ExportData').addEventListener('click',function() {
  318. var x;
  319. var names=KOCAttack.browser_listValues();
  320. var obj={};
  321. var serverId=KOCAttack.GetServerId();
  322. for(var n=0; n<names.length; n++) {
  323. var name=names[n];
  324. var a = name.substring(0,11);
  325. var b = 'attack_'+serverId+'_';
  326. if (a==b ) {
  327. var sid=KOCAttack.GetServerIdFromName(name);
  328. if(sid!=serverId) continue;
  329. var v=KOCAttack.browser_getValue(name,null);
  330. if(v!=null && v!=undefined && v!=""){
  331. x = JSON2.parse(v);
  332. if (x.fromCity == ById('srcCity').value) {
  333. obj[name]=v;
  334. }
  335. }
  336. }
  337. else if (ById('srcCity').value == 'options') {
  338. var sid=KOCAttack.GetServerIdFromName(name);
  339. if(sid!=serverId) continue;
  340. var v=KOCAttack.browser_getValue(name,null);
  341. if(v!=null && v!=undefined && v!=""){
  342. obj[name]=v;
  343. }
  344. }
  345. }
  346. ById('ImportExportArea').value = JSON2.stringify(obj);
  347. },false);
  348. },
  349. ShowViewAttacksDialog:function() {
  350. var t=this;
  351. t.attacks=[];
  352. var div=ById('KOCAttackViewAttacks');
  353. if(!div) {
  354. div=document.createElement('div');
  355. div.id='KOCAttackViewAttacks';
  356. div.style.zIndex=100000;
  357. div.style.position='absolute';
  358. div.style.left='8px';
  359. div.style.top='8px';
  360. div.style.backgroundColor='#fff';
  361. div.style.border='3px solid #888';
  362. div.style.padding='10px';
  363. document.body.appendChild(div);
  364. }
  365. var cities=this.GetSeed().cities;
  366. //WinLog.write(inspect(cities));
  367. var citysel ='<select id=srcCity>';
  368. citysel += '<option value=All>All Cities</option>';
  369. for(var c=0; c<cities.length; c++) {
  370. citysel += '<option value="'+cities[c][1]+'">'+cities[c][1]+'</option>';
  371. }
  372. citysel += '</select>';
  373. var levelsel ='<select id=srcLevel>';
  374. levelsel += '<option value="All">All Levels</option>';
  375. for(var c=1; c<=11; c++) {
  376. levelsel += '<option value="'+c+'">Level '+c+'</option>';
  377. }
  378. levelsel += '</select>';
  379. var typesel ='<select id=srcAttackType>';
  380. typesel += '<option value="All">All</option>';
  381. typesel += '<option value="normal">Attacks</option>';
  382. typesel += '<option value="transport">Transports</option>';
  383. typesel += '<option value="bulkadded">Bulk Adds</option>';
  384. typesel += '</select>';
  385. div.style.display='block';
  386. div.innerHTML='';
  387. var m = '<DIV id="srcAttackOpts" style="height:30px">\
  388. <TABLE><TR valign=bottom><TD class=xtab width=100 align=center>Search for: </td><TD align=left>\
  389. <SELECT id=srcAttack>\
  390. <OPTION value=All>All</option>\
  391. <OPTION value=Camp>Barb Camp</option>\
  392. <OPTION value=Wilderness>Wilderness</option>\
  393. <OPTION value=Grassland>Grassland</option>\
  394. <OPTION value=Lake>Lake</option>\
  395. <OPTION value=Mountains>Mountains</option>\
  396. <OPTION value=Forest>Woods</option>\
  397. <OPTION value=Hills>Hills</option>\
  398. <OPTION value=Plain>Plains</option>\
  399. <OPTION value=City>City</option>\
  400. <OPTION value=Transport>Transport</option>\
  401. <OPTION value=Unknown>Unknown</option>\
  402. </select></td>\
  403. <td class=xtab width=100 align=center>Select City: &nbsp; </td>\
  404. <td align=left><span id=ptattackcity></span></td>\
  405. <td class=xtab width=100 align=center>Select Level: &nbsp; </td>\
  406. <td align=left><span id=ptattacklevel></span></td>\
  407. <td class=xtab width=100 align=center>Select Type: &nbsp; </td>\
  408. <td align=left><span id=ptattacktype></span></td></tr>\
  409. </table></div>\
  410. <a id="KOCAttackViewAttacksCancel" class="button20"><span>Close</span></a>\
  411. <a id="KOCAttackViewAttacksList" class="button20"><span>List Attacks</span></a>\
  412. <a id="KOCAttackViewAttacksClearList" class="button20"><span>Clear List</span></a>\
  413. <a id="KOCAttackViewAttacksDelete" class="button20"><span>Delete Selected</span></a>\
  414. <br><br><DIV id="srcAttackResults" style="height:470px; max-height:470px; overflow-y:auto;"></div>\
  415. ';
  416. //<a id="KOCAttackViewAttacksImportExport" class="button20"><span>Import / Export</span></a>\
  417. var srcAttackResults = ById("srcAttackResults");
  418. if (srcAttackResults != null){
  419. ById('KOCAttackViewAttacksClearList').click();
  420. }
  421. div.innerHTML = m;
  422. ById('ptattackcity').innerHTML = citysel;
  423. ById('ptattacklevel').innerHTML = levelsel;
  424. ById('ptattacktype').innerHTML = typesel;
  425.  
  426. ById('KOCAttackViewAttacksClearList').addEventListener('click',function() {
  427. ById('srcAttackResults').innerHTML='';
  428. },false);
  429. ById('KOCAttackViewAttacksCancel').addEventListener('click',function() {
  430. div.style.display='none';
  431. },false);
  432. //ById('KOCAttackViewAttacksImportExport').addEventListener('click',function() {
  433. // t.ShowImportExportBox();
  434. //},false);
  435. ById('KOCAttackViewAttacksList').addEventListener('click',function() {
  436. t.attacks=[];
  437. t.DetailAttacks();
  438. //WinLog.write(inspect(t.attacks,10));
  439. var typeQuery = ById('srcAttackType').value;
  440. var cityQuery = ById('srcCity').value;
  441. var levelQuery = ById('srcLevel').value;
  442. var attackQuery = ById('srcAttack').value;
  443. var h = '<table>';
  444. h += '<tr><td><input type=checkbox id=selAllAttacks></td><td>&nbsp;</td><td>City</td><td>Coords</td><td nowrap>What</td>';
  445. h += '<td>Type</td><td>Attack Troops</td><td>Suicide Troops/Resources</td><td>Dist</td><td>Time</td><td>Ignore</td></tr>';
  446. var tableRows= '';
  447. var count = 1
  448. for(var a=0; a<t.attacks.length; a++) {
  449. var levelInfo=t.GetLevelInfo(t.attacks[a]);
  450. if (levelInfo==undefined) levelInfo='';
  451. var type;
  452. if (levelInfo.type){
  453. type = levelInfo.type;
  454. } else {
  455. type = 'Unknown';
  456. }
  457.  
  458. var displayRow = '';
  459. if (cityQuery != 'All'){
  460. if (t.GetCityName(t.attacks[a]['fromCity']) != cityQuery){
  461. continue;
  462. }
  463. }
  464. if (levelQuery != 'All'){
  465. if (levelInfo.level != levelQuery){
  466. continue;
  467. }
  468. }
  469. if (typeQuery != 'All'){
  470. if (t.attacks[a].currenttattackwavetype != typeQuery){
  471. continue;
  472. }
  473. }
  474. if (attackQuery != 'All'){
  475. if (type != attackQuery){
  476. continue;
  477. }
  478. }
  479. tableRows += '<tr id=row'+count+' style="display: '+displayRow+';">';
  480. tableRows += '<td><input type=checkbox id=aasel'+count+'>';
  481. tableRows += '<td>'+count+'</td><td>'+t.GetCityName(t.attacks[a]['fromCity'])+'</td>';
  482. tableRows += '<td id=aacoords'+count+' onclick="aaGotoMapHide('+t.attacks[a].xy[0]+','+t.attacks[a].xy[1]+')">'+t.attacks[a].xy[0]+','+t.attacks[a].xy[1]+'</td>';
  483.  
  484. tableRows += '<td nowrap>'+type+' Level '+levelInfo.level+'</td>';
  485. tableRows += '<td>'+t.attacks[a].currenttattackwavetype+'</td>';
  486.  
  487. tableRows += '<td>';
  488. if(typeof(t.attacks[a].troops)=="object") {
  489. var troops='';
  490. for(var i=1; i<t.attacks[a].troops.length; i++) {
  491. troops += t.attacks[a].troops[i]+',';
  492. }
  493. troops = troops.substring(0, troops.length - 1);
  494. tableRows += troops;
  495. }
  496. else{
  497. tableRows += '&nbsp;';
  498. }
  499. tableRows += '</td>';
  500.  
  501. tableRows += '<td>';
  502.  
  503. if(typeof(t.attacks[a].suicidewave)=="object") {
  504. var suicide='';
  505. for(var i=1; i<t.attacks[a].suicidewave.length; i++) {
  506. suicide += t.attacks[a].suicidewave[i]+',';
  507. }
  508. suicide = suicide.substring(0, suicide.length - 1);
  509. tableRows += suicide;
  510. }
  511. else if (typeof(t.attacks[a].resources)=="object"){
  512. var resources='';
  513. for(var i=1; i<t.attacks[a].resources.length; i++) {
  514. resources += t.attacks[a].resources[i]+',';
  515. }
  516. resources = resources.substring(0, resources.length - 1);
  517. tableRows += resources;
  518. }
  519. else {
  520. tableRows += '&nbsp;';
  521. }
  522. tableRows += '</td>';
  523. var distance=t.CalcXYDist({'x':t.attacks[a].xy[0],'y':t.attacks[a].xy[0]},{'x':t.GetCityCoordsX(t.attacks[a]['fromCity']),'y':t.GetCityCoordsX(t.attacks[a]['fromCity'])});
  524. tableRows += '<td>'+parseInt(distance)+'</td>';
  525. var nowSecs=new Date().getTime()/1000;
  526. tableRows += '<td>'+SecsToStr(nowSecs-t.attacks[a].time)+'</td>';
  527. var ignChecked = '';
  528. if (t.attacks[a].ignore == null || t.attacks[a].ignore==undefined){
  529. ignChecked = '';
  530. }else{
  531. ignChecked = 'CHECKED';
  532. }
  533. tableRows += '<td><input type=checkbox name=chkIgnore id='+count+' '+ignChecked+'></td>';
  534. tableRows += '</tr>';
  535. count++;
  536. }
  537. h += tableRows + '</table>';
  538. ById('srcAttackResults').innerHTML = h;
  539.  
  540. ById('KOCAttackViewAttacksDelete').addEventListener('click',function() {
  541. var deletes = 0;
  542. for (var i=1; i<count; i++){
  543. var row = 'aasel'+i;
  544. if (ById(row) == undefined) continue;
  545. if (ById(row).checked == true){
  546. //ById(row).checked == false;
  547. var c = ById('aacoords'+i).innerHTML;
  548. var xy = c.split(",");
  549. GM_log('Coords '+xy[0]+' '+xy[1]);
  550. t.DeleteAttack(xy[0],xy[1]);
  551. deletes++;
  552. }
  553. }
  554. window.alert(deletes+' of coords deleted');
  555. // var listBtn=ById('KOCAttackViewAttacksList');
  556. // nHtml.Click(listBtn);
  557. },false);
  558. for (var i=1; i<count; i++){
  559. var ignore = i;
  560. t.addEvent(ById(ignore), "click", t.ChangeIgnore);
  561. }
  562. ById('selAllAttacks').addEventListener('click',function() {
  563. var myChecked = true;
  564. if (ById('selAllAttacks').checked == false){
  565. myChecked = false;
  566. }
  567. for (var i=1; i<count; i++){
  568. var row = 'aasel'+i;
  569. ById(row).checked=myChecked;
  570. }
  571. },false);
  572. },false);
  573. },
  574. addEvent:function(obj, type, fn){
  575. if (obj.attachEvent) {
  576. obj['e' + type + fn] = fn;
  577. obj[type + fn] = function(){obj['e' + type + fn](window.event);}
  578. obj.attachEvent('on' + type, obj[type + fn]);
  579. }
  580. else{
  581. obj.addEventListener(type, fn, false);
  582. }
  583. },
  584. ChangeIgnore:function(e){
  585. var c = ById('aacoords'+e.target.id).innerHTML;
  586. var xy = c.split(",");
  587. var serverID = KOCAttack.GetServerId();
  588. var attackname = 'attack_'+serverID+'_'+xy[0]+','+xy[1];
  589. var str = GM_getValue(attackname,'')
  590.  
  591. if(!str) return null;
  592. attack= JSON2.parse(str);
  593. attack.ignore=e.target.checked?true:undefined;
  594. //WinLog.write (inspect(attack,10));
  595. GM_setValue(attackname,JSON2.stringify(attack));
  596. },
  597. GetAttack:function(x,y) {
  598. var str=this.browser_getValue(this.GetAttackName(x,y),'');
  599. if(!str) return null;
  600. return JSON2.parse(str);
  601. },
  602. GetCityName:function(cityid) {
  603. var cityName;
  604. for(var a=0; a<unsafeWindow.seed.cities.length; a++) {
  605. if(unsafeWindow.seed.cities[a][0] == cityid){
  606. var cityName = unsafeWindow.seed.cities[a][1];
  607. }
  608. }
  609. return cityName;
  610. },
  611.  
  612. GetCityCoordsX:function(cityid) {
  613. var cityName;
  614. for(var a=0; a<unsafeWindow.seed.cities.length; a++) {
  615. if(unsafeWindow.seed.cities[a][0] == cityid){
  616. var x = unsafeWindow.seed.cities[a][2];
  617. }
  618. }
  619. return x;
  620. },
  621.  
  622. GetCityCoordsY:function(cityid) {
  623. var cityName;
  624. for(var a=0; a<unsafeWindow.seed.cities.length; a++) {
  625. if(unsafeWindow.seed.cities[a][0] == cityid){
  626. var y = unsafeWindow.seed.cities[a][3];
  627. }
  628. }
  629. return y;
  630. },
  631. ReloadWindow:function() {
  632. var m=/^[a-zA-Z]+([0-9]+)\./.exec(document.location.hostname);
  633. if (!m){
  634. //window.location.reload(true);
  635. history.go(0);
  636. return;
  637. }
  638. var goto = window.location.protocol+'//apps.facebook.com/kingdomsofcamelot/?s='+m[1];
  639. var t = '<FORM target="_top" action="'+ goto +'" method=post><INPUT id=xxButReload type=submit value=RELOAD><input type=hidden name=s value="'+ m[1] +'"</form>';
  640. var e = document.createElement ('div');
  641. e.innerHTML = t;
  642. document.body.appendChild (e);
  643. setTimeout (function (){document.getElementById('xxButReload').click();}, 0);
  644. },
  645. ShowOptionsDialog:function() {
  646. var div=ById('KOCAttackOptions');
  647. if(!div) {
  648. div=document.createElement('div');
  649. div.id='KOCAttackOptions';
  650. div.style.zIndex=100000;
  651. div.style.position='absolute';
  652. div.style.left='8px';
  653. div.style.top='8px';
  654. div.style.backgroundColor='#fff';
  655. div.style.border='3px solid #888';
  656. div.style.padding='10px';
  657. div.style.maxWidth='700px';
  658. document.body.appendChild(div);
  659. }
  660.  
  661. var okCitiesHtml="<span onmousedown='return false; '>";
  662. for(var c=1; c<=8; c++) {
  663. okCitiesHtml+=
  664. "<a style='font-size: 11px; padding: 2px; cursor: pointer; text-decoration: none' id='KOCAttackOkCities_"+c+"'>"+c+"</a>&nbsp;";
  665. }
  666. okCitiesHtml+='</span>';
  667. var attackfirst = '';
  668. var arrData = [["Camp", "Camps"],["City", "City"],["Transport", "Transport"],["Wilderness", "Wildernesses"],["None", "None"]];
  669. for (var i=0; i < arrData.length; i++){
  670. attackfirst += "<input type=radio name=KOCAttackPriority id='KOCAttackPriority_"+arrData[i][0]+"' value="+arrData[i][0]+" "+(arrData[i][0]==this.options.attackpriority?'checked':'')+"/>";
  671. attackfirst += "<label for='KOCAttackPriority_"+arrData[i][0]+"'>"+arrData[i][1]+"</label>";
  672. };
  673. div.style.display='block';
  674. div.innerHTML='';
  675. this.options=this.GetOptions();
  676. div.innerHTML="<form><table>"+
  677. "<tr><td valign='top' align='center'><img src='img/units/unit_6_50.jpg' /></td><td valign='top'>"+
  678. "Attack Order: <select id='KOCAttackOrder'><option value='mostTroops'>Use most troops first</option><option value='closest'>Closest targets first</option></select><br />"+
  679. "Attack Type: <input type='checkbox' "+(this.options.attackTypeCamp?'checked':'')+" id='KOCAttackTypeCamp'>Camp "+
  680. "<input type='checkbox' "+(this.options.attackTypeWild?'checked':'')+" id='KOCAttackTypeWild'>Wilderness "+
  681. "<input type='checkbox' "+(this.options.attackTypeCity?'checked':'')+" id='KOCAttackTypeCity'>City "+
  682. "<input type='checkbox' "+(this.options.attackTypeTransport?'checked':'')+" id='KOCAttackTypeTransport'>Transport<br> "+
  683. "Prioritise attacks for : "+attackfirst+
  684. "<br><br />"+
  685. "<input id='KOCAttackDelay' value='"+this.options.attackDelay+"' size='3' /> seconds inbetween sending each attack<br />"+
  686. "Time inbetween sending to the <u>same target</u>...<br />"+
  687. "<div style='margin-left: 40px'>"+
  688. "Attacking camp:<input id='KOCAttackHoursSinceLastCamp' value='"+(this.options.attackSecsSinceLastCamp/(60*60))+"' size='3' />hrs<br />"+
  689. "Attacking wilderness:<input id='KOCAttackHoursSinceLastWild' value='"+(this.options.attackSecsSinceLastWild/(60*60))+"' size='3' />hrs<br />"+
  690. " Attacking city:<input id='KOCAttackHoursSinceLastCity' value='"+(this.options.attackSecsSinceLastCity/(60*60))+"' size='3' />hrs<br />"+
  691. " Transporting:<input id='KOCAttackMinsSinceLastTransport' value='"+(this.options.attackSecsSinceLastTransport/(60))+"' size='3' />mins<br />"+
  692. " If transporting, try to keep at least <input id='KOCAttackTransportReserveAmount' value='"+this.options.transportResourcesReserveAmount+"' size='10' /> of each resource in each city <font color=#FF0000>(NEW)</font>"+
  693. "</div>"+
  694. "<input id='KOCAttackRandom' value='"+this.options.randomPercent+"' size='3' />% random adjustment for all delays (to look more human).<br />"+
  695. "<input id='KOCAttackRally' value='"+this.options.rallyKeep+"' size='3' /> of rally point slots to keep<br />"+
  696. "<br />"+
  697. "<input id='KOCAttackMaxDistance' value='"+(this.options.attackMaxDistance)+"' size='3' /> max distance away from city to attack/transport.<br />"+
  698. "<input id='KOCAttackLockAttackFromCity' type='checkbox' "+(this.options.lockAttackFromCity?'checked':'')+" /> Only launch attacks from city they were first launched from.<br />"+
  699. "<input id='KOCAttackUnselectKnight' type='checkbox' "+(this.options.knightreset?'checked':'')+" /> Deselect knight when not in attack mode.<br />"+
  700. "<input id='KOCAttackRetryMarch' type='checkbox' "+(this.options.retryMarch?'checked':'')+" /> Retry march if it has unknown/excess traffic error (press reload after changing this option).<br />"+
  701. "<input id='KOCAttackImpendingStopAttack' type='checkbox' "+(this.options.impendingStopAttack?'checked':'')+" /> Stop auto attack on impeding alert.<span style='color:red'> (Will not restart auto after the attack. Use at your own risk)</span><br />"+
  702. "Open up this URL (such as a link to a sound/video file) in a tab when we're under attack:<br /><input id='KOCAttackImpendingAttackUrl' size='60' value='"+(this.options.impendingAttackUrl)+"' /><br />"+
  703. "</td></tr>"+
  704. "<tr><td valign='top' align='center'><img src='img/chrome_message_up.png' /></td><td valign='top'>"+
  705. "<input id='KOCAttackRemoveReports' type='checkbox' "+(this.options.autoRemoveReports?'checked':'')+" /> Auto remove barbarian/wilderness attack reports.<br />"+
  706. "<input id='KOCAttackRemoveFarmReports' type='checkbox' "+(this.options.autoRemoveFarmReports?'checked':'')+" /> Auto remove farm attack reports.<br />"+
  707. "<input id='KOCAttackKeepReports' value='"+this.options.keepReports+"' size='3' /> attack reports to keep maximum in the attack dialog.<br />"+
  708. "<input id='KOCAttackNoViewReports' type='checkbox' "+(this.options.noViewReports?'checked':'')+" /> Disable viewing of reports, this will also disable collecting of reports for the attack page.<br />"+
  709. "</td></tr>"+
  710. "<tr><td valign='top' align='center'><img src='img/chome_alliance_up.png' /></td><td valign='top'>"+
  711. "<input id='KOCAttackPercentOfPopToTrain' value='"+this.options.percentOfPopToTrain+"' size='3' />% of idle population available before we auto train <input id='KOCAttackPercentToTrainOfMax' value='"+this.options.percentToTrainOfMax+"' size='3' />% of max available.<br />"+
  712. "<span style=\"font-size:10px; color:#555; line-height:18px; \">To enable auto training, toggle the auto train button under a troop type in the barracks.</span><br />"+
  713. "<span style=\"font-size:10px; color:#555; line-height:18px; \">Note: If you auto train 100% of max population, you might sometimes encounter resource errors due to game caching.</span><br />"+
  714. "</td></tr>"+
  715. "<tr><td valign='top' align='center'><img src='img/gold_30.png' /></td><td valign='top'>"+
  716. "<input id='KOCAttackAutoGoldHappiness' value='"+this.options.autoGoldHappiness+"' size='3' />% happiness before we click auto gold.<br />"+
  717. "<span style=\"font-size:10px; color:#555; line-height:18px; \">To enable auto gold, toggle the auto gold button from inside your castle overview window.</span><br />"+
  718. "</td></tr>"+
  719. "<tr><td valign='top' align='center'><img src='img/gems.png' /></td><td valign='top'>"+
  720. "<input id='KOCAttackDisableMapDraw' type='checkbox' "+(this.options.disableDrawMapIcons?'checked':'')+" /> Disable drawing of map icons.<br />"+
  721. "<input id='KOCAttackDisableInviteFriends' type='checkbox' "+(this.options.disableInviteFriends?'checked':'')+" /> Disable the annoying \"Invite Friends\" popup dialog in-game.<br />"+
  722. "<input id='KOCAttackAutoHelpAlliance' type='checkbox' "+(this.options.autoHelpAlliance?'checked':'')+" /> Automatically help alliance members with building/researching.<br />"+
  723. "<input id='KOCAttackHideAllianceHelpRequests' type='checkbox' "+(this.options.hideAllianceHelpRequests?'checked':'')+" /> Hide alliance help requests/reports in chat (if above is checked, then after helping).<br />"+
  724. "<input id='KOCAttackAutoPublishGamePopups' type='checkbox' "+(this.options.autoPublishGamePopups?'checked':'')+" /> Automatically publish game popups (such as help requests) to facebook wall.<br />"+
  725. "If above is checked, what privacy setting should we use? <select id='KOCAttackAutoPublishPrivacy'><option value='80'>Everyone</option><option value='50'>Friends of Friends</option><option value='40'>Friends Only</option><option value='10'>Only Me</option></select><br />"+
  726. "<input id='KOCAttackAutoLogBackIn' type='checkbox' "+(this.options.autoLogBackIn?'checked':'')+" /> Automatically log back into domain if disconnected due to maintenance or server down-time.<br />"+
  727. "<input id='KOCAttackEnableLogging' type='checkbox' "+(this.options.enableLogging?'checked':'')+" /> Enable diagnostic logging in the Firefox error console messages window (useful if trying to debug a problem or if you are submitting details along with a bug report).<br />"+
  728. "</td></tr>"+
  729. "<tr><td valign='top' align='center'><img src='img/buildings/castle_lvl10.png' /></td><td valign='top'>"+
  730. "<input id='KOCAttackChangeCitySecs' value='"+(this.options.changeCitySecs)+"' size='3' /> seconds inbetween changing cities.<br />"+
  731. "Cycle thru all the cities <input id='KOCAttackCitiesDoneMax' value='"+(this.options.autoAttackCitiesDoneMax)+"' size='3' /> times and then wait "+
  732. "<input id='KOCAttackCitiesDelay' value='"+this.options.waitAfterCitiesDone+"' size='3' />secs before refreshing.<br />"+
  733. "Cities to attack from: "+okCitiesHtml+'<br />'+
  734.  
  735. "<tr><td valign='top' align='center'></td><td valign='top'>"+
  736. "Import/Export: Paste or copy the settings here...<br /><textarea id='KOCAttackImport'></textarea>"+
  737. "<a class='button20' id='KOCAttackImportButton'><span>Import</span></a> <a class='button20' id='KOCAttackExportButton'><span>Export</span></a><br />"+
  738. "</td></tr>"+
  739.  
  740. "</table>"+
  741. "<TABLE width=100%><TR><TD>"+
  742. "<a id='KOCAttackOptionsSave' class='button20'><span>Save</span></a> <a id='KOCAttackOptionsCancel' class='button20'><span>Cancel</span></a> <a id='KOCAttackOptionsReset' class='button20'><span>Reset options</span></a> <a id='KOCAttackOptionsResetAll' class='button20'><span>Reset all!</span></a>"+
  743. "<a id='KOCAttackDeleteAllStoredAttacks' class='button20'><span>Delete all stored attacks</span></a>"+
  744. "<a id='KOCAttackDeleteTransports' class='button20'><span>Delete transports</span></a>"+
  745. //"<a id='KOCAttackListAttacks' class='button20'><span>List attacks</span></a><a id='KOCAttackListTransports' class='button20'><span>List transports</span></a>"+
  746. "</td><TD align=right>"+ KOCAversion +"</td></tr></form>";
  747. var t=this;
  748.  
  749. var importText=ById('KOCAttackImport');
  750. importText.addEventListener('focus',function() {
  751. importText.select();
  752. },false);
  753. ById('KOCAttackImportButton').addEventListener('click',function() {
  754. if(importText.value=="") return;
  755. t.ImportAllFromJSON(importText.value);
  756. },false);
  757. ById('KOCAttackExportButton').addEventListener('click',function() {
  758. importText.value=t.ExportAllToJSON();
  759. },false);
  760. nHtml.SetSelect(ById('KOCAttackOrder'),this.options.attackOrder);
  761. ById('KOCAttackOptionsCancel').addEventListener('click',function() {
  762. div.style.display='none';
  763. },false);
  764. ById('KOCAttackOptionsReset').addEventListener('click',function() {
  765. t.ClearOptions();
  766. this.options=t.GetOptions();
  767. div.style.display='none';
  768. },false);
  769. ById('KOCAttackOptionsResetAll').addEventListener('click',function() {
  770. t.FactoryReset();
  771. //window.location.reload(true);
  772. t.ReloadWindow();
  773. },false);
  774. ById('KOCAttackDeleteAllStoredAttacks').addEventListener('click',function() {
  775. t.DeleteAllStoredAttacks();
  776. //window.location.reload(true);
  777. t.ReloadWindow();
  778. },false);
  779. ById('KOCAttackDeleteTransports').addEventListener('click',function() {
  780. t.DeleteTransports();
  781. //window.location.reload(true);
  782. t.ReloadWindow();
  783. },false);
  784. //ById('KOCAttackListTransports').addEventListener('click',function() {
  785. //t.ListTransports();
  786. //window.location.reload(true);
  787. //},false);
  788. //ById('KOCAttackListAttacks').addEventListener('click',function() {
  789. //t.ListAttacks();
  790. //window.location.reload(true);
  791. //},false);
  792. nHtml.SetSelect(ById('KOCAttackAutoPublishPrivacy'),this.options.autoPublishPrivacySetting);
  793.  
  794. for(var c=1; c<=8; c++) {
  795. var sp=ById('KOCAttackOkCities_'+c);
  796. var SetCity=function(target,set) {
  797. target.style.border=set?'2px solid #080':'';
  798. target.style.margin=set?'2px':'4px';
  799. };
  800. sp.addEventListener('click',function(evt) { SetCity(evt.target,evt.target.style.border==''?true:false); },false);
  801. //sp.onmousedown=function() { return false; }
  802. SetCity(sp,t.options.okCities[c]);
  803. }
  804.  
  805. ById('KOCAttackOptionsSave').addEventListener('click',function() {
  806. t.options.attackTypeCamp=ById('KOCAttackTypeCamp').checked;
  807. t.options.attackTypeCity=ById('KOCAttackTypeCity').checked;
  808. t.options.attackTypeWild=ById('KOCAttackTypeWild').checked;
  809. t.options.attackTypeTransport=ById('KOCAttackTypeTransport').checked;
  810. var attackpriority = ByName('KOCAttackPriority');
  811. if(attackpriority){
  812. for(var i = 0; i < attackpriority.length; i++) {
  813. if(attackpriority[i].checked) {
  814. t.options.attackpriority = attackpriority[i].value;
  815. break;
  816. }
  817. }
  818. }
  819. t.options.attackDelay=parseInt(ById('KOCAttackDelay').value);
  820. t.options.waitAfterCitiesDone=parseInt(ById('KOCAttackCitiesDelay').value);
  821. t.options.keepReports=parseInt(ById('KOCAttackKeepReports').value);
  822. t.options.changeCitySecs=parseInt(ById('KOCAttackChangeCitySecs').value);
  823. t.options.autoGoldHappiness=parseInt(ById('KOCAttackAutoGoldHappiness').value);
  824. t.options.percentOfPopToTrain=parseFloat(ById('KOCAttackPercentOfPopToTrain').value);
  825. t.options.percentToTrainOfMax=parseFloat(ById('KOCAttackPercentToTrainOfMax').value);
  826. var prev_disableInviteFriends = t.options.disableInviteFriends;
  827. t.options.disableInviteFriends=ById('KOCAttackDisableInviteFriends').checked;
  828. t.options.disableDrawMapIcons=ById('KOCAttackDisableMapDraw').checked;
  829. if(prev_disableInviteFriends != t.options.disableInviteFriends){
  830. alert("You changed the option for disabling/enabling the \"Invite Friends\" feature.\nPlease note: You will need to refresh the entire game window for the new setting to take effect!");
  831. }
  832. t.options.autoHelpAlliance=ById('KOCAttackAutoHelpAlliance').checked;
  833. t.options.hideAllianceHelpRequests=ById('KOCAttackHideAllianceHelpRequests').checked;
  834. t.options.autoPublishGamePopups=ById('KOCAttackAutoPublishGamePopups').checked;
  835. t.options.autoPublishPrivacySetting=ById('KOCAttackAutoPublishPrivacy').value;
  836. t.options.autoLogBackIn=ById('KOCAttackAutoLogBackIn').checked;
  837. t.options.enableLogging=ById('KOCAttackEnableLogging').checked;
  838.  
  839. t.options.attackSecsSinceLastCamp=parseFloat(ById('KOCAttackHoursSinceLastCamp').value)*60*60;
  840. t.options.attackSecsSinceLastWild=parseFloat(ById('KOCAttackHoursSinceLastWild').value)*60*60;
  841. t.options.attackSecsSinceLastCity=parseFloat(ById('KOCAttackHoursSinceLastCity').value)*60*60;
  842. t.options.attackSecsSinceLastTransport=parseFloat(ById('KOCAttackMinsSinceLastTransport').value)*60;
  843. t.options.transportResourcesReserveAmount=parseInt(ById('KOCAttackTransportReserveAmount').value);
  844. t.options.randomPercent=parseFloat(ById('KOCAttackRandom').value);
  845. t.options.rallyKeep=parseInt(ById('KOCAttackRally').value);
  846. t.options.attackMaxDistance=parseFloat(ById('KOCAttackMaxDistance').value);
  847. t.options.autoAttackCitiesDoneMax=parseInt(ById('KOCAttackCitiesDoneMax').value);
  848.  
  849. t.options.attackOrder=ById('KOCAttackOrder').value;
  850. t.options.lockAttackFromCity=ById('KOCAttackLockAttackFromCity').checked;
  851. t.options.knightreset=ById('KOCAttackUnselectKnight').checked;
  852. t.options.autoRemoveReports=ById('KOCAttackRemoveReports').checked;
  853. t.options.autoRemoveFarmReports=ById('KOCAttackRemoveFarmReports').checked;
  854. t.options.retryMarch=ById('KOCAttackRetryMarch').checked;
  855. t.options.impendingAttackUrl=ById('KOCAttackImpendingAttackUrl').value;
  856. t.options.impendingStopAttack=ById('KOCAttackImpendingStopAttack').checked;
  857. t.options.noViewReports=ById('KOCAttackNoViewReports').checked;
  858. for(var c=1; c<=8; c++) {
  859. var okcity=ById('KOCAttackOkCities_'+c);
  860. t.options.okCities[c]=okcity.style.border!=""?true:false;
  861. }
  862.  
  863. t.SetOptions(t.options);
  864. div.style.display='none';
  865. },false);
  866. },
  867.  
  868. AddOptionsLink:function() {
  869. var t=this;
  870. var a=ById('KOCAttackOptionsLink');
  871. if(a) return;
  872.  
  873. a=this.AddTabLink('Options');
  874. if(!a) {
  875. window.setTimeout(function() {
  876. t.AddOptionsLink();
  877. },t.GetRandTime(250));
  878. return;
  879. }
  880. a.id='KOCAttackOptionsLink';
  881. a.addEventListener('click',function() {
  882. t.ShowOptionsDialog();
  883. },false);
  884. },
  885. AddViewAttacksLink:function() {
  886. var t=this;
  887. var a=ById('KOCAttackViewAttacksLink');
  888. if(a) return;
  889.  
  890. a=this.AddTabLink('View Attacks');
  891. if(!a) {
  892. window.setTimeout(function() {
  893. t.AddViewAttacksLink();
  894. },t.GetRandTime(250));
  895. return;
  896. }
  897. a.id='KOCAttackViewAttacksLink';
  898. a.addEventListener('click',function() {
  899. t.ShowViewAttacksDialog();
  900. },false);
  901. },
  902.  
  903. /*
  904. AddImportExportLink:function() {
  905. var t=this;
  906. var a=ById('KOCImportExportLink');
  907. if(a) return;
  908.  
  909. a=this.AddTabLink('Imp Exp');
  910. if(!a) {
  911. window.setTimeout(function() {
  912. t.AddImportExportLink();
  913. },t.GetRandTime(250));
  914. return;
  915. }
  916. a.id='KOCImportExportLink';
  917. a.addEventListener('click',function() {
  918. t.ShowImportExportBox();
  919. },false);
  920. },
  921. */
  922.  
  923. AddTabLink:function(html) {
  924. // Resize main tab bar container
  925. var tab_container = ById("main_engagement_tabs");
  926. tab_container.style.width = "715px";
  927. // Create new tab
  928. var a=document.createElement('a');
  929. a.className='navTab';
  930. a.innerHTML='<span>'+html+'</span>';
  931. var tabs=ById('KOCAttackTabs');
  932. if(!tabs) {
  933. var ptabs=ById('main_engagement_tabs');
  934. if(!ptabs) {
  935. ptabs=ById('topnav_msg');
  936. if(ptabs)ptabs=ptabs.parentNode;
  937. }
  938. if(!ptabs) {
  939. ptabs=document.body;
  940. }
  941. tabs=document.createElement('span');
  942. tabs.id='KOCAttackTabs';
  943. ptabs.insertBefore(tabs,ptabs.childNodes[0]);
  944. }
  945. if(tabs) {
  946. tabs.style.whiteSpace='nowrap';
  947. tabs.style.width='1600px';
  948. tabs.appendChild(a);
  949. return a;
  950. }
  951. return null;
  952. },
  953.  
  954. ToggleAutoAttack:function() {
  955. var t=this;
  956. var a=t.GetAutoAttack();
  957. if(!a) {
  958. t.Log("Enabling Auto Attack");
  959. t.SetAutoAttack({'barbarian':true,'cities':{}});
  960. window.setTimeout(function() {
  961. t.SetAttackStatusMessage();
  962. },t.GetRandTime(250));
  963. t.RestartAutoAttack();
  964. } else {
  965. t.Log("Disabling Auto Attack");
  966. t.ClearAutoAttackTimeout();
  967. t.SetAutoAttack(null);
  968. window.setTimeout(function() {
  969. t.SetAttackStatusMessage();
  970. },t.GetRandTime(250));
  971. }
  972.  
  973. /*
  974. // toggle for this city,
  975. if(!a.cities) a.cities={};
  976. var city=t.GetCurrentCityId();
  977. a.cities[city]=a.cities[city]?undefined:true;
  978. var attackCities=0;
  979. for(city in a.cities) {
  980. attackCities++;
  981. }
  982. if(attackCities==0) {
  983. t.ClearAutoAttackTimeout();
  984. t.SetAutoAttack(null);
  985. }
  986. */
  987. },
  988.  
  989. SetAttackStatusMessage:function() {
  990. //var mess=this.GetStatusMessage();
  991. var toggle=ById('KOCAttackToggle');
  992. if(!toggle) {
  993. var t=this;
  994. toggle=this.AddTabLink('Auto Attack');
  995. if(!toggle) {
  996. window.setTimeout(function() {
  997. t.SetAttackStatusMessage();
  998. },t.GetRandTime(250));
  999. return;
  1000. }
  1001. toggle.id='KOCAttackToggle';
  1002. toggle.addEventListener('click',function() {
  1003. t.ToggleAutoAttack();
  1004. },false);
  1005. }
  1006. var autoAttack=this.GetAutoAttack();
  1007. //if(autoAttack && autoAttack.cities && autoAttack.cities[t.GetCurrentCityId()]) {
  1008. if(autoAttack) {
  1009. toggle.innerHTML='<span>Auto Attack - On</span>';
  1010. } else {
  1011. toggle.innerHTML='<span>Auto Attack - Off</span>';
  1012. }
  1013. },
  1014.  
  1015. SetStatusMessage:function(str) {
  1016. var mess=this.GetStatusMessage();
  1017. var txt=ById('KOCAttackMessage');
  1018. if(!txt) {
  1019. txt=document.createElement('span');
  1020. mess.appendChild(txt);
  1021. }
  1022. txt.innerHTML=str;
  1023. },
  1024. GetStatusMessage:function() {
  1025. var mess=ById('KOCAttackStatus');
  1026. if(!mess) {
  1027. var timeHead=ById('kochead_time');
  1028. mess=document.createElement('span');
  1029. mess.id='KOCAttackStatus';
  1030. timeHead.parentNode.appendChild(mess);
  1031. }
  1032. return mess;
  1033. },
  1034.  
  1035. Log:function(str) {
  1036. if(!this.options || !this.options.enableLogging){
  1037. // disable logging
  1038. return;
  1039. }
  1040. str=this.GetServerId()+":"+str;
  1041. GM_log(str);
  1042. },
  1043.  
  1044. currentServerId:-1,
  1045. GetServerId:function() {
  1046. var m=/^[a-zA-Z]+([0-9]+)\./.exec(document.location.hostname);
  1047. if(m) {
  1048. this.currentServerId = m[1];
  1049. }
  1050. // Attempt to pull current server id from greasemonkey cache for cross-domain calls
  1051. if(this.currentServerId<0){
  1052. this.currentServerId = GM_getValue("KOCAttackLastKnownServerID",-1);
  1053. }
  1054. return this.currentServerId;
  1055. },
  1056.  
  1057. GetValue:function(prefix,def) {
  1058. var n=prefix+'_'+this.GetServerId();
  1059. return this.browser_getValue(n,def);
  1060. },
  1061.  
  1062. SetValue:function(prefix,val) {
  1063. var n=prefix+'_'+this.GetServerId();
  1064. this.browser_setValue(n,val);
  1065. },
  1066.  
  1067. GetValuesCache:function(doneFunc) {
  1068. if(!this.isChrome) {
  1069. if(doneFunc) {
  1070. doneFunc.call(this);
  1071. }
  1072. return;
  1073. }
  1074. /*
  1075. var t=this;
  1076. chrome.extension.sendRequest({func:"get","n":'KOCAttack'},
  1077. function(response) {
  1078. //~~~
  1079. this.valuesCache=JSON2.parse(unescape(response.v));
  1080. if(doneFunc) {
  1081. doneFunc.call(t);
  1082. }
  1083. });
  1084. return def;
  1085. */
  1086. var idx=0;
  1087. var cookie='kocattack';
  1088. var doccookie=document.cookie;
  1089. while(true) {
  1090. var i=doccookie.indexOf(cookie+'=',idx);
  1091. if(i<0) { this.valuesCache={}; return; }
  1092. idx=i+cookie.length+1;
  1093. var ch=doccookie.substring(i-1,i);
  1094. if(i==0 || ch==';' || ch==' ' || ch=='=') {
  1095. break;
  1096. }
  1097. }
  1098.  
  1099. var idxEnd=doccookie.indexOf(";",idx);
  1100. if(idxEnd<0) { idxEnd=doccookie.length; }
  1101. var cookieVal=doccookie.substring(idx,idxEnd);
  1102. this.valuesCache=JSON2.parse(unescape(cookieVal));
  1103. },
  1104. SetValuesCache:function() {
  1105. if(!this.isChrome) return;
  1106. document.cookie='kocattack='+escape(JSON2.stringify(this.valuesCache))+'; expires='+
  1107. (new Date(new Date().getTime()+(60*60*24*365*5)).toGMTString() );
  1108. },
  1109.  
  1110. browser_listValues:function() {
  1111. if(this.isChrome) {
  1112. var ns=[];
  1113. for(var n in this.valuesCache) {
  1114. ns.push(n);
  1115. }
  1116. return ns;
  1117. }
  1118. return GM_listValues();
  1119. },
  1120. browser_getValue:function(n,def) {
  1121. if(this.isChrome) {
  1122. if(this.valuesCache==null) {
  1123. this.GetValuesCache();
  1124. }
  1125. if(this.valuesCache[n]==undefined) {
  1126. return def;
  1127. }
  1128. return this.valuesCache[n];
  1129. }
  1130. return GM_getValue(n,def);
  1131. },
  1132. browser_setValue:function(n,val) {
  1133. if(this.isChrome) {
  1134. this.valuesCache[n]=val;
  1135. return;
  1136. }
  1137. if(val==null || val==undefined) {
  1138. GM_deleteValue(n);
  1139. } else {
  1140. GM_setValue(n,val);
  1141. }
  1142. },
  1143.  
  1144.  
  1145. GetMinHours:function() {
  1146. var m=this.GetValue('MinHours',1);
  1147. if(m=="" || m==undefined) m=1;
  1148. return m;
  1149. },
  1150. SetMinHours:function(val) {
  1151. this.SetValue('MinHours',val);
  1152. },
  1153.  
  1154. ClearOptions:function() {
  1155. this.SetValue('Options',JSON.stringify({}));
  1156. },
  1157. GetOptions:function() {
  1158. var json=this.GetValue('Options','{}');
  1159. if(json=='') json='{}';
  1160. var options=JSON2.parse(json);
  1161. var defOptions={"attackDelay":15,
  1162. "attackTypeCamp":true,
  1163. "attackOrder":"closest",
  1164. "attackpriority":"None",
  1165. "autoRemoveReports":true,
  1166. "rallyKeep":0,
  1167. "disableDrawMapIcons":false,
  1168. "attackSecsSinceLastCity":60*60*12,
  1169. "attackSecsSinceLastCamp":3600,
  1170. "attackSecsSinceLastWild":3600,
  1171. "attackSecsSinceLastTransport":60,
  1172. "transportResourcesReserveAmount":1000000,
  1173. "randomPercent":10,
  1174. "keepReports":10,
  1175. "attackMaxDistance":60,
  1176. "lockAttackFromCity":true,
  1177. "knightreset":true,
  1178. "waitAfterCitiesDone":20,
  1179. "autoAttackCitiesDoneMax":2,
  1180. "changeCitySecs":20,
  1181. "retryMarch":true,
  1182. "noViewReports":false,
  1183. "chromeKeepReports":2,
  1184. "percentOfPopToTrain":75,
  1185. "percentToTrainOfMax":95,
  1186. "autoGoldHappiness":99,
  1187. "disableInviteFriends":true,
  1188. "autoHelpAlliance":true,
  1189. "hideAllianceHelpRequests":false,
  1190. "autoPublishGamePopups":false,
  1191. "autoPublishPrivacySetting":"80",
  1192. "autoLogBackIn":true,
  1193. "enableLogging":false,
  1194. "okCities":[1,1,1,1,1,1,1,1,1,1],
  1195. 'impendingAttackUrl':''};
  1196. for(var n in defOptions) {
  1197. if(options[n]!=undefined) { continue; }
  1198. options[n]=defOptions[n];
  1199. }
  1200. return options;
  1201. },
  1202. SetOptions:function(v) {
  1203. this.SetValue('Options',JSON2.stringify(v));
  1204. },
  1205. ClearCrossIframeCommands:function() {
  1206. this.SetValue('CrossIframeCommands',JSON.stringify({}));
  1207. },
  1208. GetCrossIframeCommands:function() {
  1209. var json=this.GetValue('CrossIframeCommands','{}');
  1210. if(json=='') json='{}';
  1211. var commands=JSON2.parse(json);
  1212. if(!commands.queue || commands.queue instanceof Array !== true){
  1213. commands.queue = new Array();
  1214. }
  1215. return commands;
  1216. },
  1217. SetCrossIframeCommands:function(v) {
  1218. this.SetValue('CrossIframeCommands',JSON2.stringify(v));
  1219. },
  1220. AddCrossIframeCommand:function(pageName, functionCall, functionParameters) {
  1221. var command = {};
  1222. command.pageName = pageName;
  1223. command.functionCall = functionCall;
  1224. var commands = this.GetCrossIframeCommands();
  1225. commands.queue.push(command);
  1226. this.SetCrossIframeCommands(commands);
  1227. },
  1228.  
  1229. GetAttackName:function(x,y) {
  1230. return 'attack_'+this.GetServerId()+'_'+x+','+y;
  1231. },
  1232. SetAttack:function(x,y,attack) {
  1233. this.browser_setValue(this.GetAttackName(x,y), JSON2.stringify(attack));
  1234. },
  1235. GetAttack:function(x,y) {
  1236. var str=this.browser_getValue(this.GetAttackName(x,y),'');
  1237. if(!str) return null;
  1238. return JSON2.parse(str);
  1239. },
  1240. DeleteAttack:function(x,y) {
  1241. var str=this.browser_getValue(this.GetAttackName(x,y),'');
  1242. if(!str) return;
  1243. GM_deleteValue(this.GetAttackName(x,y));
  1244. },
  1245.  
  1246. isSuicideAttackDefinedAtLocation:function(x,y) {
  1247. var attack=this.GetAttack(x,y);
  1248. if(!attack){ return false; }
  1249. if(attack.suicidewave) { return true; }
  1250. if(attack.a && attack.a.suicidewave){ return true; }
  1251. return false;
  1252. },
  1253.  
  1254. IsFirstAttackAtLocation:function(x,y) {
  1255. var attack=this.GetAttack(x,y);
  1256. if(!attack){
  1257. this.Log("Attack not defined in system. This is first attack!");
  1258. return true;
  1259. }
  1260. if(attack.a) { attack = attack.a; }
  1261. // Check the current marches to see if there's an existing attack underway from this city
  1262. var current_marches=this.GetSeed().queue_atkp["city" + this.GetCurrentCityId()];
  1263. for (var march in current_marches) {
  1264. if(current_marches[march]['toXCoord'] == x && current_marches[march]['toYCoord'] == y){
  1265. this.Log("Troops are already marching to ("+x+","+y+") in the troop activity.");
  1266. /*
  1267. this.Log("Suicide wave time: "+attack.suicidewavetime+". Attack time: "+attack.time+".");
  1268. if(!attack.suicidewavetime || !attack.time){
  1269. this.Log("Suicide wave time: "+attack.suicidewavetime+". Attack time: "+attack.time+". This is first attack!");
  1270. return true;
  1271. }
  1272. */
  1273. if(attack.suicidewavetime && attack.suicidewave){
  1274. var nowSecs=new Date().getTime()/1000;
  1275. var elapsedTime=nowSecs-attack.suicidewavetime;
  1276. if(elapsedTime > 30 && attack.time < attack.suicidewavetime){
  1277. this.Log("Suicide wave attack was sent more than 30 seconds ago and normal wave has not been sent yet. Suicide wave should be re-sent! This is the first attack sent to ("+x+","+y+")!");
  1278. return true;
  1279. }
  1280. }
  1281. this.Log("This is not the first attack sent to ("+x+","+y+").");
  1282. return false;
  1283. break;
  1284. }
  1285. }
  1286.  
  1287. /*
  1288. if(this.prevAttack.x && this.prevAttack.y){
  1289. if(this.prevAttack.x==x && this.prevAttack.y==y) {
  1290. this.Log("Previous attack matches current attack. This is not first attack!");
  1291. return false;
  1292. }
  1293. }
  1294. */
  1295.  
  1296. this.Log("Troops are not currently marching to ("+x+","+y+") in the troop activity. This is the first attack.");
  1297. return true;
  1298. },
  1299.  
  1300. GetCommandHistory:function(history_log_name) {
  1301. if(!history_log_name){
  1302. var history_log_name = "default";
  1303. }
  1304. var json=this.GetValue('PreviousCommandHistory_'+history_log_name,'{}');
  1305. if(json=='') json='{}';
  1306. var json_object=JSON2.parse(json);
  1307. if(!json_object['items']){
  1308. json_object['items'] = Array();
  1309. }
  1310. return json_object;
  1311. },
  1312.  
  1313. AddToCommandHistory:function(command_string, history_log_name, log_length_limit) {
  1314. if(!command_string){ return false; }
  1315. if(!history_log_name){ var history_log_name = "default"; }
  1316. // Default to a history length of 20 commands
  1317. if(!log_length_limit){ var log_length_limit = 20; }
  1318. // Get the previous history of commands
  1319. var previous_commands = this.GetCommandHistory(history_log_name);
  1320. var items = previous_commands['items'];
  1321. // Add the new command
  1322. items.push(command_string);
  1323. // Limit the history length
  1324. if(items.length>log_length_limit){
  1325. items = items.slice(items.length-log_length_limit);
  1326. }
  1327. previous_commands['items'] = items;
  1328. this.SetValue('PreviousCommandHistory_'+history_log_name,JSON2.stringify(previous_commands));
  1329. },
  1330.  
  1331. FindInCommandHistory:function(command_string, history_log_name) {
  1332. if(!command_string){ return false; }
  1333. if(!history_log_name){ var history_log_name = "default"; }
  1334. // Get the previous history of commands
  1335. var previous_commands = this.GetCommandHistory(history_log_name);
  1336. var items = previous_commands['items'];
  1337. for(var i=0; i<items.length; i++){
  1338. if(items[i] == command_string){
  1339. return true;
  1340. }
  1341. }
  1342. return false;
  1343. },
  1344.  
  1345. GetGuiCoords:function() {
  1346. var x=ById('modal_attack_target_coords_x');
  1347. var y=ById('modal_attack_target_coords_y');
  1348. if(!x || !y) {
  1349. this.Log("Cannot find gui coords");
  1350. return null;
  1351. }
  1352. if(x.value.length<1 || y.value.length<1){
  1353. this.Log("One or both coordinates are missing!");
  1354. return null;
  1355. }
  1356. return [x.value,y.value];
  1357. },
  1358.  
  1359. SetAttackFromGui:function(box, resetTime) {
  1360. var xy=this.GetGuiCoords();
  1361. if(!xy) return null;
  1362. if(!resetTime){resetTime=false;}
  1363. return this.SetAttackFromGuiXY(xy[0],xy[1],box, null, null, resetTime);
  1364. },
  1365.  
  1366. AttackLastSentTime:0,
  1367. UpdateAttackLastSentTime:function(){
  1368. this.AttackLastSentTime = new Date().getTime()/1000;
  1369. this.SetValue('AttackLastSentTime',parseInt(this.AttackLastSentTime));
  1370. },
  1371. SendingMultipleWaves:false,
  1372. IsCurrentlySendingMultipleWaves:function() {
  1373. if(this.AttackLastSentTime == 0){
  1374. this.AttackLastSentTime = this.GetValue('AttackLastSentTime',0);
  1375. }
  1376. var nowSecs = new Date().getTime()/1000;
  1377. var waveTimerDelay = this.options.attackDelay*2;
  1378. var timeDifference = nowSecs-this.AttackLastSentTime;
  1379. //this.Log("nowSecs: "+nowSecs+" waveTimerDelay: "+waveTimerDelay+" timeDifference: "+timeDifference+" SendingMultipleWaves: "+this.SendingMultipleWaves);
  1380. // If the last attack was sent at a time ago that is more than twice the attack delay,
  1381. // then we assume something failed and we reset the multiple wave tracker so everything can continue.
  1382. if(timeDifference > waveTimerDelay && this.SendingMultipleWaves==true){
  1383. this.SendingMultipleWaves=false;
  1384. this.Log("Multiple wave timer \("+waveTimerDelay+"\ seconds) has expired. Last known attack was sent "+timeDifference+" seconds ago. Resetting timer and continuing...");
  1385. }
  1386. return this.SendingMultipleWaves;
  1387. },
  1388. SetAttackFromGuiXY:function(x,y,box,isSuicideWave,locationType,resetTime) {
  1389. if(resetTime==true){
  1390. this.Log("Resetting start times for attack ("+x+","+y+")");
  1391. }
  1392. // Determine location type
  1393. if(!locationType){ var locationType = ""; }
  1394. var locationTypeRadioBoxes = ByName('KOCAttackLocationType');
  1395. if(locationTypeRadioBoxes){
  1396. for(var i = 0; i < locationTypeRadioBoxes.length; i++) {
  1397. if(locationTypeRadioBoxes[i].checked) {
  1398. locationType = locationTypeRadioBoxes[i].value;
  1399. break;
  1400. }
  1401. }
  1402. }
  1403.  
  1404. // Determine attack wave type
  1405. if(!isSuicideWave){
  1406. var isSuicideWave = false;
  1407. var bulkAddSuicideWaveCheckbox = ById("KOCAttackBulkAddSuicideWave");
  1408. if(bulkAddSuicideWaveCheckbox){isSuicideWave = bulkAddSuicideWaveCheckbox.checked;}
  1409. var otherIsSuicideWaveCheckbox = ById("KOCAttackSuicideWaveCheckbox");
  1410. if(otherIsSuicideWaveCheckbox){ if(otherIsSuicideWaveCheckbox.checked){isSuicideWave=true;} }
  1411. }
  1412.  
  1413. var troops=[];
  1414. var totalTroops=0;
  1415. for(var tr=0; tr<20; tr++) {
  1416. var troop=ById('modal_attack_unit_ipt'+tr);
  1417. if(!troop) continue;
  1418. try {
  1419. var v=parseInt(troop.value);
  1420. troops[tr]=v;
  1421. totalTroops+=v;
  1422. } catch(e) {
  1423. continue;
  1424. }
  1425. }
  1426. var comment=ById('KocAttackComment');
  1427. var marchType = getAttackTypeSelected();
  1428. if(marchType==null) {
  1429. throw("Cannot find attack type");
  1430. }
  1431.  
  1432. if(totalTroops<=0) {
  1433. this.Log("No troops, not saving attack");
  1434. return null;
  1435. }
  1436.  
  1437. var nowSecs=new Date().getTime()/1000;
  1438. var monthAgo=nowSecs-(60*60*24*31);
  1439. // ignore anything other than attack
  1440. if(marchType==0 && locationType!="Transport") {
  1441. var attack=this.GetAttack(x,y);
  1442. if(!attack) attack={};
  1443. attack.type=marchType;
  1444. if(comment){ attack.comment=comment.value; }
  1445. var SuicideAttackDefined=this.isSuicideAttackDefinedAtLocation(x,y);
  1446. var firstAttack=this.IsFirstAttackAtLocation(x,y);
  1447. this.Log("First attack?: "+firstAttack);
  1448. this.Log("Suicide attack defined? : "+SuicideAttackDefined);
  1449.  
  1450. if(isSuicideWave) {
  1451. this.Log("Suicide attack determined by checkbox");
  1452. this.Log("Suicide wave :"+troops);
  1453. attack.suicidewave=troops;
  1454. attack.currenttattackwavetype = "suicide";
  1455. attack.suicidewavetime = nowSecs;
  1456. if(resetTime==true){ attack.suicidewavetime=monthAgo; }
  1457. this.SendingMultipleWaves = true;
  1458. } else {
  1459. this.Log("Normal wave :"+troops);
  1460. attack.time=nowSecs;
  1461. if(resetTime==true){ attack.time=monthAgo; }
  1462. if(!SuicideAttackDefined && firstAttack){
  1463. attack.suicidewave=undefined;
  1464. }
  1465. attack.currenttattackwavetype = "normal";
  1466. attack.troops=troops;
  1467. this.SendingMultipleWaves = false;
  1468. }
  1469. //if (this.options.lockAttackFromCity) {
  1470. attack.fromCity=this.GetCurrentCityId();
  1471. //}
  1472. //Check if level is undefined
  1473. if(!attack.levelInfo){attack.levelInfo={'type':locationType,'level':0};}
  1474. if(locationType==""){
  1475. if(attack.levelInfo.type!=""){
  1476. // a pre-defined location type was already entered before for this attack.
  1477. locationType = attack.levelInfo.type;
  1478. }else{
  1479. // Default to camp if attack location type was absolutely not specified in any way
  1480. locationType = "Camp";
  1481. }
  1482. }
  1483. attack.levelInfo.type = locationType;
  1484.  
  1485. //attack.ignore=undefined;
  1486. this.prevAttack={'x':x,'y':y};
  1487. this.SetAttack(x,y,attack);
  1488. return attack;
  1489. } else if(marchType==1 || locationType=="Transport") {
  1490. // try to parse transports
  1491. var attack=this.GetAttack(x,y);
  1492. if(!attack) attack={};
  1493. attack.type=1; //If we got here presume to be transport mode
  1494. //attack.ignore=true; // We set this to ignore for now until I can get the auto attack working
  1495. if(comment){
  1496. attack.comment=comment.value;
  1497. }
  1498. var SuicideAttackDefined=this.isSuicideAttackDefinedAtLocation(x,y);
  1499.  
  1500. attack.time=nowSecs;
  1501. if(resetTime==true){ attack.time=monthAgo; }
  1502. attack.troops=troops;
  1503.  
  1504. var resources=[];
  1505. var resourceTypes = new Array(
  1506. 'gold',
  1507. 'rec1',
  1508. 'rec2',
  1509. 'rec3',
  1510. 'rec4'
  1511. );
  1512. for(var res=0; res<resourceTypes.length; res++) {
  1513. var resource=ById('modal_attack_'+resourceTypes[res]);
  1514. if(!resource) continue;
  1515. try {
  1516. var v=parseInt(resource.value);
  1517. resources[res]=v;
  1518. totalResources+=v;
  1519. } catch(e) {
  1520. continue;
  1521. }
  1522. }
  1523. attack.resources=resources;
  1524. //if (this.options.lockAttackFromCity) {
  1525. attack.fromCity=this.GetCurrentCityId();
  1526. //}
  1527. //attack.ignore=undefined;
  1528. //locationType = "Transport"; Redundant code
  1529. //Check if level is undefined
  1530. if(!attack.levelInfo){attack.levelInfo={'type':locationType,'level':0};}
  1531. // Set the location type
  1532. //attack.levelInfo.type = locationType;
  1533. attack.currenttattackwavetype = "transport";
  1534. this.prevAttack={'x':x,'y':y};
  1535. this.SetAttack(x,y,attack);
  1536. return attack;
  1537. } else {
  1538. // Reset it
  1539. this.prevAttack={'x':"350",'y':'350'};
  1540. }
  1541. return null;
  1542. },
  1543.  
  1544. ToggleCurrenttAttackWaveType:function(x,y,manual_setting) {
  1545. var original_attack = this.GetAttack(x,y);
  1546. if(original_attack) {
  1547. var attack = original_attack;
  1548. if(original_attack.a){
  1549. attack = original_attack.a;
  1550. }
  1551. var previousattackwavetype = 'undefined';
  1552. if(attack){
  1553. //this.Log("Inspecting attack: "+inspect(attack,10));
  1554. if(attack.currenttattackwavetype){
  1555. previousattackwavetype = attack.currenttattackwavetype;
  1556. }
  1557. if(manual_setting){
  1558. attack.currenttattackwavetype = manual_setting;
  1559. }else if(attack.suicidewave && attack.currenttattackwavetype == "bulkadded"){
  1560. attack.currenttattackwavetype = "suicide";
  1561. }else{
  1562. // Toggle back and forth
  1563. if(attack.suicidewave && attack.currenttattackwavetype == "normal"){
  1564. attack.currenttattackwavetype = "suicide";
  1565. }else{
  1566. attack.currenttattackwavetype = "normal";
  1567. }
  1568. }
  1569. this.Log("Toggling attack for ("+x+", "+y+") from "+previousattackwavetype+" to "+attack.currenttattackwavetype);
  1570. if(original_attack.a){
  1571. original_attack.a = attack;
  1572. attack = original_attack;
  1573. }
  1574. this.SetAttack(x,y,attack);
  1575. return attack.currenttattackwavetype;
  1576. }else{
  1577. return false;
  1578. }
  1579. }else{
  1580. return false;
  1581. }
  1582. },
  1583.  
  1584. BulkAddCoords:function(box,coordsText,force,locationType,isSuicideWave) {
  1585. if(!locationType){
  1586. var locationType = "Camp"; //Default to camp
  1587. }
  1588. if(!isSuicideWave){
  1589. var isSuicideWave = false;
  1590. }
  1591. var coordRows=coordsText.split("\n");
  1592. var added=0;
  1593. for(var r=0; r<coordRows.length; r++) {
  1594. var row=coordRows[r];
  1595. var m=/^\s*([0-9]+)\s*,\s*([0-9]+)/.exec(row);
  1596. if(!m) {
  1597. m=/^\s*([0-9]+)\s+([0-9]+)/.exec(row);
  1598. if(!m) continue;
  1599. }
  1600. var x=m[1];
  1601. var y=m[2];
  1602. var attack=this.GetAttack(x,y);
  1603. var currenttattackwavetype = "bulkadded";
  1604. if(locationType=="Transport"){
  1605. currenttattackwavetype = "transport";
  1606. }
  1607. var SuicideAttackDefined=this.isSuicideAttackDefinedAtLocation(x,y);
  1608. var previous_suicidewave = undefined;
  1609. if(attack && (SuicideAttackDefined || isSuicideWave)){
  1610. previous_suicidewave = attack.suicidewave;
  1611. }
  1612. if(attack && !force) {
  1613. if(SuicideAttackDefined && isSuicideWave==true){
  1614. this.Log('Suicide wave for '+x+','+y+' has already been added. Try over-writing it.');
  1615. continue;
  1616. }else if(attack.troops){
  1617. this.Log('Attack wave for '+x+','+y+' has already been added. Try over-writing it.');
  1618. continue;
  1619. }
  1620. }
  1621. var attack=this.SetAttackFromGuiXY(x,y,box,isSuicideWave,locationType);
  1622. if(attack) {
  1623. attack.levelInfo={'type':locationType,'level':0};
  1624. attack.fromCity=this.GetCurrentCityId();
  1625. var nowSecs=new Date().getTime()/1000;
  1626. var monthAgo=nowSecs-(60*60*24*31);
  1627. attack.time=monthAgo;
  1628. if(SuicideAttackDefined || isSuicideWave || previous_suicidewave){
  1629. // set up suicide wave before attack time, according to "seconds in between sending each attack"
  1630. attack.suicidewavetime = attack.time - this.options.attackDelay;
  1631. if(previous_suicidewave && (!SuicideAttackDefined || !isSuicideWave)){
  1632. this.Log("Previous suicide wave for this attack was over-written by new attack. Merging and restoring...");
  1633. attack.suicidewave = previous_suicidewave;
  1634. }
  1635. }
  1636. attack.ignore=undefined;
  1637. attack.currenttattackwavetype=currenttattackwavetype;
  1638. this.SetAttack(x,y,attack);
  1639. this.Log(x+','+y+' attack added: '+inspect(attack));
  1640. this.Log("current attack wave type: "+attack.currenttattackwavetype);
  1641. added++;
  1642. }
  1643. }
  1644. // Redraw attacks on map listing
  1645. this.DrawClosestFarms();
  1646. // done
  1647. return added;
  1648. },
  1649.  
  1650. BulkAddAttackLink:function(box) {
  1651. var div=ById('BulkAddAttackDiv');
  1652. var t=this;
  1653. if(!div) {
  1654. div=document.createElement('div');
  1655. div.id='BulkAddAttackDiv';
  1656. div.style.display='inline';
  1657. }
  1658. div.innerHTML='';
  1659. var bulkAddTable=document.createElement('table');
  1660. bulkAddTable.style.background='transparent';
  1661. var bulkAddDiv=document.createElement('div');
  1662. bulkAddTable.insertRow(-1).insertCell(-1).appendChild(bulkAddDiv);
  1663. bulkAddDiv.style.display='none';
  1664. //AddHtml(bulkAddDiv,"<hr />");
  1665. AddHtml(bulkAddDiv,"Copy and paste coords here (ie. 343,434) one on each line...<br />Note: it will only add the target using the current number of troops on this screen.<br /><input id='KOCAttackBulkAddForce' type='checkbox' /> <label for=\"KOCAttackBulkAddForce\">Overwrite existing attack if one already exists</label><br />");
  1666.  
  1667. // radio boxes for defining bulk coordinate type
  1668. AddHtml(bulkAddDiv,"<hr />");
  1669. AddHtml(bulkAddDiv,"Type of Locations (All coordinates must match this type):<br />");
  1670. var arrData = [["Camp", "Camps"],["City", "City"],["Transport", "Transport"],["Wilderness", "Wildernesses"]];
  1671. for (var i=0; i < arrData.length; i++){
  1672. var objRadItem = document.createElement("input");
  1673. objRadItem.type = "radio";
  1674. objRadItem.name = "KOCAttackBulkAddLocationType";
  1675. objRadItem.id = "KOCAttackBulkAddLocationType_" + arrData[i][0];
  1676. objRadItem.value = arrData[i][0];
  1677.  
  1678. if(i == 0) {objRadItem.defaultChecked = true; objRadItem.checked = true; };
  1679.  
  1680. var objTextNode = document.createTextNode(" " + arrData[i][1]);
  1681.  
  1682. var objLabel = document.createElement("label");
  1683. objLabel.htmlFor = objRadItem.id;
  1684. objLabel.appendChild(objRadItem);
  1685. objLabel.appendChild(objTextNode);
  1686.  
  1687. bulkAddDiv.appendChild(objLabel);
  1688. objRadItem.addEventListener('change',function() {
  1689. var locationType = "Camp"; // Set default value to camp
  1690. var bulkLocationTypeRadioBoxes = ByName('KOCAttackBulkAddLocationType');
  1691. if(bulkLocationTypeRadioBoxes){
  1692. for(var i = 0; i < bulkLocationTypeRadioBoxes.length; i++) {
  1693. if(bulkLocationTypeRadioBoxes[i].checked) {
  1694. locationType = bulkLocationTypeRadioBoxes[i].value;
  1695. break;
  1696. }
  1697. }
  1698. }
  1699. // Select the same radio box in the normal add area
  1700. var locationTypeRadioBoxes = ByName('KOCAttackLocationType');
  1701. if(locationTypeRadioBoxes){
  1702. for(var i = 0; i < locationTypeRadioBoxes.length; i++) {
  1703. if(locationTypeRadioBoxes[i].value == locationType) {
  1704. locationTypeRadioBoxes[i].checked = true;
  1705. break;
  1706. }
  1707. }
  1708. }
  1709. },false);
  1710. AddHtml(bulkAddDiv," ");
  1711. };
  1712. AddHtml(bulkAddDiv,"<hr />");
  1713. //AddHtml(bulkAddDiv,"<input id='KOCAttackBulkAddSuicideWave' type='checkbox' /> This is an initial suicide wave to wipe out traps on a wilderness.<br />");
  1714. var bulkAddSuicideSpan=document.createElement('span');
  1715. var bulkAddSuicideCheckbox=document.createElement('input');
  1716. bulkAddSuicideCheckbox.id = "KOCAttackBulkAddSuicideWave";
  1717. bulkAddSuicideCheckbox.name = bulkAddSuicideCheckbox.id;
  1718. bulkAddSuicideCheckbox.type='checkbox';
  1719. bulkAddSuicideSpan.appendChild(bulkAddSuicideCheckbox);
  1720. AddHtml(bulkAddSuicideSpan,'<label for="KOCAttackBulkAddSuicideWave">This is an initial suicide wave to wipe out traps on a wilderness.</label>');
  1721. bulkAddDiv.appendChild(bulkAddSuicideSpan);
  1722. bulkAddSuicideCheckbox.addEventListener('click',function() {
  1723. var bulkAddSuicideWaveCheckbox = ById("KOCAttackBulkAddSuicideWave");
  1724. var suicideWaveCheckbox = ById("KOCAttackSuicideWaveCheckbox");
  1725. var locationType_Wilderness = ById("KOCAttackLocationType_Wilderness");
  1726. var bulkAddLocationType_Wilderness = ById("KOCAttackBulkAddLocationType_Wilderness");
  1727. if(bulkAddSuicideWaveCheckbox && suicideWaveCheckbox && locationType_Wilderness && bulkAddLocationType_Wilderness){
  1728. if(bulkAddSuicideCheckbox.checked){
  1729. suicideWaveCheckbox.checked = true;
  1730. locationType_Wilderness.checked = true;
  1731. bulkAddLocationType_Wilderness.checked = true;
  1732. }else{
  1733. suicideWaveCheckbox.checked = false;
  1734. }
  1735. }
  1736. },false);
  1737.  
  1738. AddHtml(bulkAddDiv,"<hr />");
  1739.  
  1740. var coords=document.createElement('textarea');
  1741. coords.wrap='off';
  1742. coords.style.whiteSpace='nowrap';
  1743. coords.cols=10;
  1744. coords.rows=8;
  1745. bulkAddDiv.appendChild(coords);
  1746. AddHtml(bulkAddDiv,"<br />");
  1747. var bulkAdd=document.createElement('a');
  1748. bulkAdd.className='buttonDown20';
  1749. bulkAdd.innerHTML='<span>Bulk Add</span>';
  1750. bulkAddDiv.appendChild(bulkAdd);
  1751. bulkAdd.addEventListener('click',function() {
  1752. // Determine location type
  1753. var locationType = "Camp"; // Set default value to camp
  1754. var locationTypeRadioBoxes = ByName('KOCAttackBulkAddLocationType');
  1755. if(locationTypeRadioBoxes){
  1756. for(var i = 0; i < locationTypeRadioBoxes.length; i++) {
  1757. if(locationTypeRadioBoxes[i].checked) {
  1758. locationType = locationTypeRadioBoxes[i].value;
  1759. break;
  1760. }
  1761. }
  1762. }
  1763. // Determine attack wave type
  1764. var isSuicideWave = false;
  1765. var bulkAddSuicideWaveCheckbox = ById("KOCAttackBulkAddSuicideWave");
  1766. if(bulkAddSuicideWaveCheckbox){isSuicideWave = bulkAddSuicideWaveCheckbox.checked;}
  1767. var otherIsSuicideWaveCheckbox = ById("KOCAttackSuicideWaveCheckbox");
  1768. if(otherIsSuicideWaveCheckbox){ if(otherIsSuicideWaveCheckbox.checked){isSuicideWave=true;} }
  1769. // Add the coordinates
  1770. var added=t.BulkAddCoords(box,coords.value,ById('KOCAttackBulkAddForce').checked,locationType,isSuicideWave);
  1771. bulkAddDiv.style.display='none';
  1772. bulkAddAttackLink.style.display='inline';
  1773. window.alert('Bulk added '+added+' coords');
  1774. },false);
  1775. AddHtml(bulkAddDiv,"<br />");
  1776.  
  1777. var bulkAddAttackLink=document.createElement('a');
  1778. bulkAddAttackLink.className='buttonDown20';
  1779. bulkAddAttackLink.innerHTML='<span>Bulk add coords</span>';
  1780. bulkAddAttackLink.addEventListener('click',function() {
  1781. if(bulkAddDiv.style.display=='inline'){
  1782. bulkAddDiv.style.display='none';
  1783. }else{
  1784. bulkAddDiv.style.display='inline';
  1785. }
  1786. },false);
  1787. div.appendChild(bulkAddAttackLink);
  1788. div.appendChild(bulkAddTable);
  1789. return div;
  1790. },
  1791. hideAttackEffortsState : true,
  1792. HideAttackEfforts: function () {
  1793. var t = KOCAttack;
  1794. if (!ById('modal_attack_march_boost')) { return; }
  1795. var span = document.createElement('span');
  1796. var a = document.createElement('a');
  1797. //var txt = document.createElement('text');
  1798. a.innerHTML = 'Hide Attack/Speed Boosts';
  1799. //inp.type='checkbox';
  1800. span.appendChild(a);
  1801. //span.appendChild (txt);
  1802. if (t.hideAttackEffortsState) {
  1803. hideshow('none');
  1804. }
  1805. a.addEventListener('click', function (evt) {
  1806. t.hideAttackEffortsState = !t.hideAttackEffortsState;
  1807. hideshow();
  1808. }, false);
  1809. for (var i = 1; i < 5; i++) {
  1810. document.getElementById('modal_attack_tab_' + i).addEventListener('click', hideshow, false);
  1811. document.getElementById('modal_attack_tab_' + i).addEventListener('click', setLocationType, false);
  1812. }
  1813. return span;
  1814.  
  1815. function setLocationType() {
  1816. var attackTypeSelected = getAttackTypeSelected();
  1817. if(attackTypeSelected==1){
  1818. // Transport
  1819. var KOCAttackLocationType_Transport = ById("KOCAttackLocationType_Transport");
  1820. if(KOCAttackLocationType_Transport) { KOCAttackLocationType_Transport.checked = true; }
  1821. var KOCAttackBulkAddLocationType_Transport = ById("KOCAttackBulkAddLocationType_Transport");
  1822. if(KOCAttackBulkAddLocationType_Transport) { KOCAttackBulkAddLocationType_Transport.checked = true; }
  1823. }else{
  1824. // Default back to Camp
  1825. var KOCAttackLocationType_Camp = ById("KOCAttackLocationType_Camp");
  1826. if(KOCAttackLocationType_Camp) { KOCAttackLocationType_Camp.checked = true; }
  1827. var KOCAttackBulkAddLocationType_Camp = ById("KOCAttackBulkAddLocationType_Camp");
  1828. if(KOCAttackBulkAddLocationType_Camp) { KOCAttackBulkAddLocationType_Camp.checked = true; }
  1829. }
  1830. }
  1831. function hideshow() {
  1832. if (t.options.knightreset) {
  1833. var attackTypeSelected = getAttackTypeSelected();
  1834. var knightSelect = ById('modal_attack_knight');
  1835. if (attackTypeSelected != 0) { knightSelect.selectedIndex = 0; }
  1836. }
  1837. if (t.hideAttackEffortsState) {
  1838. disp = 'none';
  1839. }else{
  1840. disp = 'block';
  1841. }
  1842. ById('modal_attack_march_boost').style.display = disp;
  1843. ById('modal_attack_attack_boost').style.display = disp;
  1844. ById('modal_attack_defense_boost').style.display = disp;
  1845. var div = ById('modal_attack_speed_boost');
  1846. for (var i = 0; i < i < div.childNodes.length; i++) {
  1847. if (div.childNodes[i].className == 'section_title'){
  1848. div.childNodes[i].style.display = disp;
  1849. }
  1850. if (div.childNodes[i].className == 'section_content') {
  1851. div = div.childNodes[i];
  1852. for (i = 0; i < div.childNodes.length; i++) {
  1853. if (div.childNodes[i].style != undefined && div.childNodes[i].className != 'estimated') {
  1854. div.childNodes[i].style.display = disp;
  1855. }
  1856. }
  1857. break;
  1858. }
  1859. }
  1860. }
  1861. },
  1862.  
  1863. SetResourceInput:function(num,resourceCount) {
  1864. var resource=ById('modal_attack_'+num);
  1865. if(!resource) return null;
  1866. resource.value=resourceCount;
  1867. resource.style.backgroundColor='';
  1868.  
  1869. // send a shift key so that it recalculates
  1870. var evt = document.createEvent("KeyboardEvent");
  1871. if(evt.initKeyboardEvent) {
  1872. evt.initKeyboardEvent("keyup",true,true,null,false,false,false,false,0x10,0);
  1873. } else {
  1874. evt.initKeyEvent("keyup",true,true,null,false,false,false,false,0x10,0);
  1875. }
  1876. resource.dispatchEvent(evt);
  1877.  
  1878. if(parseInt(resourceCount)>0) {
  1879. if(resource.value!=resourceCount) {
  1880. this.Log('Not able to set resource count:'+num+',wanted:'+resourceCount+', count:'+resource.value);
  1881. resource.style.backgroundColor='#f88';
  1882. return 'notfull';
  1883. } else {
  1884. resource.style.backgroundColor='#ff8';
  1885. return 'full';
  1886. }
  1887. }
  1888. return 'none';
  1889. },
  1890.  
  1891. SetTroopInput:function(num,troopCount) {
  1892. var troop=ById('modal_attack_unit_ipt'+num);
  1893. if(!troop) return null;
  1894. if(troop.disabled) return 'notfull'; //Disable filling in of troops if field is disabled
  1895. troop.value=troopCount;
  1896. troop.style.backgroundColor='';
  1897.  
  1898. // send a shift key so that it recalculates
  1899. var evt = document.createEvent("KeyboardEvent");
  1900. if(evt.initKeyboardEvent) {
  1901. evt.initKeyboardEvent("keyup",true,true,null,false,false,false,false,0x10,0);
  1902. } else {
  1903. evt.initKeyEvent("keyup",true,true,null,false,false,false,false,0x10,0);
  1904. }
  1905. troop.dispatchEvent(evt);
  1906.  
  1907. if(parseInt(troopCount)>0) {
  1908. if(troop.value!=troopCount) {
  1909. this.Log('Not able to set troop count:'+num+',wanted:'+troopCount+', count:'+troop.value);
  1910. troop.style.backgroundColor='#f88';
  1911. return 'notfull';
  1912. } else {
  1913. troop.style.backgroundColor='#ff8';
  1914. return 'full';
  1915. }
  1916. }
  1917. return 'none';
  1918. },
  1919.  
  1920. GetRandTime:function(millis) {
  1921. var millisPerc=millis*(this.options.randomPercent/100);
  1922. var randSecs=Math.floor((Math.random()*millisPerc*2)-millisPerc)+millis;
  1923. return randSecs;
  1924. },
  1925.  
  1926. GetAutoGold:function() {
  1927. return this.GetValue('AutoGold,'+this.GetCurrentCityId(),true);
  1928. },
  1929. SetAutoGold:function(v) {
  1930. return this.SetValue('AutoGold,'+this.GetCurrentCityId(),v);
  1931. },
  1932.  
  1933. GetAbandonWilds:function() {
  1934. return this.GetValue('AbandonWilds_'+this.GetCurrentCityId(),false);
  1935. },
  1936. SetAbandonWilds:function(v) {
  1937. return this.SetValue('AbandonWilds_'+this.GetCurrentCityId(),v);
  1938. },
  1939.  
  1940. CheckAutoRaiseGold:function() {
  1941. if(!this.GetAutoGold()) return;
  1942. var happiness=parseInt(this.GetSeed().citystats["city" + this.GetCurrentCityId()].pop[2]);
  1943. if(happiness>=this.options.autoGoldHappiness) {
  1944. this.DoUnsafeWindow("modal_raise_gold();");
  1945. }
  1946. },
  1947.  
  1948. CheckAbandonWilds:function() {
  1949. if(!this.GetAbandonWilds()) return;
  1950. var t=this;
  1951. var castle=ById('slot_0');
  1952. nHtml.Click(castle);
  1953. this.DoUnsafeWindow("changeCastleModalTabs(2);");
  1954. var wildsWindow=ById('castle_2');
  1955. var rows=wildsWindow.getElementsByTagName('tr');
  1956. if (rows.length==1) { //no wilds
  1957. this.DoUnsafeWindow("Modal.hideModal();");
  1958. return;
  1959. }
  1960. var commands = new Array();
  1961. for (i=0;i<rows.length;i++) {
  1962. var abandonButton=rows[i].getElementsByTagName('a')[1];
  1963. if (abandonButton==undefined) {
  1964. continue;
  1965. }
  1966. var command=abandonButton.getAttribute('onclick');
  1967. command=command.substring(0,command.length-13);
  1968. if(command.indexOf("wilderness_abandon")>-1){
  1969. var tmp_obj = new Object;
  1970. tmp_obj.command = command;
  1971. tmp_obj.clicked = false;
  1972. commands.push(tmp_obj);
  1973. }
  1974. }
  1975. var command_timer=0;
  1976. var milliseconds_between=4000;
  1977. for (var i=0;i<commands.length;i++) {
  1978. window.setTimeout(function() {
  1979. // Determine next unclicked button
  1980. var unclicked_commandObj = undefined;
  1981. for (var j=0;j<commands.length;j++) {
  1982. if(!commands[j].clicked){
  1983. t.DoUnsafeWindow(commands[j].command);
  1984. window.setTimeout(function() {
  1985. var mainbody = ById("mainbody");
  1986. if(mainbody){
  1987. var okay_btn=nHtml.FindByXPath(mainbody,".//a[contains(@class,'okay')]");
  1988. if(okay_btn){
  1989. nHtml.Click(okay_btn);
  1990. }
  1991. }
  1992. },500);
  1993. commands[j].clicked = true;
  1994. break;
  1995. }
  1996. }
  1997. },t.GetRandTime(command_timer));
  1998. command_timer+=milliseconds_between;
  1999. }
  2000. window.setTimeout(function() {
  2001. t.DoUnsafeWindow("Modal.hideModal();");
  2002. },t.GetRandTime(command_timer));
  2003. },
  2004.  
  2005. GetDisplayName:function(){
  2006. var DisplayName = ById('topnavDisplayName');
  2007. if(DisplayName){
  2008. DisplayName = DisplayName.innerHTML;
  2009. }else{
  2010. DisplayName = null;
  2011. }
  2012. return DisplayName
  2013. },
  2014.  
  2015. HandleChatPane:function() {
  2016. var t=this;
  2017. // Determine our own name so we can ignore our own requests
  2018. var DisplayName = t.GetDisplayName();
  2019. // Process chat pane
  2020. var AllianceChatBox=ById('mod_comm_list2');
  2021. if(AllianceChatBox){
  2022. var chatPosts = document.evaluate(".//div[contains(@class,'chatwrap')]", AllianceChatBox, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );
  2023. if(chatPosts){
  2024. // Loop through each post
  2025. for (var i = 0; i < chatPosts.snapshotLength; i++) {
  2026. thisPost = chatPosts.snapshotItem(i);
  2027. //t.Log(thisPost.innerHTML);
  2028. // Automatically help out with alliance requests
  2029. if(this.options.autoHelpAlliance){
  2030. // Make sure that this isn't our own request
  2031. var postAuthor = document.evaluate('.//*[@class="nm"]', thisPost, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );
  2032. if(postAuthor.snapshotItem(0)){
  2033. var postAuthorName = postAuthor.snapshotItem(0).innerHTML;
  2034. if(postAuthorName != DisplayName){
  2035. // Look for any alliance assist links in this current post item
  2036. var helpAllianceLinks=document.evaluate(".//a[contains(@onclick,'claimAllianceChatHelp')]", thisPost, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );
  2037. if(helpAllianceLinks){
  2038. for (var j = 0; j < helpAllianceLinks.snapshotLength; j++) {
  2039. thisLink = helpAllianceLinks.snapshotItem(j);
  2040. // Check to see if link has already been clicked
  2041. var alreadyClicked = thisLink.getAttribute("clicked");
  2042. if(!alreadyClicked){
  2043. // Mark it as clicked
  2044. thisLink.setAttribute('clicked', 'true');
  2045. // Execute the onclick code
  2046. var myregexp = /(claimAllianceChatHelp\(.*\);)/;
  2047. var match = myregexp.exec(thisLink.getAttribute("onclick"));
  2048. if (match != null) {
  2049. onclickCode = match[0];
  2050. //t.Log(onclickCode);
  2051. // Check alliance help command history to make sure link hasn't already been processed
  2052. if(!t.FindInCommandHistory(onclickCode, 'alliance_help')){
  2053. t.DoUnsafeWindow(onclickCode);
  2054. // Add the onclick code to the alliance help command history
  2055. this.AddToCommandHistory(onclickCode, 'alliance_help');
  2056. }else{
  2057. //t.Log("already clicked");
  2058. }
  2059. }
  2060. }else{
  2061. //t.Log("already clicked");
  2062. }
  2063. }
  2064. }else{
  2065. //t.Log("no alliance links found in current post");
  2066. }
  2067. }else{
  2068. //t.Log("current post is by yourself");
  2069. }
  2070. }else{
  2071. //t.Log("unable to find post's author");
  2072. }
  2073. }
  2074. // Hide alliance requests in chat
  2075. if(this.options.hideAllianceHelpRequests){
  2076. // Look for any alliance assist links in this current post item
  2077. var helpAllianceLinks=document.evaluate(".//a[contains(@onclick,'claimAllianceChatHelp')]", thisPost, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );
  2078. if(helpAllianceLinks){
  2079. for (var j = 0; j < helpAllianceLinks.snapshotLength; j++) {
  2080. thisLink = helpAllianceLinks.snapshotItem(j);
  2081. // Delete the post item from the DOM
  2082. thisLink.parentNode.parentNode.parentNode.parentNode.parentNode.removeChild(thisLink.parentNode.parentNode.parentNode.parentNode);
  2083. }
  2084. }
  2085. }
  2086. // Hide alliance reports in chat
  2087. if(this.options.hideAllianceHelpRequests){
  2088. // Look for any alliance assist links in this current post item
  2089. var myregexp1 = /You are # [1-5] of 5 to help/i;
  2090. var myregexp2 = /\'s Kingdom does not need help\./i;
  2091. var myregexp3 = /\'s project has already been completed\./i;
  2092. var myregexp4 = /\'s project has received the maximum amount of help\./i;
  2093. if (thisPost.innerHTML.match(myregexp1) || thisPost.innerHTML.match(myregexp2) || thisPost.innerHTML.match(myregexp3) || thisPost.innerHTML.match(myregexp4)) {
  2094. // Delete the post item from the DOM
  2095. thisPost.parentNode.removeChild(thisPost);
  2096. }
  2097. }
  2098. }
  2099. }
  2100. }
  2101. },
  2102.  
  2103. HandlePublishPopup:function() {
  2104. var t=this;
  2105. if (t.currentPage == "facebook_popup") {
  2106. if(t.options.autoPublishGamePopups){
  2107. // Check the app id (we only want to handle the popup for kingdoms of camelot)
  2108. var FBInputForm = ById('uiserver_form');
  2109. if(FBInputForm){
  2110. var channel_input = nHtml.FindByXPath(FBInputForm,".//input[contains(@name,'channel')]");
  2111. if(channel_input){
  2112. var current_channel_url = channel_input.value;
  2113. if (current_channel_url.match(/http:\/\/.{0,100}kingdomsofcamelot\.com\/.*?\/cross_iframe\.htm/i)) {
  2114. var publish_button = nHtml.FindByXPath(FBInputForm,".//input[@type='submit' and contains(@name,'publish')]");
  2115. var privacy_setting = nHtml.FindByXPath(FBInputForm,".//input[@type='hidden' and contains(@name, 'privacy_data') and contains(@name, 'value')]");
  2116. if(publish_button && privacy_setting){
  2117. // 80: Everyone
  2118. // 50: Friends of Friends
  2119. // 40: Friends Only
  2120. // 10: Only Me
  2121. privacy_setting.value = t.options.autoPublishPrivacySetting;
  2122. nHtml.Click(publish_button);
  2123. }
  2124. }
  2125. }
  2126. }
  2127. }
  2128. }
  2129. },
  2130. domainLoginTimer:null,
  2131. domainLoginStartTime:null,
  2132. domainLoginCurrentTime:null,
  2133. domainLoginSeconds:30,
  2134. domainLoginActionTaken:false,
  2135. HandleDomainLogin:function() {
  2136. var t=this;
  2137. if (t.currentPage == "domain_selection" && t.options.autoLogBackIn && !t.domainLoginActionTaken) {
  2138. if(!t.domainLoginStartTime){
  2139. t.domainLoginStartTime = Math.round(new Date().getTime() / 1000);
  2140. }
  2141. t.domainLoginCurrentTime = Math.round(new Date().getTime() / 1000);
  2142. var timeDifference = Math.round(t.domainLoginStartTime+t.domainLoginSeconds - t.domainLoginCurrentTime);
  2143. if(timeDifference<0){ timeDifference=0; }
  2144. var statusDiv=ById('KOCAttackLoginStatus');
  2145. if(!statusDiv) {
  2146. statusDiv=document.createElement('div');
  2147. statusDiv.id='KOCAttackLoginStatus';
  2148. statusDiv.style.position='relative';
  2149. statusDiv.style.backgroundColor='#fff';
  2150. statusDiv.style.border='3px solid #888';
  2151. statusDiv.style.margin='30px 0px 0px 0px';
  2152. statusDiv.style.padding='10px';
  2153. statusDiv.style.display='none';
  2154. var loginBox = ById("formoptions0");
  2155. loginBox.appendChild(statusDiv);
  2156. }
  2157. // Find the top-most domain in the list (the most recent one)
  2158. var playButtons=document.evaluate(".//a[contains(@class,'button20')]", unsafeWindow.document.body, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );
  2159. if(playButtons && playButtons.snapshotLength>0){
  2160. //var firstPlayButton = playButtons.snapshotItem(0);
  2161. //var domain_name = firstPlayButton.parentNode.parentNode.firstChild.innerHTML;
  2162. //statusDiv.innerHTML='<center>KoCAttack Extra: Automatically logging into '+domain_name+' in '+timeDifference+' seconds...</center>';
  2163. statusDiv.innerHTML='<center>KoCAttack Extra: Automatically logging back into KoC in '+timeDifference+' seconds...</center>';
  2164. if(timeDifference==0){
  2165. //t.Log("Loading URL: "+firstPlayButton.href);
  2166. t.Log("Loading URL: http://apps.facebook.com/kingdomsofcamelot/");
  2167. //statusDiv.innerHTML='<center>KoCAttack Extra: Automatically logging into '+domain_name+' now...</center>';
  2168. statusDiv.innerHTML='<center>KoCAttack Extra: Automatically logging back into KoC now...</center>';
  2169. var functionCall = {
  2170. 'action':'load_url',
  2171. //'parameters':firstPlayButton.href
  2172. 'parameters':'http://apps.facebook.com/kingdomsofcamelot/'
  2173. };
  2174. t.AddCrossIframeCommand("domain_selection_app_page", functionCall);
  2175. t.domainLoginActionTaken=true;
  2176. // Reload current window if things are unsuccessful
  2177. window.setTimeout(function() {
  2178. t.ReloadWindow();
  2179. },10000);
  2180. }
  2181. }else{
  2182. statusDiv.innerHTML='<center>KoCAttack Extra: Automatically reloading page in '+timeDifference+' seconds...</center>';
  2183. if(timeDifference==0){
  2184. statusDiv.innerHTML='<center>KoCAttack Extra: Automatically reloading page now...</center>';
  2185. t.ReloadWindow();
  2186. t.domainLoginActionTaken=true;
  2187. }
  2188. }
  2189. statusDiv.style.display='block';
  2190. if(!t.domainLoginTimer && !t.domainLoginActionTaken) {
  2191. t.domainLoginTimer=window.setTimeout(function() {
  2192. t.domainLoginTimer=null;
  2193. t.HandleDomainLogin();
  2194. },1000);
  2195. }
  2196. }
  2197. },
  2198. HandleCrossIframeCommands:function() {
  2199. var t=this;
  2200. var commands = t.GetCrossIframeCommands();
  2201. if(!commands.queue) return false;
  2202. var commandsUpdated = false;
  2203. for(var i=0; i<commands.queue.length; i++) {
  2204. var command = commands.queue[i];
  2205. // Cross-iframe Command structure:
  2206. // commands {
  2207. // command {
  2208. // 'pageName' (string) - The page to execute the code on
  2209. // 'functionCall' (string) - The function to call
  2210. // }
  2211. // }
  2212. if(t.currentPage == command.pageName){
  2213. if(command.functionCall.action == "load_url"){
  2214. setTimeout (function (){window.location.href=command.functionCall.parameters;}, 0);
  2215. }
  2216. ArrayRemoveItem(commands.queue, i);
  2217. commandsUpdated=true;
  2218. }
  2219. }
  2220. if(commandsUpdated){
  2221. this.SetCrossIframeCommands(commands);
  2222. }
  2223. },
  2224. OnCastleBoxAppear:function(box) {
  2225. var raiseGold=nHtml.FindByXPath(box,".//a[contains(@onclick,'raiseGold')]");
  2226. var a=document.createElement('a');
  2227. a.className='button25';
  2228. var t=this;
  2229. function SetAutoGoldA() {
  2230. var str=t.GetAutoGold()?'Auto - On':'Auto - Off';
  2231. a.innerHTML='<span>'+str+'</span>';
  2232. }
  2233. a.addEventListener('click',function() {
  2234. var autoGold=t.GetAutoGold();
  2235. t.SetAutoGold(autoGold?false:true);
  2236. SetAutoGoldA();
  2237. },false);
  2238. SetAutoGoldA();
  2239. raiseGold.parentNode.insertBefore(a,raiseGold.nextSibling);
  2240. var productionHeader=nHtml.FindByXPath(box,".//div[contains(@class,'prodtableheader')]");
  2241. productionHeader=productionHeader.parentNode;
  2242. var b=document.createElement('a');
  2243. b.className='button25';
  2244. function SetAbandonWildsA() {
  2245. var str=t.GetAbandonWilds()?'Abandon Wilds - On':'Abandon Wilds - Off';
  2246. b.innerHTML='<span>'+str+'</span>';
  2247. }
  2248. b.addEventListener('click',function() {
  2249. var abandonWilds=t.GetAbandonWilds();
  2250. if(!abandonWilds){
  2251. var abandonWildsConfirm = confirm("Are you sure you want to automatically abandon all wildernesses?\n")
  2252. if (!abandonWildsConfirm){
  2253. return false;
  2254. }
  2255. }
  2256. t.SetAbandonWilds(abandonWilds?false:true);
  2257. SetAbandonWildsA();
  2258. },false);
  2259. SetAbandonWildsA();
  2260. //raiseGold.parentNode.insertBefore(b,raiseGold.nextSibling);
  2261. productionHeader.parentNode.insertBefore(b,productionHeader);
  2262. },
  2263.  
  2264. ClickShareToWall:function(box) {
  2265. var t=this;
  2266. if(t.options.autoPublishGamePopups){
  2267. var sharetowall_btn = nHtml.FindByXPath(box,".//a[contains(@onclick,'gethelp')]");
  2268. nHtml.Click(sharetowall_btn);
  2269. }
  2270. },
  2271.  
  2272. marketBoxTimeout:null,
  2273. OnMarketBoxAppear:function(box) {
  2274. var marketBox=ById('marketmain_bdy');
  2275. var t=this;
  2276. if(marketBox) {
  2277. window.setTimeout(function() {
  2278. t.OnMarketBoxAppear();
  2279. },250);
  2280. var amt=ById('marketmod_amount');
  2281. if(amt && amt.value=="0") amt.value='999000';
  2282. var price=ById('marketmod_price');
  2283. if(price && price.value=="0") price.value='1';
  2284. }
  2285. },
  2286.  
  2287. nextAutoAttackTimeout:null,
  2288. onclickTimeRe:/,([0-9]+),[0-9]+,[0-9]+,[0-9]+[^,]*$/,
  2289. waitForAttackBoxAppear:null,
  2290. knightmarchid:0,
  2291. OnAttackBoxAppear:function(box) {
  2292. var btnMarch=ById('btnMarch');
  2293. var t=this;
  2294. if(!btnMarch) {
  2295. this.Log('no march button');
  2296. window.setTimeout(function() {
  2297. t.OnAttackBoxAppear(box);
  2298. },1000);
  2299. return;
  2300. }
  2301.  
  2302. this.StopWaitForAttackBoxAppear();
  2303. if(ById('KocAttackComment')) {
  2304. this.Log("We already have an attack dialog opened");
  2305. return;
  2306. }
  2307. var addAttackContainerDiv=document.createElement('div');
  2308. addAttackContainerDiv.id = "addAttackButtonContainerDiv";
  2309. addAttackContainerDiv.style.position = "relative";
  2310. addAttackContainerDiv.style.width = "1px";
  2311. addAttackContainerDiv.style.height = "1px";
  2312. addAttackContainerDiv.style.overflow = "visible";
  2313. var addAttackDiv=document.createElement('div');
  2314. addAttackDiv.id = "addAttackButtonDiv";
  2315. addAttackDiv.style.width = "250px";
  2316. addAttackDiv.style.left = "430px";
  2317. addAttackDiv.style.top = "5px";
  2318. addAttackDiv.style.position = "absolute";
  2319. addAttackDiv.style.overflow = "visible";
  2320. addAttackDiv.style.textAlign="left";
  2321.  
  2322. var addBtn=document.createElement('a');
  2323. addBtn.className='button25';
  2324. addBtn.style.cssFloat="left";
  2325. addBtn.innerHTML='<span>Add Attack</span>';
  2326. addBtn.addEventListener('click',function() {
  2327. t.ClickMarch(null, box, true, true);
  2328. },false);
  2329. addAttackDiv.appendChild(addBtn);
  2330. addAttackContainerDiv.appendChild(addAttackDiv);
  2331. var locationTypeDiv=document.createElement('div');
  2332. locationTypeDiv.id="KOCAttackLocationTypeDiv"
  2333. locationTypeDiv.style.width="300px"
  2334. locationTypeDiv.style.position="absolute";
  2335. locationTypeDiv.style.left="0px";
  2336. locationTypeDiv.style.top="-23px";
  2337. locationTypeDiv.style.fontSize="10px";
  2338. locationTypeDiv.style.textAlign="left";
  2339. // radio boxes for defining bulk coordinate type
  2340. var arrData = [["Camp", "Camp"],["City", "City"],["Transport", "Transport"],["Wilderness", "Wilderness"]];
  2341. for (var i=0; i < arrData.length; i++){
  2342. var objRadItem = document.createElement("input");
  2343. objRadItem.type = "radio";
  2344. objRadItem.name = "KOCAttackLocationType";
  2345. objRadItem.id = "KOCAttackLocationType_" + arrData[i][0];
  2346. objRadItem.value = arrData[i][0];
  2347.  
  2348. if(i == 0) {objRadItem.defaultChecked = true; objRadItem.checked = true; };
  2349.  
  2350. var objTextNode = document.createTextNode(" " + arrData[i][1]);
  2351.  
  2352. var objLabel = document.createElement("label");
  2353. objLabel.htmlFor = objRadItem.id;
  2354. objLabel.appendChild(objRadItem);
  2355. objLabel.appendChild(objTextNode);
  2356. locationTypeDiv.appendChild(objLabel);
  2357. objRadItem.addEventListener('change',function() {
  2358. var locationType = "Camp"; // Set default value to camp
  2359. var locationTypeRadioBoxes = ByName('KOCAttackLocationType');
  2360. if(locationTypeRadioBoxes){
  2361. for(var i = 0; i < locationTypeRadioBoxes.length; i++) {
  2362. if(locationTypeRadioBoxes[i].checked) {
  2363. locationType = locationTypeRadioBoxes[i].value;
  2364. break;
  2365. }
  2366. }
  2367. }
  2368. // Select the same radio box in the bulk add area
  2369. var bulkLocationTypeRadioBoxes = ByName('KOCAttackBulkAddLocationType');
  2370. if(bulkLocationTypeRadioBoxes){
  2371. for(var i = 0; i < bulkLocationTypeRadioBoxes.length; i++) {
  2372. if(bulkLocationTypeRadioBoxes[i].value == locationType) {
  2373. bulkLocationTypeRadioBoxes[i].checked = true;
  2374. break;
  2375. }
  2376. }
  2377. }
  2378. },false);
  2379.  
  2380. };
  2381. addAttackDiv.appendChild(locationTypeDiv);
  2382. var suicideSpan=document.createElement('span');
  2383. suicideSpan.style.fontSize="11px";
  2384. var suicideCheckbox=document.createElement('input');
  2385. suicideCheckbox.id = "KOCAttackSuicideWaveCheckbox";
  2386. suicideCheckbox.name = suicideCheckbox.id;
  2387. suicideCheckbox.type='checkbox';
  2388. suicideSpan.appendChild(suicideCheckbox);
  2389. AddHtml(suicideSpan,'<label for="KOCAttackSuicideWaveCheckbox">This is a suicide wave</label>');
  2390. addAttackDiv.appendChild(suicideSpan);
  2391. suicideCheckbox.addEventListener('click',function() {
  2392. var bulkAddSuicideWaveCheckbox = ById("KOCAttackBulkAddSuicideWave");
  2393. var locationType_Wilderness = ById("KOCAttackLocationType_Wilderness");
  2394. var bulkAddLocationType_Wilderness = ById("KOCAttackBulkAddLocationType_Wilderness");
  2395. if(bulkAddSuicideWaveCheckbox && locationType_Wilderness && bulkAddLocationType_Wilderness){
  2396. if(suicideCheckbox.checked){
  2397. bulkAddSuicideWaveCheckbox.checked = true;
  2398. locationType_Wilderness.checked = true;
  2399. bulkAddLocationType_Wilderness.checked = true;
  2400. }else{
  2401. bulkAddSuicideWaveCheckbox.checked = false;
  2402. }
  2403. }
  2404. },false);
  2405. if(btnMarch){
  2406. btnMarch.parentNode.insertBefore(addAttackContainerDiv,btnMarch);
  2407. }
  2408.  
  2409. var comment=document.createElement('input');
  2410. comment.id='KocAttackComment';
  2411. comment.size='30';
  2412.  
  2413. var nowSecs=new Date().getTime()/1000;
  2414.  
  2415. var div=document.createElement('div');
  2416. AddText(div,'Comment:');
  2417. div.appendChild(comment);
  2418. div.appendChild(document.createElement('br'));
  2419.  
  2420. var div2=document.createElement('div');
  2421. var ignore=document.createElement('input');
  2422. ignore.type='checkbox';
  2423. div2.appendChild(ignore);
  2424. AddText(div2,'Ignore in the attack list');
  2425. var div3=document.createElement('div');
  2426. var deletefarmno=document.createElement('input');
  2427. deletefarmno.type='checkbox';
  2428. div3.appendChild(deletefarmno);
  2429. AddText(div3,'Do not delete this report');
  2430. var nextElement=ById('marchTypeDesc');
  2431. //nextElement.parentNode.insertBefore(div2, nextElement.nextSibling);
  2432. //div.appendChild(document.createElement('br'));
  2433. div.appendChild (div2);
  2434. div2.appendChild (div3);
  2435. var xy=this.GetGuiCoords();
  2436. var attack=null;
  2437. if(xy) {
  2438. attack=this.GetAttack(xy[0],xy[1]);
  2439. }
  2440. var notFullTroops=false;
  2441. var notFullResources=false;
  2442.  
  2443. var knightSelect=ById('modal_attack_knight');
  2444. var totalTroops=0;
  2445. var totalResources=0;
  2446. var attackTypeSelected = getAttackTypeSelected();
  2447. if(attack) {
  2448. ignore.checked=attack.ignore?true:false;
  2449. deletefarmno.checked=attack.deletefarmno?true:false;
  2450. if(attack.time) {
  2451. AddHtml(div,'Last attack: '+SecsToStr(nowSecs-attack.time)+' ago<br />');
  2452. }
  2453. if(attack.comment){
  2454. comment.value=attack.comment;
  2455. }
  2456. // Select the attack type radio boxes
  2457. var wildtype={
  2458. 'Lake':'Wilderness',
  2459. 'Mountains':'Wilderness',
  2460. 'Woods':'Wilderness',
  2461. 'Forest':'Wilderness',
  2462. 'Plain':'Wilderness',
  2463. 'Hills':'Wilderness',
  2464. 'Grassland':'Wilderness',
  2465. 'Wilderness':'Wilderness' // Unknown wilderness type
  2466. };
  2467. var levelInfo=this.GetLevelInfo(attack);
  2468. var locationType = "City"; // Default to city
  2469. if(levelInfo && levelInfo.type) {
  2470. locationType = levelInfo.type;
  2471. }
  2472. if(wildtype[levelInfo.type]) {
  2473. locationType = wildtype[levelInfo.type];
  2474. }
  2475. // Select the location type radio box in the normal add area
  2476. var locationTypeRadioBoxes = ByName('KOCAttackLocationType');
  2477. if(locationTypeRadioBoxes){
  2478. for(var i = 0; i < locationTypeRadioBoxes.length; i++) {
  2479. if(locationTypeRadioBoxes[i].value == locationType) {
  2480. locationTypeRadioBoxes[i].checked = true;
  2481. break;
  2482. }
  2483. }
  2484. }
  2485. // Select the location type radio box in the bulk add area
  2486. var bulkLocationTypeRadioBoxes = ByName('KOCAttackBulkAddLocationType');
  2487. if(bulkLocationTypeRadioBoxes){
  2488. for(var i = 0; i < bulkLocationTypeRadioBoxes.length; i++) {
  2489. if(bulkLocationTypeRadioBoxes[i].value == locationType) {
  2490. bulkLocationTypeRadioBoxes[i].checked = true;
  2491. break;
  2492. }
  2493. }
  2494. }
  2495. // only fill things in if we're in attack mode.
  2496. if(attackTypeSelected==0 && attack.type==0) { // if 'attack' mode
  2497. SuicideAttackDefined = this.isSuicideAttackDefinedAtLocation(xy[0], xy[1])
  2498. if(this.prevAttack) { this.Log('Previous attack:'+this.prevAttack.x+'=='+xy[0] +','+this.prevAttack.y+'=='+xy[1] ); }
  2499. var firstAttack = this.IsFirstAttackAtLocation(xy[0], xy[1]);
  2500. this.Log("current attack wave type: "+attack.currenttattackwavetype);
  2501. if(SuicideAttackDefined && firstAttack) {
  2502. // anti traps suicide wave attack
  2503. if(typeof(attack.suicidewave)=="object") {
  2504. for(var i=1; i<attack.suicidewave.length; i++) {
  2505. this.SetTroopInput(i,attack.suicidewave[i]);
  2506. totalTroops+=attack.suicidewave[i];
  2507. }
  2508. } else {
  2509. this.SetTroopInput(2,attack.suicidewave);
  2510. totalTroops+=attack.suicidewave;
  2511. }
  2512. // Check the suicide wave checkbox
  2513. suicideCheckbox.checked = true;
  2514. } else if(attack.troops) {
  2515. for(var tr=0; tr<attack.troops.length; tr++) {
  2516. var troopCount=attack.troops[tr];
  2517. if(!troopCount) continue;
  2518. totalTroops+=troopCount;
  2519.  
  2520. if(this.SetTroopInput(tr,troopCount)=='notfull') {
  2521. notFullTroops=true;
  2522. }
  2523. }
  2524. // Make sure the suicide wave checkbox is *not* checked
  2525. suicideCheckbox.checked = false;
  2526. }
  2527.  
  2528. //attackTypeSelect.selectedIndex=attack.type;
  2529. if(this.knightmarchid == knightSelect.options[knightSelect.selectedIndex].value){
  2530. knightSelect.selectedIndex = 1+Math.floor(Math.random()*(knightSelect.options.length-1)); //Select random knight if last knight didn't go out
  2531. }
  2532. } else if (attackTypeSelected==1 && attack.type==1) { // transport
  2533. ById('KOCAttackLocationType_Transport').checked;
  2534. // If transporting, we enable all troop types. No reason to restrict ourselves to just normal supply troops!
  2535. var supplyfilter_checkbox = ById('modal_attack_supplyfilter_checkbox');
  2536. if(supplyfilter_checkbox){
  2537. if(supplyfilter_checkbox.checked){
  2538. supplyfilter_checkbox.click();
  2539. }
  2540. }
  2541. var resourceTypes = new Array(
  2542. 'gold',
  2543. 'rec1',
  2544. 'rec2',
  2545. 'rec3',
  2546. 'rec4'
  2547. );
  2548. for(var tr=0; tr<attack.troops.length; tr++) {
  2549. var troopCount=attack.troops[tr];
  2550. if(!troopCount) continue;
  2551. totalTroops+=troopCount;
  2552.  
  2553. if(this.SetTroopInput(tr,troopCount)=='notfull') {
  2554. this.Log("Input field disabled for troop type: "+tr);
  2555. notFullTroops=true;
  2556. }
  2557. }
  2558.  
  2559. for(var res=0; res<attack.resources.length; res++) {
  2560. var resourceCount=attack.resources[res];
  2561. if(!resourceCount) continue;
  2562. totalResources+=resourceCount;
  2563.  
  2564. if(this.SetResourceInput(resourceTypes[res],resourceCount)=='notfull') {
  2565. notFullResources=true;
  2566. }
  2567. }
  2568. // We don't send a knight with transports
  2569. knightSelect.selectedIndex = 0;
  2570. }
  2571. if(attack.messages) {
  2572. div.appendChild(document.createElement('br'));
  2573. for(var m=attack.messages.length-1; m>=0; m--) {
  2574. var message=attack.messages[m];
  2575. var ma=document.createElement('a');
  2576. var mess=message[0];
  2577. var timeNumM=this.onclickTimeRe.exec(message[1]);
  2578. if(timeNumM) {
  2579. var secs=nowSecs-parseInt(timeNumM[1]);
  2580. mess=SecsToStr(secs)+' ago, '+mess;
  2581. //mess=(new Date(parseFloat(timeNumM[1])*1000).toLocalString())+', '+mess;
  2582. }
  2583. ma.innerHTML=mess;
  2584. //{"time":1273315720.514,"troops":"test","type":0,"messages":[["Attack (326,97) - Barbarian Camp Lv. 2 (NewCity4216)","modal_messages_viewreports_view(\"529747\",1,51,2,0,\"Enemy\",\"0\",\"niknah\",\"M\",4,326,97,1273312617,1,333,110);return false;"],["Attack (326,97) - Barbarian Camp Lv. 2 (NewCity4216)","modal_messages_viewreports_view(\"529747\",1,51,2,0,\"Enemy\",\"0\",\"niknah\",\"M\",4,326,97,1273312617,0,333,110);return false;"]]}
  2585. ma.setAttribute('onclick',"var m=CreateMsgDiv(); "+ message[1]+'');
  2586. ma.href='javascript:;';
  2587. div.appendChild(ma);
  2588. div.appendChild(document.createElement('br'));
  2589. }
  2590. div.appendChild(document.createElement('br'));
  2591. }
  2592. // Show the "Delete Attack" button
  2593. var deleteBtnDiv=document.createElement('div');
  2594. deleteBtnDiv.id = "deleteAttackButtonDiv";
  2595. deleteBtnDiv.style.width = "115px";
  2596. deleteBtnDiv.style.left = "203px";
  2597. deleteBtnDiv.style.top = "5px";
  2598. deleteBtnDiv.style.position = "absolute";
  2599. var deleteBtn=document.createElement('a');
  2600. deleteBtn.className='button25';
  2601. deleteBtn.innerHTML='<span>Delete Attack</span>';
  2602. deleteBtn.addEventListener('click',function() {
  2603. t.DeleteAttack(xy[0],xy[1]);
  2604. t.DoUnsafeWindow('Modal.hideModalAll();');
  2605. },false);
  2606. deleteBtnDiv.appendChild(deleteBtn);
  2607. addAttackContainerDiv.appendChild(deleteBtnDiv);
  2608.  
  2609. //div.insertBefore (deleteBtn, div.firstChild);
  2610. }
  2611. var ChangeAttack=function() {
  2612. var xy=t.GetGuiCoords();
  2613. var attack=null;
  2614. if(xy) {
  2615. attack=t.GetAttack(xy[0],xy[1]);
  2616. }
  2617. if(!attack) attack={};
  2618. if(getAttackTypeSelected()!=attack.type) {
  2619. t.Log('We wont change an attack if the type is different. You must delete the attack to change the type');
  2620. return;
  2621. }
  2622. attack.comment=comment.value;
  2623. attack.ignore=ignore.checked?true:undefined;
  2624. attack.deletefarmno=deletefarmno.checked?true:undefined;
  2625. t.SetAttack(xy[0],xy[1],attack);
  2626. }
  2627. comment.addEventListener('change',function() { ChangeAttack(); },false);
  2628. ignore.addEventListener('change',function() { ChangeAttack(); },false);
  2629. deletefarmno.addEventListener('change',function() { ChangeAttack(); },false);
  2630. var divContainer = document.createElement ('div');
  2631. divContainer.style.padding = '0px 12px';
  2632. divContainer.style.height = '320px';
  2633. divContainer.style.maxHeight = '320px';
  2634. divContainer.style.overflowY = 'auto';
  2635. divContainer.appendChild(this.HideAttackEfforts());
  2636. divContainer.appendChild(div);
  2637. divContainer.appendChild(this.BulkAddAttackLink(box));
  2638. document.getElementById ('modal_attack').appendChild(divContainer);
  2639. this.AttachXYPaste('modal_attack_target_coords_x','modal_attack_target_coords_y');
  2640. var autoAttack=this.GetAutoAttack();
  2641. if(autoAttack && autoAttack.x==xy[0] && autoAttack.y==xy[1] && !ignore.checked) {
  2642.  
  2643. autoAttack.x=autoAttack.y=-1;
  2644. this.SetAutoAttack(autoAttack);
  2645.  
  2646. if(totalTroops>0
  2647. && (knightSelect.options.length>1 || attackTypeSelected==1)//If transport you don't need knights(Thanks to shalm for pointing that out)
  2648. && !notFullTroops
  2649. && !notFullResources
  2650. && btnMarch.className.indexOf('grey')<0
  2651. ) {
  2652. this.Log('Auto attack: '+xy[0]+','+xy[1]+', from city:'+this.autoAttackCityUpto);
  2653. var t=this;
  2654. window.setTimeout(function() {
  2655. t.autoAttacksThisCity++;
  2656. t.ClickMarch(btnMarch, box, false);
  2657. this.knightmarchid = knightSelect.options[knightSelect.selectedIndex].value;
  2658. //t.ResetIdStatus();
  2659. },t.GetRandTime(1000));
  2660.  
  2661. if(!this.nextAutoAttackTimeout) {
  2662. this.nextAutoAttackTimeout=setTimeout(function() {
  2663. // let's attack again in a few secs.
  2664. t.nextAutoAttackTimeout=null;
  2665. t.NextAutoAttack();
  2666. },t.GetRandTime(1000*this.options.attackDelay));
  2667. } else {
  2668. this.Log('Cannot continue auto attacking, about to attack or change city');
  2669. }
  2670. return;
  2671. } else {
  2672. this.Log('Unable to send attack to '+xy[0]+','+xy[1]+', knights avail:'+(knightSelect.options.length-1)+', Not enough troops: '+notFullTroops+'(need '+totalTroops+'). Not enough resources:'+notFullResources+' (need '+totalResources+')');
  2673. this.DoUnsafeWindow("Modal.hideModal();");
  2674. this.NextAutoAttackCity();
  2675. }
  2676. }
  2677. },
  2678. ClickMarch:function(btnMarch, box, alert, resetTime){
  2679. if(!resetTime){resetTime=false;}
  2680. var t = this;
  2681. if(btnMarch){
  2682. nHtml.Click(btnMarch);
  2683. window.setTimeout(function() {
  2684. var mist=nHtml.FindByXPath(document,".//div[@class='mistwarn']");
  2685. if(mist) {
  2686. t.DoUnsafeWindow("Modal.hideModal();");
  2687. t.DoUnsafeWindow("modal_attack_do();");
  2688. }
  2689. },t.GetRandTime(200));
  2690. }
  2691. var added = t.SetAttackFromGui(box, resetTime);
  2692. t.SetValuesCache();
  2693. if(added){
  2694. if(alert){
  2695. window.alert("Added attack");
  2696. }
  2697. }
  2698. },
  2699.  
  2700. coordsRe:/\(([0-9]+),([0-9]+)\)/,
  2701. maptileRe:/modal_maptile.([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+)/,
  2702.  
  2703. OnToolTipAppear:function(box) {
  2704. var box1=box.childNodes[0].childNodes[0];
  2705. var m=this.coordsRe.exec(box.innerHTML);
  2706. if(!m || m.length==0) return;
  2707.  
  2708. var x=m[1]; var y=m[2];
  2709.  
  2710. var a=ById('l_'+x+'_t_'+y);
  2711. if(a) {
  2712. var onclick=a.getAttribute('onclick');
  2713. if(onclick) {
  2714. var titleM=this.maptileRe.exec(onclick);
  2715. if(titleM && titleM[8].indexOf('null')<0) {
  2716. AddHtml(box1,'Title: '+titleM[8].StripQuotes()+'<br />');
  2717. }
  2718. }
  2719. }
  2720. var attack=this.GetAttack(x,y);
  2721. if(!attack) return;
  2722. var troops=attack.troops;
  2723. if(troops && troops.length>0) {
  2724. var lastAttack=parseInt(attack.time);
  2725. var nowSecs=new Date().getTime()/1000;
  2726. var lastAttackStr='Last attack: '+SecsToStr(nowSecs-lastAttack)+' ago'+(attack.ignore?' <b>(ignore)</b> ':'');
  2727. AddHtml(box1,lastAttackStr+'<br />');
  2728. if(attack.comment) {
  2729. AddHtml(box1,attack.comment+'<br />');
  2730. }
  2731. }
  2732. },
  2733.  
  2734.  
  2735. /*
  2736. // don't know why but messages get duped sometimes.
  2737. FixMessages:function(attack) {
  2738. var fixed=0;
  2739. var done={};
  2740. for(var m=0; m<attack.messages.length; m++) {
  2741. if(!done[attack.messages[m][1]]) {
  2742. done[attack.messages[m][1]]=true;
  2743. GM_log('ffff:'+attack.messages[m][1]+'####'+typeof(attack.messages[m][1]));
  2744. } else {
  2745. attack.messages.splice(m,1);
  2746. fixed++;
  2747. }
  2748. }
  2749. return fixed;
  2750. },
  2751. */
  2752.  
  2753. CalcXYDist:function(a,b) {
  2754. var xdist=parseInt(a.x)-parseInt(b.x);
  2755. xdist=Math.abs(xdist);
  2756. if(xdist>=375) xdist=750-xdist;
  2757. var ydist=parseInt(a.y)-parseInt(b.y);
  2758. ydist=Math.abs(ydist);
  2759. if(ydist>=375) ydist=750-ydist;
  2760. return Math.sqrt((xdist*xdist)+(ydist*ydist));
  2761. },
  2762.  
  2763. //attackRe:/\s+(\S+)\s+Lv\.\s*([0-9]+)/,
  2764. //javascript:Messages.viewMarchReport("22891795",0,51,10,1550996,"oftheNOOBS","M","Debby32","F",1,430,205,1302284981,1,284,83);
  2765. squareTypeNums:{
  2766. '51':'Camp',
  2767. '10':'Grassland',
  2768. '11':'Lake',
  2769. '20':'Forest',
  2770. '30':'Hills',
  2771. '40':'Mountains',
  2772. '50':'Plain',
  2773. '0':'Bog'
  2774. },
  2775. FindLevelFromMessages:function(attack) {
  2776. if(!attack || !attack.messages) return null;
  2777. for(var a=0; a<attack.messages.length; a++) {
  2778. var m=this.onclickReportRe.exec(attack.messages[a][1]);
  2779. if(!m) {
  2780. this.Log("Unable to find location level/type information in cached reports!");
  2781. continue;
  2782. }
  2783. var typeNum=m[3].replace('"','');
  2784. var type=this.squareTypeNums[typeNum];
  2785. if(!type) {
  2786. this.Log("Unable to find location type information in cached reports!");
  2787. continue;
  2788. }
  2789. if(typeNum=="51" && m[5]!='0') { //Gradually replace all attack types to follow Tom's new method of storing attacks
  2790. if(attack.type==0){
  2791. type='City';
  2792. } else if (attack.type==1){
  2793. type='Transport';
  2794. }
  2795. }
  2796. //this.Log("Target Type: "+type+", Target Level: "+m[4]);
  2797. return {'type':type,'level':m[4]};
  2798. }
  2799. return null;
  2800. },
  2801.  
  2802. DrawLevelIcons:function() {
  2803. var mapwindow=ById('mapwindow');
  2804. if(!mapwindow) return;
  2805. var levelIcons=ById('LevelIcons');
  2806. if(levelIcons) return;
  2807.  
  2808. var ss=document.evaluate(".//a[contains(@class,'slot')]",mapwindow,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
  2809. var lvRe=/_([0-9]+)/;
  2810. var idDone=false;
  2811. for(var s=0; s<ss.snapshotLength; s++) {
  2812. var a=ss.snapshotItem(s);
  2813. var onclick=a.getAttribute('onclick');
  2814. var owner='';
  2815. if(onclick) {
  2816. var onclickM=this.maptileRe.exec(onclick);
  2817. if(onclickM && onclickM[6]!='"null"' && onclickM[12]!='"city"') {
  2818. var might=onclickM[7].StripQuotes();
  2819. //var alliance=onclickM[9].StripQuotes();
  2820. //+"<br />"+(alliance=="null"?"":alliance);
  2821. owner=" "+onclickM[6].StripQuotes()+'<br />Might:'+might;
  2822. }
  2823. }
  2824. var m=lvRe.exec(a.className);
  2825. if(!m) continue;
  2826. var sp=a.getElementsByTagName('span');
  2827. if(sp.length==0) continue;
  2828.  
  2829. if(!idDone) { a.id='levelIcons'; idDone=true; }
  2830. sp[0].style.color='#cc0';
  2831. //sp[0].innerHTML='<center>'+m[1]+'</center>';
  2832. sp[0].innerHTML='&nbsp;'+m[1]+owner;
  2833. }
  2834.  
  2835. },
  2836.  
  2837. AttachXYPaste:function(xId,yId,func) {
  2838. var x=ById(xId);
  2839. if(!x) {
  2840. this.Log('Cannot find x coord box: '+xId);
  2841. return;
  2842. }
  2843. var attached=x.getAttribute('KOCpasteAttached');
  2844. if(attached) return;
  2845. x.setAttribute('maxlength','20');
  2846. var onchange=function() {
  2847. var xValue=x.value.trim();
  2848. var xI=/^\s*([0-9]+)[\s|,|-|.]+([0-9]+)/.exec(xValue);
  2849. if(xI) {
  2850. var y=ById(yId);
  2851. x.value=xI[1]
  2852. y.value=xI[2]
  2853.  
  2854. if(func!=undefined) func(xI[0],xI[1]);
  2855. }
  2856. }
  2857. x.setAttribute('KOCpasteAttached',true);
  2858. x.addEventListener('keyup',function() { onchange(); },false);
  2859. x.addEventListener('change',function() { onchange(); },false);
  2860. },
  2861.  
  2862.  
  2863. GetClosestAttacks:function(x,y) {
  2864. var attacks=[];
  2865. var t=this;
  2866. this.IterateAttacks(function(name,value) {
  2867. var nameI=name.split('_');
  2868. if(nameI.length<3) return;
  2869. var xy=nameI[2].split(',');
  2870. if(value=="") return;
  2871. var attack=JSON2.parse(value);
  2872. if(!attack) return;
  2873. if(attack.ignore) return;
  2874. var dist=t.CalcXYDist({'x':xy[0],'y':xy[1]},{'x':x,'y':y});
  2875. if (dist==0) { return; } // Don't attack yourself
  2876. if(dist>=t.options.attackMaxDistance) { return; }
  2877. if(t.options.lockAttackFromCity && attack.fromCity!=unsafeWindow.currentcityid) { return; }
  2878. attacks.push({'dist':dist,'x':xy[0],'y':xy[1],'a':attack});
  2879. });
  2880. attacks.sort(function(a,b) {
  2881. return a.dist-b.dist;
  2882. });
  2883. return attacks;
  2884. },
  2885.  
  2886. IsEnoughTroops:function(currentTroops,neededTroops) {
  2887. for(var t=0; t<neededTroops.length; t++) {
  2888. if(!neededTroops[t]) continue;
  2889. if(parseInt(neededTroops[t])>parseInt(currentTroops[t])) {
  2890. return false;
  2891. }
  2892. }
  2893. return true;
  2894. },
  2895.  
  2896. IsEnoughResources:function(currentResources,neededResources) {
  2897. for(var t=0; t<neededResources.length; t++) {
  2898. if(!neededResources[t]) continue;
  2899. if((parseInt(neededResources[t])+parseInt(this.options.transportResourcesReserveAmount))>parseInt(currentResources[t])) {
  2900. return false;
  2901. }
  2902. }
  2903. return true;
  2904. },
  2905.  
  2906. currentMarchesNum:0,
  2907. available_marches_num:0,
  2908. DetermineCurrentMarchesNum:function() {
  2909. var marchesnum = 0;
  2910. var troopactivity = ById("untqueue_list");
  2911. if(troopactivity && troopactivity.style.display!="none" && troopactivity.style.visibility!="hidden"){
  2912. marchesnum = troopactivity.childNodes.length;
  2913. }
  2914. //this.Log("Current number of marches in this city: "+marchesnum);
  2915. this.currentMarchesNum = marchesnum;
  2916. return marchesnum;
  2917. },
  2918.  
  2919. currentRallyPointLevel:0,
  2920. DetermineCurrentRallyPointLevel:function() {
  2921. var rallypointlevel = 0;
  2922. var citymap = ById("citymap");
  2923. if(citymap){
  2924. var citylinks = nHtml.FindByXPath(citymap,'.//a[contains(@class, "bldg")]', XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
  2925. for (var i = 0; i < citylinks.snapshotLength; i++){
  2926. var building = citylinks.snapshotItem(i);
  2927. var style = window.getComputedStyle(building, false);
  2928. var css_bgimg = style.backgroundImage;
  2929. //this.Log("building background image "+i+": "+css_bgimg);
  2930. var myregexp = /rally_point_lvl/i;
  2931. var match = myregexp.exec(css_bgimg);
  2932. if (match != null) {
  2933. // Determine the rally point level based on the level tag overlay
  2934. var leveltag = nHtml.FindByXPath(building,'.//span[contains(@class, "level")]');
  2935. if(!leveltag){ continue; }
  2936. var levelnum = parseInt(leveltag.innerHTML);
  2937. if(levelnum>rallypointlevel){
  2938. rallypointlevel = levelnum;
  2939. }
  2940. } else {
  2941. var b_class = building.className.split("_");
  2942. if(b_class != null){
  2943. if(parseInt(b_class[1]) == 12){
  2944. rallypointlevel = parseInt(b_class[2]);
  2945. // this.Log("classname "+b_class[1] +" "+b_class[2]);
  2946. }
  2947. }
  2948. }
  2949. }
  2950. if(rallypointlevel==0){
  2951. // Couldn't find the rally point based on the background image. Odds are that the rally point exists,
  2952. // but is currently under construction. Let's see if we can deduce the rally point's level based on this assumption.
  2953. // Note: This will bug out if the city has literally no rally point at all, but who's really that stupid?
  2954. for (var i = 0; i < citylinks.snapshotLength; i++){
  2955. var building = citylinks.snapshotItem(i);
  2956. var style = window.getComputedStyle(building, false);
  2957. var css_bgimg = style.backgroundImage;
  2958. //this.Log("building background image "+i+": "+css_bgimg);
  2959. var myregexp = /construction/i;
  2960. var match = myregexp.exec(css_bgimg);
  2961. if (match != null) {
  2962. // Determine the rally point level based on the level tag overlay
  2963. var leveltag = nHtml.FindByXPath(building,'.//span[contains(@class, "level")]');
  2964. if(!leveltag){ continue; }
  2965. var levelnum = parseInt(leveltag.innerHTML);
  2966. if(levelnum>rallypointlevel){
  2967. rallypointlevel = levelnum-1;
  2968. }
  2969. }
  2970. }
  2971. }
  2972. this.Log("Rally point level in this city is: "+rallypointlevel);
  2973. }
  2974. if(rallypointlevel==12) rallypointlevel = 11;
  2975. this.currentRallyPointLevel = rallypointlevel;
  2976. return rallypointlevel;
  2977. },
  2978.  
  2979. GetLevelInfo:function(attack) {
  2980. if(!attack) throw('GetLevelInfo: attack is null');
  2981. var levelI=attack.levelInfo;
  2982. //if((!levelI || levelI.level==0) && attack.messages && attack.messages.length>0) {
  2983. if((!levelI || levelI.level==0 || levelI.type=="" || levelI.type=="Camp") && attack.messages && attack.messages.length>0) { //The idea is to replace all old attacks with the new one
  2984. levelI=this.FindLevelFromMessages(attack);
  2985. }
  2986. if (!levelI && (attack.currenttattackwavetype == 'transport')){
  2987. return {'type':'Transport','level':0};
  2988. }
  2989. // if (!levelI){
  2990. // return {'type':'Camp','level':0}; // Default to camp
  2991. // }
  2992. //All old attacks for city are stored as "" So disable this option for the mean time
  2993. //if(levelI.type==""){levelI.type="Camp";}
  2994. return levelI;
  2995. },
  2996.  
  2997. GetAttackDelay:function(attack) {
  2998. if(!attack) throw('GetAttackDelay: attack is null');
  2999. var attackDelay = 0;
  3000. var wilderness={
  3001. 'Lake':1,
  3002. 'Mountains':1,
  3003. 'Woods':1,
  3004. 'Forest':1,
  3005. 'Plain':1,
  3006. 'Hills':1,
  3007. 'Grassland':1,
  3008. 'Wilderness':1 // Unknown wilderness type
  3009. };
  3010. var levelInfo=this.GetLevelInfo(attack);
  3011. if(!levelInfo) {
  3012. this.Log("Unable to calculate attack delay: Missing level info for coordinates ("+attack.x+","+attack.y+"). Assuming delay of 0.");
  3013. }else{
  3014. if(levelInfo.type=='Camp') {
  3015. // Camp
  3016. attackDelay = this.options.attackSecsSinceLastCamp;
  3017. } else if(wilderness[levelInfo.type]) {
  3018. // Wilderness
  3019. attackDelay = this.options.attackSecsSinceLastWild;
  3020. } else if (levelInfo.type!='Camp' && !wilderness[levelInfo.type]) {
  3021. var tempAttack=this.GetAttack(attack.x,attack.y);
  3022. if(tempAttack){
  3023. if(tempAttack.type==0) {
  3024. // City
  3025. attackDelay = this.options.attackSecsSinceLastCity;
  3026. } else if(tempAttack.type==1) {
  3027. // Transport
  3028. attackDelay = this.options.attackSecsSinceLastTransport;
  3029. }else{
  3030. this.Log("Unknown attack type for ("+attack.x+","+attack.y+"). Assuming delay of 0.");
  3031. }
  3032. }else{
  3033. this.Log("Unknown/Invalid attack specified ("+attack.x+","+attack.y+").");
  3034. }
  3035. }else{
  3036. this.Log("Unknown attack type for ("+attack.x+","+attack.y+"). Assuming delay of 0.");
  3037. }
  3038. }
  3039. return attackDelay;
  3040. },
  3041. priorityattack:true,
  3042. FindBiggestCampAttack:function(attacks,currentTroops,currentResources) {
  3043. var bestAttack=null;
  3044. var bestAttackSize=0;
  3045. var bestAttackDist=10000;
  3046. var nowSecs=new Date().getTime()/1000;
  3047. var currentCity = this.GetCurrentCityId();
  3048. // Determine the current rally point level and current marches
  3049. this.DetermineCurrentRallyPointLevel();
  3050. this.DetermineCurrentMarchesNum();
  3051. this.Log("Current Rally Point Level: "+this.currentRallyPointLevel+" Current Marches: "+this.currentMarchesNum);
  3052.  
  3053. var wilderness={
  3054. 'Lake':1,
  3055. 'Mountains':1,
  3056. 'Woods':1,
  3057. 'Forest':1,
  3058. 'Plain':1,
  3059. 'Hills':1,
  3060. 'Grassland':1,
  3061. 'Wilderness':1 // Unknown wilderness type
  3062. };
  3063. for(var a=0; a<attacks.length; a++) {
  3064. var attack=attacks[a];
  3065. //this.Log("Inspecting attack #"+a+": "+inspect(attack,10));
  3066. var levelInfo=this.GetLevelInfo(attack.a);
  3067. if(!levelInfo) {
  3068. this.Log("Not attacking: Missing level info! for coordinates ("+attack.x+","+attack.y+")");
  3069. continue;
  3070. }
  3071. if(levelInfo.type == ""){levelInfo.type = this.FindLevelFromMessages(attack);;} // If empty look in messages
  3072. if(levelInfo.type == ""){levelInfo.type = "City";} // If still blanck default to city
  3073. if(levelInfo.type=='Camp') {
  3074. if(this.options.attackTypeCamp!=true) {
  3075. this.Log("Not attacking: Not attacking camps! for coordinates ("+attack.x+","+attack.y+")");
  3076. continue;
  3077. }
  3078. } else if(wilderness[levelInfo.type]) {
  3079. if(this.options.attackTypeWild!=true) {
  3080. this.Log("Not attacking: Not attacking wildernesses! for coordinates ("+attack.x+","+attack.y+")");
  3081. continue;
  3082. }
  3083. } else if (levelInfo.type!='Camp' && !wilderness[levelInfo.type]) {
  3084. var tempAttack=this.GetAttack(attack.x,attack.y);
  3085. if(!tempAttack){
  3086. this.Log("Not attacking: Invalid attack entered ("+attack.x+","+attack.y+")");
  3087. continue;
  3088. }
  3089. if(tempAttack.type==0) {
  3090. if(this.options.attackTypeCity!=true) {
  3091. this.Log("Not attacking: Not attacking cities for coordinates ("+attack.x+","+attack.y+")");
  3092. continue;
  3093. }
  3094. } else if(tempAttack.type==1) {
  3095. if(this.options.attackTypeTransport!=true) {
  3096. this.Log("Not attacking: Not sending transports for coordinates ("+attack.x+","+attack.y+")");
  3097. continue;
  3098. }
  3099. }
  3100. } else {
  3101. if(levelInfo.type!='City' && levelInfo.type!='Camp') {
  3102. this.Log("Not attacking: Unknown attack type for coordinates ("+attack.x+","+attack.y+")");
  3103. continue;
  3104. }
  3105. }
  3106.  
  3107. if(!attack.a.troops) {
  3108. this.Log("inspect1: "+inspect(attack.a),10);
  3109. this.Log("Not attacking: No troops defined for coordinates ("+attack.x+","+attack.y+")");
  3110. continue;
  3111. }
  3112. if(attack.a.ignore) {
  3113. this.Log("Not attacking: Location ignored for coordinates ("+attack.x+","+attack.y+")");
  3114. continue;
  3115. }
  3116. if(attack.dist>=this.options.attackMaxDistance) {
  3117. this.Log("Not attacking: Distance too far for coordinates ("+attack.x+","+attack.y+")");
  3118. continue;
  3119. }
  3120. if(this.options.lockAttackFromCity) {
  3121. //this.Log('fromCity='+attack.a.fromCity+', currentCity='+this.GetCurrentCityId());
  3122. if(attack.a.fromCity!=undefined) {
  3123. if(currentCity!=attack.a.fromCity) { continue; }
  3124. }
  3125. }
  3126. var troops_to_send = attack.a.troops;
  3127. if(attack.a.suicidewave){
  3128. // count up all the troops in *both* attack waves.
  3129. // we don't want to launch suicide wave if we can't follow it up.
  3130. var suicide_troops = attack.a.suicidewave;
  3131. for(var t=0; t<suicide_troops.length; t++) {
  3132. if(!suicide_troops[t]) continue;
  3133. troops_to_send[t] = troops_to_send[t] + suicide_troops[t];
  3134. }
  3135. }
  3136.  
  3137. //if(!this.currentMarchesNum || this.currentMarchesNum==undefined) {
  3138. // this.Log("Not attacking: Unable to determine current number of marches (refresh your window?) for coordinates ("+attack.x+","+attack.y+")");
  3139. // continue;
  3140. //}
  3141. // Make sure we have more than two available slots in attack queue if this is a suicide wave (unless there are only two slots even allowed)
  3142. this.available_marches_num = this.currentRallyPointLevel - this.currentMarchesNum - this.options.rallyKeep;
  3143. //this.Log("Available marches: "+available_marches_num);
  3144. if(attack.a.suicidewave && attack.a.currenttattackwavetype != "normal"){
  3145. //this.Log("Current attack wave type: "+attack.a.currenttattackwavetype);
  3146. if(this.available_marches_num < 2 || this.currentRallyPointLevel < 2){
  3147. // Make sure this is the first wave of the multi-wave attack and then don't send it if there aren't enough marching slots for both waves
  3148. if(this.IsFirstAttackAtLocation(attack.x, attack.y)) {
  3149. // This is the first wave
  3150. this.Log("Not attacking: Not enough available marching slots at rally point to launch both suicide wave and second wave for coordinates ("+attack.x+","+attack.y+")");
  3151. break;
  3152. }
  3153. }
  3154. }
  3155. // Make sure we have at least one available slot in attack queue for normal attack
  3156. if(this.available_marches_num<1){
  3157. this.Log("Not attacking: Not enough marching slots at rally point to launch attack for coordinates ("+attack.x+","+attack.y+")");
  3158. break;
  3159. }
  3160. if(!this.IsEnoughTroops(currentTroops,troops_to_send)) {
  3161. this.Log("Not attacking: Not enough troops for coordinates ("+attack.x+","+attack.y+")");
  3162. continue;
  3163. }
  3164. if (attack.a.type==1) {
  3165. if(!this.IsEnoughResources(currentResources,attack.a.resources)) {
  3166. this.Log("Not attacking: Not enough resources for coordinates ("+attack.x+","+attack.y+")");
  3167. continue;
  3168. }
  3169. }
  3170. var lastAttack;
  3171. if(!attack.a.time) {
  3172. lastAttack=60*60*24*31;
  3173. } else {
  3174. lastAttack=nowSecs-parseInt(attack.a.time);
  3175. }
  3176. if(levelInfo.type=='' || levelInfo.type=='City' || levelInfo.type=='Transport') {
  3177. if(attack.a.type==0) {
  3178. if(lastAttack<this.options.attackSecsSinceLastCity) {
  3179. this.Log("Not attacking: last attack ("+lastAttack+") < this.options.attackSecsSinceLastCity ("+this.options.attackSecsSinceLastCity+") for coordinates ("+attack.x+","+attack.y+")");
  3180. continue;
  3181. }
  3182. } else {
  3183. if(lastAttack<this.options.attackSecsSinceLastTransport){
  3184. this.Log("Not attacking: last attack ("+lastAttack+") < this.options.attackSecsSinceLastTransport ("+this.options.attackSecsSinceLastTransport+") for coordinates ("+attack.x+","+attack.y+")");
  3185. continue;
  3186. }
  3187. }
  3188. } else if(levelInfo.type=='Camp') {
  3189. if(lastAttack<this.options.attackSecsSinceLastCamp) {
  3190. this.Log("Not attacking: last attack ("+lastAttack+") < this.options.attackSecsSinceLastCamp ("+this.options.attackSecsSinceLastCamp+") for coordinates ("+attack.x+","+attack.y+")");
  3191. continue;
  3192. }
  3193. } else {
  3194. if(lastAttack<this.options.attackSecsSinceLastWild) {
  3195. this.Log("Not attacking: last attack ("+lastAttack+") < this.options.attackSecsSinceLastWild ("+this.options.attackSecsSinceLastWild+") for coordinates ("+attack.x+","+attack.y+")");
  3196. continue;
  3197. }
  3198. }
  3199. var armySize=0;
  3200. for(var t=0; t<attack.a.troops.length; t++) {
  3201. if(!attack.a.troops[t]) {
  3202. continue;
  3203. }
  3204. armySize+=parseInt(attack.a.troops[t]);
  3205. }
  3206. if(attack.a.suicidewave) {
  3207. var suicideArmySize=0;
  3208. for(var t=0; t<attack.a.suicidewave.length; t++) {
  3209. if(!attack.a.suicidewave[t]) {
  3210. continue;
  3211. }
  3212. suicideArmySize+=parseInt(attack.a.suicidewave[t]);
  3213. }
  3214. if(suicideArmySize<=0) {
  3215. this.Log('Invalid suicide wave army size (not enough!) for coordinates ('+attack.x+','+attack.y+')');
  3216. continue;
  3217. }
  3218. }
  3219. if(armySize<=0) {
  3220. this.Log('Invalid suicide wave army size (not enough!) for coordinates ('+attack.x+','+attack.y+')');
  3221. continue;
  3222. }
  3223.  
  3224. var ok=0;
  3225. if(this.options.attackOrder=='mostTroops') {
  3226. if(bestAttackSize<armySize) {
  3227. ok=1;
  3228. }
  3229. } else {
  3230. if(this.options.attackOrder!='closest') {
  3231. this.Log('Unknown order:'+this.options.attackOrder);
  3232. }
  3233. if(bestAttackDist>attack.dist) {
  3234. ok=1;
  3235. }
  3236. }
  3237. if((this.options.attackpriority == levelInfo.type || this.options.attackpriority == 'None') && ok && this.priorityattack){
  3238. bestAttack=attack;
  3239. bestAttack.type=attack.a.type;
  3240. bestAttackSize=armySize;
  3241. bestAttackDist=attack.dist;
  3242. } else if (!this.priorityattack && ok) {
  3243. bestAttack=attack;
  3244. bestAttack.type=attack.a.type;
  3245. bestAttackSize=armySize;
  3246. bestAttackDist=attack.dist;
  3247. }
  3248. }
  3249. if(bestAttack == null && this.priorityattack){
  3250. this.priorityattack = false;
  3251. bestAttack = this.FindBiggestCampAttack(attacks,currentTroops,currentResources);
  3252. } else {
  3253. this.priorityattack = true;
  3254. }
  3255. return bestAttack;
  3256. },
  3257. IsMapperRunning:function() {
  3258. if(ById('SendMap')) {
  3259. this.Log('mapper is running, do not auto attack');
  3260. return true;
  3261. }
  3262. return false;
  3263. },
  3264. GetAutoAttack:function() {
  3265. var aStr=this.GetValue('AutoAttack','');
  3266. if(aStr=='') {
  3267. return null;
  3268. }
  3269. try {
  3270. return JSON2.parse(aStr);
  3271. } catch(e) {
  3272. this.Log('failed to parse autoattack: '+aStr);
  3273. this.SetValue('AutoAttack','');
  3274. return null;
  3275. }
  3276. },
  3277. SetAutoAttack:function(s) {
  3278. if(s) {
  3279. //this.Log("Setting Auto Attack: "+JSON2.stringify(s));
  3280. this.SetValue('AutoAttack',JSON2.stringify(s));
  3281. } else {
  3282. this.SetValue('AutoAttack','');
  3283. }
  3284. },
  3285. ResetAutoAttackTarget:function() {
  3286. var autoAttack=this.GetAutoAttack();
  3287. if(autoAttack) {
  3288. autoAttack.x=undefined;
  3289. autoAttack.y=undefined;
  3290. this.SetAutoAttack(autoAttack);
  3291. }
  3292. },
  3293.  
  3294. GetCurrentMapCoord:function() {
  3295. // Check to see if we are on map screen
  3296. var mapbutton = ById('mod_views_map');
  3297. if(mapbutton && mapbutton.className=='sel'){
  3298. // Return xy values from form inputs
  3299. var xcoord=ById('mapXCoor');
  3300. var ycoord=ById('mapYCoor');
  3301. if(xcoord && ycoord){
  3302. return {'x':xcoord.value,'y':ycoord.value};
  3303. }
  3304. }
  3305. // Not on map screen. Return coordinates of current city
  3306. var cities=this.GetSeed().cities;
  3307. for(i=0; i<cities.length; i++){
  3308. if(cities[i][0]==unsafeWindow.currentcityid){
  3309. return {'x':cities[i][2],'y':cities[i][3]};
  3310. break;
  3311. }
  3312. }
  3313. },
  3314.  
  3315. hrsInput:null,
  3316. viewTypeOnly:"",
  3317. expandedInfo:false,
  3318. DrawClosestFarms:function() {
  3319. this.SetAttackStatusMessage();
  3320. var t=this;
  3321.  
  3322. //unsafeWindow.statusupdate();
  3323. var bookmark=ById('maparea_map');
  3324. if(!bookmark) throw("Cannot find bookmark box");
  3325. bookmark=nHtml.FindByXPath(bookmark.parentNode,".//div[@class='coords']");
  3326.  
  3327. var div=ById('ClosestFarms');
  3328. if(!div) {
  3329. div=document.createElement('div');
  3330. var titleA=document.createElement('a');
  3331. titleA.innerHTML='Attacks ';
  3332. titleA.title='Closest attacks, more than ? hrs since last attack';
  3333. titleA.style.cursor='pointer';
  3334. titleA.addEventListener('click',function() {
  3335. div.style.display=div.style.display=='block'?'none':'block';
  3336. setTimeout(function() {
  3337. t.SetValue('ClosestFarmDisplay',div.style.display);
  3338. },0);
  3339. },false);
  3340. var viewTypeOnlyInp=document.createElement('input');
  3341. viewTypeOnlyInp.style.width='10px';
  3342. viewTypeOnlyInp.style.fontSize="8px";
  3343. viewTypeOnlyInp.title="Type of target. ex: P, W, M, P1";
  3344. this.hrsInput=document.createElement('input');
  3345. this.hrsInput.style.width='16px';
  3346. this.hrsInput.value=this.GetMinHours();
  3347. var hrsChanged=function() {
  3348. var v=parseFloat(t.hrsInput.value);
  3349. t.viewTypeOnly=viewTypeOnlyInp.value;
  3350. if(v!=undefined && v!=NaN) {
  3351. t.SetMinHours(t.hrsInput.value);
  3352. t.DrawClosestFarms();
  3353. }
  3354. }
  3355. this.hrsInput.addEventListener('change',function() {
  3356. hrsChanged();
  3357. },false);
  3358. this.hrsInput.addEventListener('keyup',function() {
  3359. hrsChanged();
  3360. },false);
  3361. viewTypeOnlyInp.addEventListener('keyup',function() {
  3362. hrsChanged();
  3363. },false);
  3364. bookmark.appendChild(document.createElement('br'));
  3365. bookmark.appendChild(titleA);
  3366. AddText(bookmark,'>');
  3367. bookmark.appendChild(this.hrsInput);
  3368. AddText(bookmark,'hrs ');
  3369. var expandA=document.createElement('a');
  3370. expandA.innerHTML='E';
  3371. expandA.title='Expand information';
  3372. expandA.addEventListener('click',function() {
  3373. t.expandedInfo=t.expandedInfo?false:true;
  3374. t.DrawClosestFarms();
  3375. },false);
  3376.  
  3377. bookmark.appendChild(viewTypeOnlyInp);
  3378. bookmark.appendChild(expandA);
  3379. bookmark.appendChild(document.createElement('br'));
  3380. }
  3381. div.innerHTML='';
  3382. div.id='ClosestFarms';
  3383. div.style.overflow='scroll';
  3384. div.style.height='200px';
  3385. div.style.display=this.GetValue('ClosestFarmDisplay','block');
  3386.  
  3387. var currentTroops=this.GetArmySize();
  3388. var currentResources=this.GetResourcesSize();
  3389.  
  3390. var mapCoord=this.GetCurrentMapCoord();
  3391. var nowSecs=new Date().getTime()/1000;
  3392. var attacks=this.GetClosestAttacks(mapCoord.x,mapCoord.y);
  3393. //var bestAttack=this.FindBiggestCampAttack(attacks,currentTroops,currentResources);
  3394. var GoClosestFarm=function(e) {
  3395. var xy=e.target.parentNode.parentNode.getAttribute('xy').split(',');
  3396. t.DoUnsafeWindow("setBookmarkCoord("+xy[0]+","+xy[1]+");");
  3397. };
  3398. var AttackClosestFarm=function(e) {
  3399. var xy=e.target.parentNode.parentNode.getAttribute('xy').split(',');
  3400. var attack=t.GetAttack(xy[0],xy[1]);
  3401. if(!attack) throw("Cannot find:"+xy[0]+','+xy[1]);
  3402. if(attack.type==0) {
  3403. t.DoUnsafeWindow("modal_attack(4,"+xy[0]+","+xy[1]+");");
  3404. } else if(attack.type==1) {
  3405. t.DoUnsafeWindow("modal_attack(1,"+xy[0]+","+xy[1]+");");
  3406. }
  3407. };
  3408. var IgnoreFarm=function(e) {
  3409. var xy=e.target.parentNode.parentNode.getAttribute('xy').split(',');
  3410. var attack=t.GetAttack(xy[0],xy[1]);
  3411. if(!attack) throw("Cannot find:"+xy[0]+','+xy[1]);
  3412. attack.ignore=true;
  3413. t.SetAttack(xy[0],xy[1],attack);
  3414. };
  3415. var DeleteFarm=function(e) {
  3416. var xy=e.target.parentNode.parentNode.getAttribute('xy').split(',');
  3417. t.DeleteAttack(xy[0],xy[1]);
  3418. t.DrawClosestFarms();
  3419. };
  3420. var aDone=0;
  3421. var table=document.createElement('table');
  3422. table.className='';
  3423. var minHrsSinceAttack=parseFloat(this.hrsInput.value);
  3424.  
  3425. var viewType=this.viewTypeOnly.trim().toUpperCase();
  3426.  
  3427. for(var aUpto=0; aUpto<attacks.length; aUpto++) {
  3428. var attackI=attacks[aUpto];
  3429. try {
  3430. //attackI.a.levelInfo=this.FindLevelFromMessages(attackI.a);
  3431. //this.SetAttack(attackI.x,attackI.y,attackI.a);
  3432. if(!attackI.a.time) {
  3433. lastAttack=60*60*24*31;
  3434. } else {
  3435. lastAttack=nowSecs-parseInt(attackI.a.time);
  3436. }
  3437. if(lastAttack<(60*60*minHrsSinceAttack)) continue;
  3438.  
  3439. var levelI=this.GetLevelInfo(attackI.a);
  3440. var m=( (levelI!=null && levelI.type) ?(levelI.type.charAt(0)+levelI.level):'');
  3441. //this.Log("Location Type: "+m);
  3442. if(this.viewTypeOnly!="") {
  3443. if(this.viewTypeOnly==" ") {
  3444. if(m!="") {
  3445. continue;
  3446. }
  3447. } else if(viewType.length==0 || m.substring(0,viewType.length)!=viewType) {
  3448. continue;
  3449. }
  3450. }
  3451.  
  3452. var dist=this.CalcXYDist({'x':attackI.x,'y':attackI.y},mapCoord);
  3453. if(dist>=this.options.attackMaxDistance) {
  3454. break;
  3455. }
  3456. var tr=table.insertRow(-1);
  3457. tr.setAttribute('xy',attackI.x+','+attackI.y);
  3458. var td=tr.insertCell(-1);
  3459. td.style.whiteSpace='nowrap';
  3460.  
  3461. var a=document.createElement('a');
  3462. a.style.fontSize='10px';
  3463. a.innerHTML=attackI.x+','+attackI.y;
  3464. a.addEventListener('click',function(e) { GoClosestFarm(e); },false);
  3465. td.appendChild(a);
  3466.  
  3467. AddText(td,' ');
  3468. //td=tr.insertCell(-1);
  3469.  
  3470. var attackA=document.createElement('a');
  3471. attackA.style.fontSize='10px';
  3472. /* ~~~ disabled: incorrect numbers due to having to wait for attack to update.
  3473. if(bestAttack && attackI.x==bestAttack.x && attackI.y==bestAttack.y) {
  3474. attackA.style.color='#f88';
  3475. }
  3476. */
  3477. attackA.title=(levelI!=null?(levelI.type+' '+levelI.level):'');
  3478. if(attackI.a.comment) {
  3479. attackA.title+=", "+attackI.a.comment;
  3480. }
  3481. if(attackI.a.time && !isNaN(lastAttack)) {
  3482. // if we only scouted or transported to someone they won't have a last attack time.
  3483. m=m+' @'+SecsToStr(lastAttack);
  3484. }
  3485. attackA.innerHTML=m;
  3486. attackA.addEventListener('click',function(e) { AttackClosestFarm(e); },false);
  3487. td.appendChild(attackA);
  3488.  
  3489. if(t.expandedInfo) {
  3490. var troops=attackI.a.troops;
  3491. if(troops) {
  3492. for(var tupto=0; tupto<troops.length; tupto++) {
  3493. var num=troops[tupto];
  3494. if(attackI.a.suicidewave) {
  3495. var am=attackI.a.suicidewave[tupto];
  3496. if(am) num+=" ("+am+")";
  3497. }
  3498. AddText(tr.insertCell(-1),num);
  3499. }
  3500. }
  3501. }
  3502. var aDelete=document.createElement('a');
  3503. aDelete.innerHTML='X';
  3504. aDelete.title='Delete';
  3505. aDelete.addEventListener('click',function(e) { DeleteFarm(e); },false);
  3506. tr.insertCell(-1).appendChild(aDelete);
  3507. aDone++;
  3508. } catch(e) {
  3509. this.Log('Error:'+e);
  3510. }
  3511.  
  3512. }
  3513.  
  3514. div.appendChild(table);
  3515. //bookmark.parentNode.insertBefore(div,bookmark);
  3516. //bookmark.parentNode.appendChild(document.createElement('br'));
  3517. bookmark.appendChild(div);
  3518.  
  3519. this.AttachXYPaste('mapXCoor','mapYCoor');
  3520. },
  3521.  
  3522.  
  3523. // ?,1,square type, level, player id?,
  3524. // target player name, target gender, player name, player gender, ?, target x, target y, report id, 0, x y
  3525. onclickReportRe:/(["0-9]+),(["0-9]+),(["0-9]+),(["0-9]+),(["0-9]+),("[^"]+"),("[^"]+"),("[^"]+"),("[^"]+"),(["0-9]+),(["0-9]+),(["0-9]+),/,
  3526. //modal_messages_viewreports_view("897422",0,51,9,2485358,"niknah","M","niknah","M",1,333,110,1275178036,1,286,181);
  3527.  
  3528. // remove the read/unread flag
  3529. onclickReadRe:/^(.*,)([0-9]+)(,[0-9]+,[0-9]+[^,]*)$/,
  3530. FixOnClick:function(a) {
  3531. var m=this.onclickReadRe.exec(a);
  3532. if(m) {
  3533. return m[1]+"0"+m[3];
  3534. }
  3535. return a;
  3536. },
  3537.  
  3538.  
  3539.  
  3540. IterateArmy:function(f) {
  3541. if(!this.GetSeed()) return;
  3542. var armyDiv=ById('cityinfo_3');
  3543. var units=this.GetSeed().units["city"+unsafeWindow.currentcityid];
  3544. //var unitKeys=Object.keys(units);
  3545. //for(var u=0; u<unitKeys; u++) {
  3546. var uRe=/([0-9]+)$/;
  3547. for(var u in units) {
  3548. var m=uRe.exec(u);
  3549. if(!m) continue;
  3550. f.call(this,m[1],units[u]);
  3551. }
  3552. /*
  3553. var ss=document.evaluate(".//div[@class='unit']",armyDiv,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
  3554. for(var s=0; s<ss.snapshotLength; s++) {
  3555. var unit=ss.snapshotItem(s);
  3556. var amt=unit.textContent;
  3557. f.call(s,amt);
  3558. }
  3559. */
  3560. },
  3561.  
  3562. GetArmySize:function() {
  3563. var troops=[];
  3564. this.IterateArmy(function(s,amt) {
  3565. troops[s]=amt;
  3566. });
  3567. return troops;
  3568. },
  3569.  
  3570. GetResourcesSize:function() {
  3571. var resources=[];
  3572. resources[0]=parseInt(ById('stat_gold_bar_num').innerHTML.replace(/,/g,'')); // Gold
  3573. resources[1]=parseInt(ById('stat_rec1_bar_num').innerHTML.replace(/,/g,'')); // Food
  3574. resources[2]=parseInt(ById('stat_rec2_bar_num').innerHTML.replace(/,/g,'')); // Wood
  3575. resources[3]=parseInt(ById('stat_rec3_bar_num').innerHTML.replace(/,/g,'')); // Stone
  3576. resources[4]=parseInt(ById('stat_rec4_bar_num').innerHTML.replace(/,/g,'')); // Ore
  3577. return resources;
  3578. },
  3579.  
  3580. OpenViewReports:function() {
  3581. this.Log('Open View Reports');
  3582. this.DoUnsafeWindow("modal_messages();");
  3583. this.DoUnsafeWindow('track_chrome_btn("messages_btn");');
  3584. this.DoUnsafeWindow('modal_messages_viewreports();');
  3585. },
  3586.  
  3587. //autoAttackCitiesDoneMax:3,
  3588. autoAttackCitiesDone:0,
  3589. autoAttackCityUpto:1,
  3590. autoAttackModalWaiting:false,
  3591. autoAttackTimeout:null,
  3592. autoAttacksThisCity:0,
  3593. ClearAutoAttackTimeout:function() {
  3594. if(this.autoAttackTimeout!=null) {
  3595. this.Log('reload page timer killed');
  3596. window.clearTimeout(this.autoAttackTimeout);
  3597. this.autoAttackTimeout=null;
  3598. }
  3599. },
  3600. RestartAutoAttack:function() {
  3601. this.autoAttacksThisCity=0;
  3602. this.autoAttackCitiesDone=0;
  3603. this.autoAttackCityUpto=1;
  3604. this.autoAttackModalWaiting=false;
  3605. this.NextAutoAttack();
  3606. },
  3607.  
  3608. StartReloadPageTimer:function(secs) {
  3609. var t=this;
  3610. if(!secs) secs=this.options.waitAfterCitiesDone;
  3611. var refreshMSecs=t.GetRandTime(1000*secs);
  3612. this.Log('refreshing in '+(refreshMSecs/1000)+' secs, all cities done:'+this.autoAttackCityUpto);
  3613. this.ClearAutoAttackTimeout();
  3614. this.autoAttackTimeout=window.setTimeout(function() {
  3615. if(t.autoAttackTimeout==null) return;
  3616. t.autoAttackTimeout=null;
  3617. if(t.IsMapperRunning() || t.IsCurrentlySendingMultipleWaves()) {
  3618. if(t.IsMapperRunning()){
  3619. t.Log("Waiting for mapping to finish");
  3620. }else{
  3621. t.Log("Waiting for multiple wave attack to finish");
  3622. }
  3623. // don't reload until the mapper or multi-wave attack has finished.
  3624. window.setTimeout(function() {
  3625. t.StartReloadPageTimer();
  3626. },0);
  3627. return;
  3628. }
  3629. t.SetValuesCache();
  3630. //window.location.reload(true);
  3631. t.ReloadWindow();
  3632. },refreshMSecs);
  3633. this.Log('reload page timer started');
  3634. },
  3635. multipleWaveTimeout:null,
  3636. ClearMultipleWaveTimeout:function() {
  3637. if(this.multipleWaveTimeout!=null) {
  3638. this.Log('city switching timer killed');
  3639. window.clearTimeout(this.multipleWaveTimeout);
  3640. this.multipleWaveTimeout=null;
  3641. }
  3642. },
  3643. StartMultipleWaveTimer:function(secs) {
  3644. var t=this;
  3645. if(!secs) secs=t.options.attackDelay;
  3646. var attackDelayMSecs=t.GetRandTime(1000*secs);
  3647. this.Log('Waiting '+(attackDelayMSecs/1000)+' secs to retry second wave attack...');
  3648. this.ClearMultipleWaveTimeout();
  3649. this.multipleWaveTimeout=window.setTimeout(function() {
  3650. if(t.multipleWaveTimeout==null) return;
  3651. t.multipleWaveTimeout=null;
  3652. if(t.IsCurrentlySendingMultipleWaves()) {
  3653. t.Log("Waiting for multiple wave attack to finish...");
  3654. // don't switch cities until the multi-wave attack has finished.
  3655. window.setTimeout(function() {
  3656. t.StartMultipleWaveTimer();
  3657. },0);
  3658. return;
  3659. }
  3660. t.NextAutoAttackCity();
  3661. },attackDelayMSecs);
  3662. this.Log('Multiple wave attack timer started');
  3663. },
  3664.  
  3665. lastOpenViewReports:0,
  3666. CheckReports:function() {
  3667. var t=this;
  3668. var autoAttack=this.GetAutoAttack();
  3669. if(!autoAttack) return;
  3670. // Load the reports every minute or on initial page load
  3671. if(!this.options.noViewReports) {
  3672. var nowSecs=new Date().getTime()/1000;
  3673. if((this.lastOpenViewReports+(60*1))<nowSecs) {
  3674. this.lastOpenViewReports=nowSecs;
  3675. this.OpenViewReports();
  3676. this.bringUpReports=true;
  3677. if(this.options.autoRemoveReports || this.options.autoRemoveFarmReports) {
  3678. this.autoAttackRemoveReports=true;
  3679. }
  3680. }
  3681. }
  3682. },
  3683.  
  3684. ClickChangeCity:function(cityA,tries) {
  3685. var t=this;
  3686. nHtml.Click(cityA);
  3687. // If this is the only city selected in the options, we just pretend to switch
  3688. var currentCityNum = this.autoAttackCityUpto;
  3689. var enabledCities = 0;
  3690. for(var i=1; i<=8; i++){
  3691. if(this.options.okCities[i]){
  3692. enabledCities++;
  3693. }
  3694. }
  3695. //t.Log("Number of enabled cities to attack from: "+enabledCities);
  3696. if(enabledCities==1){ t.prevCurrentCity = -1; }
  3697. // Determine the number of the city and store it
  3698. t.SetCurrentAttackCityNum(cityA.id.replace("citysel_",""));
  3699. t.nextAutoAttackWanted=window.setTimeout(function() {
  3700. if(t.nextAutoAttackWanted!=null) {
  3701. if(tries>4) {
  3702. t.Log("Skip city, too many retries");
  3703. t.NextAutoAttackCity();
  3704. return;
  3705. }
  3706. t.Log("We clicked change city but the city did not change, trying again");
  3707. // Didn't change city
  3708. t.ClickChangeCity(cityA,tries+1);
  3709. }
  3710. },10000);
  3711. },
  3712.  
  3713.  
  3714. NextAutoAttackCity:function() {
  3715. var t=this;
  3716. var autoAttack=this.GetAutoAttack();
  3717. if(!autoAttack) return;
  3718. if(this.IsCurrentlySendingMultipleWaves()){
  3719. this.Log('Cannot change city. Waiting for multiple wave attack to finish...');
  3720. t.ClearMultipleWaveTimeout();
  3721. t.StartMultipleWaveTimer();
  3722. return;
  3723. }else{
  3724. t.ClearMultipleWaveTimeout();
  3725. }
  3726. // change to next city
  3727. this.autoAttacksThisCity=0;
  3728.  
  3729. var cityA=null;
  3730.  
  3731. // this.autoAttackCityUpto++;
  3732. // cityA=ById('citysel_'+this.autoAttackCityUpto);
  3733. // //~~~ problem here when under attack, the city isn't marked as selected?
  3734. // // Skip to next city along the line if the current city is already selected somehow
  3735. // if(cityA && cityA.className && cityA.className.indexOf('city_selected')>=0) {
  3736. // this.Log('Skip city, current city:'+this.autoAttackCityUpto);
  3737. // this.autoAttackCityUpto++;
  3738. // }
  3739.  
  3740. // // Determine the next enabled city in the options
  3741. // var firstAvailableCityNum = this.autoAttackCityUpto;
  3742. // while(firstAvailableCityNum<=8){
  3743. // if(this.options.okCities[firstAvailableCityNum]){
  3744. // break;
  3745. // }else{
  3746. // firstAvailableCityNum++;
  3747. // }
  3748. // }
  3749. // // Default to city #1 if no cities are enabled
  3750. // if(!this.options.okCities[firstAvailableCityNum]){
  3751. // firstAvailableCityNum = 1;
  3752. // }
  3753. // // Check to make sure that the next city is selected in the options
  3754. // //this.Log("Currently attempting to switch to city: "+this.autoAttackCityUpto);
  3755. // var currentCityNum = this.autoAttackCityUpto;
  3756. // while(currentCityNum<=8){
  3757. // //this.Log("Is City "+currentCityNum+" Selected in options: "+this.options.okCities[currentCityNum]);
  3758. // if(!this.options.okCities[currentCityNum]){
  3759. // currentCityNum++;
  3760. // }else{
  3761. // if(currentCityNum>this.autoAttackCityUpto){
  3762. // this.Log("City "+this.autoAttackCityUpto+" not enabled in options.");
  3763. // this.autoAttackCityUpto = currentCityNum;
  3764. // }
  3765. // //this.Log("Attempting to switch to city: "+this.autoAttackCityUpto);
  3766. // break;
  3767. // }
  3768. // // No cities were available. Switching to first available city
  3769. // this.autoAttackCityUpto = firstAvailableCityNum;
  3770. // }
  3771.  
  3772. while(true) {
  3773. this.autoAttackCityUpto++;
  3774. cityA=ById('citysel_'+this.autoAttackCityUpto);
  3775. //~~~ problem here when under attack, the city isn't marked as selected?
  3776. if((cityA && cityA.className && cityA.className.indexOf('city_selected')>=0) || (!this.options.okCities[this.autoAttackCityUpto])) {
  3777. this.Log('Skip city, current city or city not selected: '+this.autoAttackCityUpto);
  3778. } else {
  3779. this.Log('Attempting to select this city: '+this.autoAttackCityUpto);
  3780. cityA=ById('citysel_'+this.autoAttackCityUpto);
  3781. break;
  3782. }
  3783. }
  3784. cityA=ById('citysel_'+this.autoAttackCityUpto);
  3785. if(!cityA) {
  3786. // go back to the 1st available city
  3787. this.Log('Start from 1st city again');
  3788. if(this.autoAttackCityUpto<=2) {
  3789. // only one city.
  3790. } else {
  3791. this.autoAttackCityUpto=1;
  3792. cityA=ById('citysel_'+this.autoAttackCityUpto);
  3793. }
  3794. this.autoAttackCitiesDone++;
  3795. }
  3796.  
  3797. if(!cityA || this.autoAttackCitiesDone>=this.options.autoAttackCitiesDoneMax) {
  3798. //Reset to first city if auto attack does the refresh
  3799. this.SetCurrentAttackCityNum(1);
  3800. // ran out of cities, let's refresh in a minute
  3801. this.StartReloadPageTimer();
  3802. return;
  3803. } else {
  3804. if(this.nextAutoAttackTimeout==null) {
  3805. var secs=t.GetRandTime(1000*t.options.changeCitySecs);
  3806. this.Log('Changing city to: '+this.autoAttackCityUpto+', in '+(secs/1000)+'secs, loop: '+this.autoAttackCitiesDone);
  3807. this.nextAutoAttackTimeout=setTimeout(function() {
  3808. t.nextAutoAttackTimeout=null;
  3809. t.SetValuesCache();
  3810. t.ClickChangeCity(cityA,0);
  3811. },secs);
  3812. } else {
  3813. this.Log('Cannot change city. Reason: about to attack or change city');
  3814. }
  3815. // this.autoAttackCityUpto++;
  3816. }
  3817. },
  3818.  
  3819.  
  3820. StopWaitForAttackBoxAppear:function() {
  3821. if(this.waitForAttackBoxAppear!=null) {
  3822. window.clearTimeout(this.waitForAttackBoxAppear);
  3823. this.waitForAttackBoxAppear=null;
  3824. }
  3825. },
  3826.  
  3827. OpenAttackDialog:function(bestAttack) {
  3828. var t=this;
  3829. t.StopWaitForAttackBoxAppear();
  3830. t.waitForAttackBoxAppear=window.setTimeout(function() {
  3831. if(t.waitForAttackBoxAppear==null) return;
  3832. t.waitForAttackBoxAppear=null;
  3833. t.DoUnsafeWindow('Modal.hideModalAll();');
  3834. t.DoUnsafeWindow('Modal.hideModalAll();');
  3835. try {
  3836. // something in the script is triggering a bug in
  3837. t.DoUnsafeWindow('Modal.hideCurtain();');
  3838. t.DoUnsafeWindow('Modal.hideWindow();');
  3839. } catch(e) {
  3840. // ignore
  3841. }
  3842. //window.location.reload(true);
  3843. t.ResetIdStatus();
  3844. t.Log("Attack box has not appeared, let's reopen");
  3845. window.setTimeout(function() {
  3846. t.OpenAttackDialog(bestAttack);
  3847. },0);
  3848. },5*1000);
  3849. //~~~ strange things here, sometimes the attack dialog is on screen but modalid is not updated
  3850. if(ById('modal_attack')) {
  3851. try {
  3852. var countOut=10;
  3853. while(countOut-->=0) {
  3854. t.Log('modal attck still up'+unsafeWindow.Modal.modalid);
  3855. var maxi=0;
  3856. for(var i=0; i<20; i++) {
  3857. if(ById('modalBox'+i)) {
  3858. maxi=i;
  3859. }
  3860. }
  3861. t.Log('Closing: '+maxi);
  3862. unsafeWindow.Modal.modalid=maxi;
  3863. if(maxi>0) {
  3864. unsafeWindow.Modal.hideCurtain();
  3865. unsafeWindow.Modal.hideWindow();
  3866. } else {
  3867. break;
  3868. }
  3869. }
  3870. }catch(e) {
  3871. t.Log("Mmm..."+e);
  3872. }
  3873. } else {
  3874. //t.Log('hide all: '+unsafeWindow.Modal.modalid);
  3875. unsafeWindow.Modal.hideModalAll();
  3876. }
  3877. if (bestAttack.type==0) {
  3878. unsafeWindow.modal_attack(4,bestAttack.x,bestAttack.y);
  3879. // Toggle attack waves between suicide and normal mode
  3880. this.ToggleCurrenttAttackWaveType(bestAttack.x,bestAttack.y);
  3881. // Update the last attack sent time
  3882. this.UpdateAttackLastSentTime();
  3883. } else if (bestAttack.type==1) {
  3884. unsafeWindow.modal_attack(1,bestAttack.x,bestAttack.y);
  3885. }
  3886. },
  3887.  
  3888. nextAutoAttackWanted:null,
  3889. NextAutoAttack:function() {
  3890. this.Log("Next auto attack");
  3891. if(this.nextAutoAttackWanted!=null) {
  3892. window.clearTimeout(this.nextAutoAttackWanted);
  3893. this.nextAutoAttackWanted=null;
  3894. }
  3895.  
  3896. var autoAttack=this.GetAutoAttack();
  3897.  
  3898. if(!this.options.okCities[this.autoAttackCityUpto]) {
  3899. this.Log('Skip city. Not enabled in options. City: '+this.autoAttackCityUpto);
  3900. this.NextAutoAttackCity();
  3901. return;
  3902. }
  3903. if(!autoAttack || (autoAttack.x!=undefined && autoAttack.x!=-1)) return;
  3904. if(this.IsMapperRunning()) {
  3905. this.StartReloadPageTimer();
  3906. return;
  3907. }
  3908. this.DetermineCurrentRallyPointLevel();
  3909. this.DetermineCurrentMarchesNum();
  3910. this.available_marches_num = this.currentRallyPointLevel - this.currentMarchesNum - this.options.rallyKeep;
  3911. var currentTroops=this.GetArmySize();
  3912. var currentResources=this.GetResourcesSize();
  3913. var mapCoord=this.GetCurrentMapCoord();
  3914. var attacks=this.GetClosestAttacks(mapCoord.x,mapCoord.y);
  3915. //this.Log("Current attacks in system: "+inspect(attacks,10));
  3916. var bestAttack=this.FindBiggestCampAttack(attacks,currentTroops,currentResources);
  3917. if(bestAttack && this.available_marches_num>0) {
  3918. // attack closest biggest barbarian/wilderness
  3919. autoAttack.x=bestAttack.x;
  3920. autoAttack.y=bestAttack.y;
  3921. this.SetAutoAttack(autoAttack);
  3922. this.autoAttackModalWaiting=true;
  3923.  
  3924. var t=this;
  3925. // *** we need to wait until the current attack box is off first.
  3926. var waitedCount=0;
  3927. var startAttack=function() {
  3928. waitedCount++;
  3929. //t.Log('waiting'+waitedCount);
  3930. if(waitedCount>20) {
  3931. t.Log('Force close the attack dialog');
  3932. t.DoUnsafeWindow('Modal.hideModalAll();');
  3933. }
  3934. var attackBox=document.getElementById('modal_attack');
  3935. if(!attackBox) {
  3936. t.OpenAttackDialog(bestAttack);
  3937. /*
  3938. attackBox=document.getElementById('modal_attack');
  3939. if(attackBox) {
  3940. //*** for some reason it doesn't trigger DOMInserted sometimes for the "modal_attack" div
  3941. if(t.waitForAttackBoxAppear) {
  3942. t.OnAttackBoxAppear(attackBox);
  3943. }
  3944. }
  3945. */
  3946. return;
  3947. }
  3948. window.setTimeout(function() {
  3949. startAttack();
  3950. },1000);
  3951. }
  3952. startAttack();
  3953. } else {
  3954. autoAttack.x=autoAttack.y=-1;
  3955. this.SetAutoAttack(autoAttack);
  3956. // no valid attacks for this city.
  3957. this.Log("No valid targets, need to attack more targets or wait for troops to return.");
  3958. this.NextAutoAttackCity();
  3959. }
  3960. },
  3961.  
  3962. /////////////////////////
  3963.  
  3964. RemoveEmptyReportsDivs:function() {
  3965. var ss=document.evaluate("./div[@id='modal_msg_reports_tablediv']",document.body,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
  3966. for(var s=0; s<ss.snapshotLength; s++) {
  3967. var div=ss.snapshotItem(s);
  3968. if(div.innerHTML=="") {
  3969. div.parentNode.removeChild(div);
  3970. }
  3971. }
  3972. },
  3973.  
  3974.  
  3975. IterateAllianceReports:function(f) {
  3976. return this.IterateReports('modal_alliance_reports_tablediv',0,f);
  3977. },
  3978. IterateMsgReports:function(f) {
  3979. return this.IterateReports('modal_msg_reports_tablediv',1,f);
  3980. },
  3981.  
  3982. IterateReports:function(id,colStart,f) {
  3983. this.RemoveEmptyReportsDivs();
  3984. var msgs=ById(id);
  3985. if(!msgs) return;
  3986. var trs=msgs.getElementsByTagName('tr');
  3987. for(var tUpto=0; tUpto<trs.length; tUpto++) {
  3988. var tr=trs[tUpto];
  3989. var a=nHtml.FindByXPath(tr,".//a[contains(@onclick,'modal_messages_viewreports') or contains(@onclick,'modal_alliance_report_view') or contains(@onclick,'viewMarchReport')]");
  3990. if(!a) continue;
  3991. if(tr.cells.length<(colStart+2)) continue;
  3992. var descCol=tr.cells[colStart+1];
  3993. var dateCol=tr.cells[colStart+0];
  3994. var desc=descCol.textContent;
  3995. var m=this.coordsRe.exec(desc);
  3996. var x=null,y=null;
  3997. if(m) {
  3998. x=m[1]; y=m[2];
  3999. }
  4000. var onclick=a.getAttribute('onclick');
  4001. if(onclick) {
  4002. var m=this.onclickReportRe.exec(onclick);
  4003. if(m) { x=m[11]; y=m[12]; }
  4004. }
  4005. if(!f.call(this,a,tr,desc,x,y)) break;
  4006. }
  4007. },
  4008.  
  4009.  
  4010.  
  4011. recordingReports:false,
  4012. replaceReturnRe:/return[^{}]*$/,
  4013. RecordReports:function() {
  4014. try {
  4015. if(this.recordingReports) return;
  4016. this.recordingReports=true;
  4017. this.IterateMsgReports(function(a,tr,desc,x,y) {
  4018. if(x==null || y==null) return true;
  4019. var onclick=a.getAttribute('onclick').trim();
  4020. if(this.IsOnclickMyselfToMyself(onclick)) {
  4021. return true;
  4022. }
  4023. var attack=this.GetAttack(x,y);
  4024. var saveReportAsAttack = true;
  4025. if(!attack) {
  4026. // Don't record reports as attacks if the attack doesn't already exist in the system
  4027. var saveReportAsAttack = false;
  4028. }
  4029. if(!attack) { attack={}; }
  4030. if(!attack.messages) attack.messages=[];
  4031. var onclickWithoutReturn=onclick.replace(this.replaceReturnRe,'');
  4032. a.href='javascript:'+onclickWithoutReturn;
  4033. onclick=this.FixOnClick(onclick);
  4034. var addedAlready=false;
  4035. for(var m=0; m<attack.messages.length; m++) {
  4036. if(attack.messages[m][1]==onclick) {
  4037. addedAlready=true;
  4038. break;
  4039. }
  4040. }
  4041. var changed=false;
  4042. if(!addedAlready) {
  4043. attack.messages.push([desc,onclick]);
  4044. //this.Log("attack messages: "+attack.messages);
  4045. var li=this.GetLevelInfo(attack);
  4046. //this.Log('type:'+li.type+',level:'+li.level);
  4047. if(li) attack.levelInfo=li;
  4048. changed=true;
  4049. }
  4050. if(!attack.levelInfo) {
  4051. // to fix up old scripts where this didn't work.
  4052. attack.levelInfo=this.GetLevelInfo(attack);
  4053. if(attack.levelInfo) changed=true;
  4054. }
  4055. if(changed && saveReportAsAttack) {
  4056. this.SetAttack(x,y,attack);
  4057. }
  4058. return true;
  4059. });
  4060. } finally {
  4061. this.recordingReports=false;
  4062. }
  4063. },
  4064.  
  4065. IsOnclickMyselfToMyself:function(onclick) {
  4066. if(!onclick) return false;
  4067. var m=this.onclickReportRe.exec(onclick);
  4068. if(m && m[6]==m[8] && m[7]==m[9]) {
  4069. return true;
  4070. }
  4071. return false;
  4072. },
  4073. DeleteWildBarbAttacks:function() {
  4074. var deletes=0;
  4075. this.IterateMsgReports(function(a,tr,desc,x,y) {
  4076. var onclick=a.getAttribute('onclick');
  4077. if(!onclick) return false;
  4078. onclick=onclick.trim();
  4079. var m=this.onclickReportRe.exec(onclick);
  4080. if(this.IsOnclickMyselfToMyself(onclick)) {
  4081. // message to myself
  4082. } else if(m && m[5]!='0') {
  4083. return true;
  4084. }
  4085. var inps=tr.getElementsByTagName('input');
  4086. if(inps.length>=1) {
  4087. inps[0].checked=true;
  4088. }
  4089. deletes++;
  4090. return true;
  4091. });
  4092. if(deletes>0) {
  4093. this.DoUnsafeWindow('modal_messages_reports_chkdel();');
  4094. }
  4095. return deletes;
  4096. },
  4097. DeleteFarmAttacks:function() {
  4098. var deletes=0;
  4099. this.IterateMsgReports(function(a,tr,desc,x,y) {
  4100. var DisplayName = this.GetDisplayName();
  4101. DisplayName = /([^"]+) ([^"]+)/.exec(DisplayName);
  4102. var onclick=a.getAttribute('onclick');
  4103. if(!onclick) return false;
  4104. onclick=onclick.trim();
  4105. var m=this.onclickReportRe.exec(onclick);
  4106. if(this.IsOnclickMyselfToMyself(onclick)) {
  4107. return true; //Don't select transports
  4108. } else if(m && m[5]=='0') {
  4109. return true; //Don't select barbs or wilds
  4110. } else if(m && m[11]=='0' && m[12]=='0') {
  4111. return true; //Don't select if empty
  4112. } else if(m && m[8].StripQuotes()!=DisplayName[2]) {
  4113. return true; //Don't select if attacker is not yourself
  4114. }
  4115. var attack = this.GetAttack(m[11],m[12]); //Check if attack exists in system
  4116. if(!attack) return true;
  4117. if(attack.deletefarmno) return true; //Don't select if checked not to delete
  4118. if(!attack.troops) return true; //Sometimes the script will record reports but u don't want them deleted
  4119. var inps=tr.getElementsByTagName('input');
  4120. if(inps.length>=1) {
  4121. inps[0].checked=true;
  4122. }
  4123. deletes++;
  4124. return true;
  4125. });
  4126. if(deletes>0) {
  4127. this.DoUnsafeWindow('modal_messages_reports_chkdel();');
  4128. }
  4129. return deletes;
  4130. },
  4131.  
  4132. bringUpReports:false,
  4133. AddCheckBarbarians:function() {
  4134. //var msgBody=ById('modal_msg_reports');
  4135. var msgBody=ById('modal_msg_reports_tablediv');
  4136. if(!msgBody) return;
  4137. var t=this;
  4138. var closeReports=true;
  4139. if(this.autoAttackRemoveReports) {
  4140. var reportsRemoved=0;
  4141. if(this.options.autoRemoveReports){
  4142. reportsRemoved+=this.DeleteWildBarbAttacks();
  4143. }
  4144. if(this.options.autoRemoveFarmReports){
  4145. reportsRemoved+=this.DeleteFarmAttacks();
  4146. }
  4147. if(reportsRemoved==0) {
  4148. this.autoAttackRemoveReports=false;
  4149. } else {
  4150. closeReports=false;
  4151. }
  4152. }
  4153. if(this.bringUpReports && closeReports) {
  4154. window.setTimeout(function() {
  4155. t.DoUnsafeWindow('Modal.hideModalAll();');
  4156. },t.GetRandTime(3000));
  4157. this.bringUpReports=false;
  4158. }
  4159. this.ClearMessages();
  4160. var a=document.createElement('a');
  4161. var t=this;
  4162. a.addEventListener('click',function() {
  4163. t.DeleteWildBarbAttacks();
  4164. },false);
  4165. a.className='buttonDown20';
  4166. //a.style.paddingLeft='30px';
  4167. a.innerHTML='<span>Delete Wild/Barb/Transp</span>';
  4168. if(msgBody.nextSibling) {
  4169. msgBody.nextSibling.insertBefore(a,msgBody.nextSibling.childNodes[0]);
  4170. //msgBody.nextSibling.appendChild(a);
  4171. } else {
  4172. msgBody.appendChild(a);
  4173. }
  4174. var a=document.createElement('a');
  4175. var t=this;
  4176. a.addEventListener('click',function() {
  4177. t.DeleteFarmAttacks();
  4178. },false);
  4179. a.className='buttonDown20';
  4180. //a.style.paddingLeft='30px';
  4181. a.innerHTML='<span>Delete Farm</span>';
  4182. if(msgBody.nextSibling) {
  4183. msgBody.nextSibling.insertBefore(a,msgBody.nextSibling.childNodes[0]);
  4184. //msgBody.nextSibling.appendChild(a);
  4185. } else {
  4186. msgBody.appendChild(a);
  4187. }
  4188. },
  4189.  
  4190. HighlightAllianceReports:function() {
  4191. var mapCoord=this.GetCurrentMapCoord();
  4192. var cities=this.GetSeed().cities;
  4193. this.IterateAllianceReports(function(a,tr,desc,x,y) {
  4194. if(x==null || y==null) return true;
  4195. var closestDist=999999;
  4196. var closestLoc=null;
  4197. for(var c=0; c<cities.length; c++) {
  4198. var city=cities[c];
  4199. var cityLoc={'x':city[2],'y':city[3]};
  4200. var dist=this.CalcXYDist({'x':x,'y':y},cityLoc);
  4201. if(dist<closestDist) { closestDist=dist; closestLoc=cityLoc; }
  4202. }
  4203. var onclick=a.getAttribute('onclick');
  4204. var m=this.onclickReportRe.exec(onclick);
  4205. if(m && m[5]=='0') {
  4206. tr.cells[1].style.color='#888';
  4207. }
  4208. if(closestLoc!=null) {
  4209. var td=tr.insertCell(-1);
  4210. td.style.textAlign='right';
  4211. var loctd=tr.insertCell(-1);
  4212. AddText(loctd,closestLoc.x+','+closestLoc.y);
  4213. AddText(td,Math.floor(closestDist) );
  4214. }
  4215. return true;
  4216. });
  4217. },
  4218.  
  4219.  
  4220.  
  4221. IterateAttacks:function(f) {
  4222. if(this.isChrome) {
  4223. return;
  4224. }
  4225. var names=this.browser_listValues();
  4226. var attackPrefix='attack_'+this.GetServerId()+'_';
  4227. for(var n=0; n<names.length; n++) {
  4228. var name=names[n];
  4229. if(name.substring(0,attackPrefix.length)!=attackPrefix) continue;
  4230. f(name,this.browser_getValue(name));
  4231. }
  4232. },
  4233.  
  4234. prevClearMessages:0,
  4235. ClearMessages:function() {
  4236. var nowSecs=new Date().getTime()/1000;
  4237. if((this.prevClearMessages+(10*60)) > nowSecs) {
  4238. return;
  4239. }
  4240. this.prevClearMessages=nowSecs;
  4241. var keepReports=this.isChrome?this.options.chromeKeepReports:this.options.keepReports;
  4242. this.Log('Clear old messages, keeping '+keepReports);
  4243. if(keepReports<=0) {
  4244. // must keep at least 1 report to get level information.
  4245. keepReports=1;
  4246. }
  4247. var t=this;
  4248. this.IterateAttacks(function(name,value) {
  4249. var attack=JSON2.parse(value);
  4250. if(attack.messages && attack.messages.length>keepReports) {
  4251. attack.messages.splice(0,attack.messages.length-keepReports+1);
  4252. }
  4253. t.browser_setValue(name,JSON2.stringify(attack));
  4254. });
  4255. },
  4256.  
  4257.  
  4258. SetupClearMessages:function() {
  4259. var t=this;
  4260. var cm=document.createElement('input');
  4261. cm.type='button';
  4262. cm.id='ClearMessages';
  4263. cm.style.display='none';
  4264. document.body.appendChild(cm);
  4265. cm.addEventListener('click',function(e) {
  4266. setTimeout(function() {
  4267. t.ClearMessages();
  4268. },0);
  4269. },false);
  4270. },
  4271.  
  4272. trainTroopsOnclick:/\(([0-9]+)\)/,
  4273. AddTrainTroopsLink:function() {
  4274. var startObj=ById('unit_btns_start');
  4275. if(!startObj) return;
  4276. var onclick=startObj.getAttribute('onclick');
  4277. var m=this.trainTroopsOnclick.exec(onclick);
  4278. if(!m) {
  4279. return;
  4280. }
  4281. var t=this;
  4282. var type=m[1];
  4283.  
  4284. var pnode=startObj.parentNode;
  4285. var a=document.createElement('a');
  4286. a.className='button25';
  4287. var setTrainTroopsA=function() {
  4288. var trainTroops=JSON2.parse(t.GetValue('TrainTroops','{}'));
  4289. a.innerHTML='<span>'+(trainTroops[t.GetCurrentCityId()]==type?'Auto Train - On':'Auto Train - Off')+'</span>';
  4290. }
  4291. a.addEventListener('click',function() {
  4292. var trainTroops=JSON2.parse(t.GetValue('TrainTroops','{}'));
  4293. trainTroops[t.GetCurrentCityId()]=trainTroops[t.GetCurrentCityId()]==type?undefined:type;
  4294. t.SetValue('TrainTroops',JSON2.stringify(trainTroops));
  4295. setTrainTroopsA();
  4296. },false);
  4297. setTrainTroopsA();
  4298.  
  4299. //pnode.appendChild(document.createElement('br'));
  4300. AddText(pnode,' ');
  4301. pnode.appendChild(a);
  4302. },
  4303.  
  4304. GetCurrentCityId:function() {
  4305. if(!unsafeWindow.currentcityid) return null;
  4306. return unsafeWindow.currentcityid;
  4307. },
  4308. GetCurrentAttackCityNum:function() {
  4309. var curCityNum=this.GetValue('CurrentAttackCityNum',null);
  4310. if(!curCityNum || !is_int(curCityNum) || curCityNum>8){
  4311. // default to first city
  4312. curCityNum=1;
  4313. }
  4314. return curCityNum;
  4315. },
  4316. SetCurrentAttackCityNum:function(curCityNum) {
  4317. if(!curCityNum){
  4318. var curCityNum = 1;
  4319. }
  4320. //this.Log("Setting current attack city to: "+curCityNum);
  4321. this.SetValue('CurrentAttackCityNum',curCityNum);
  4322. return curCityNum;
  4323. },
  4324.  
  4325. // returns {count, maxlevel}
  4326. getCityBuilding: function(cityId, buildingId){
  4327. var b = unsafeWindow.seed.buildings['city'+cityId];
  4328. var ret = {count:0, maxLevel:0};
  4329. for (var i=1; i<33; i++){
  4330. if (b['pos'+i] && b['pos'+i][0] == buildingId){
  4331. ++ret.count;
  4332. if (parseInt(b['pos'+i][1]) > ret.maxLevel)
  4333. ret.maxLevel = parseInt(b['pos'+i][1]);
  4334. }
  4335. }
  4336. return ret;
  4337. },
  4338.  
  4339. lastTrainTroops:{},
  4340. CheckTrainTroops:function() {
  4341. var t=this;
  4342. if(!this.GetSeed()) return;
  4343. var cityid=this.GetCurrentCityId();
  4344.  
  4345. var trainTroops=JSON2.parse(this.GetValue('TrainTroops','{}'));
  4346. //var trainTroops=GM_getValue('TrainTroops_'+this.GetServerId(),0);
  4347. if(!trainTroops || !trainTroops[cityid]) {
  4348. return;
  4349. }
  4350. var trainTroopId=trainTroops[cityid];
  4351. //GM_log('buildTroops'+unsafeWindow.seed.citystats["city" +cityid ]["pop"][0]+"=="+unsafeWindow.seed.citystats["city" + cityid]["pop"][1]);
  4352. var popAvail=parseInt(unsafeWindow.seed.citystats["city" +cityid ]["pop"][0]);
  4353. var popTotal=parseInt(unsafeWindow.seed.citystats["city" + cityid]["pop"][1]);
  4354. var labourTotal=parseInt(unsafeWindow.seed.citystats["city" + cityid]["pop"][3]);
  4355. var idleTotal=popTotal-labourTotal;
  4356. var popNeeded=((t.options.percentOfPopToTrain/100)*idleTotal)+labourTotal;
  4357. // Determine number of available training slots
  4358. var availableTrainingSlots = 0;
  4359. try{
  4360. var barracksTotal = this.getCityBuilding(cityid, 13).count;
  4361. var trainingSlotsUsed = unsafeWindow.seed.queue_unt['city'+cityid].length;
  4362. if(trainingSlotsUsed!=null){
  4363. var availableTrainingSlots = barracksTotal-trainingSlotsUsed;
  4364. }
  4365. }finally{
  4366. if(availableTrainingSlots<1){ return false; }
  4367. }
  4368.  
  4369. //GM_log('idleTotal:'+idleTotal+', labourTotal:'+labourTotal+', popneeded:'+popNeeded);
  4370. if(popAvail>0 && popAvail>=popNeeded) {
  4371. // avoid over training.
  4372. var lastTrain=this.lastTrainTroops[cityid];
  4373. var nowSecs=new Date().getTime()/1000;
  4374. if(nowSecs<(lastTrain+(3*60))) { return; }
  4375. var startButton=ById('unit_btns_start');
  4376. if(!startButton) {
  4377. // let's bring up build troops
  4378. this.DoUnsafeWindow('modal_barracks_train('+trainTroopId+');')
  4379. return;
  4380. }
  4381. var onclick=startButton.getAttribute('onclick');
  4382. var onclickM=/\(([0-9]+)\)/.exec(onclick);
  4383. if(!onclickM || trainTroopId!=onclickM[1]) {
  4384. return;
  4385. }
  4386. this.lastTrainTroops[cityid]=nowSecs;
  4387. // let's build troops
  4388. var numInp=ById('modal_barracks_num');
  4389. var maxObj=ById('modal_barracks_max_num');
  4390. if(numInp && maxObj) {
  4391. numInp.value=Math.floor(parseInt(maxObj.textContent)*(parseInt(this.options.percentToTrainOfMax)/100));
  4392. var t=this;
  4393. window.setTimeout(function() {
  4394. if(numInp.value>parseInt(maxObj.textContent)) {
  4395. t.Log('Not training troops:'+numInp.value+'>'+maxObj.textContent);
  4396. return;
  4397. }
  4398. //var n=unsafeWindow.modal_barracks_train_max(6);
  4399. onclick=onclick.replace('return false;','');
  4400. window.setTimeout(function() {
  4401. eval('unsafeWindow.'+onclick);
  4402. },t.GetRandTime(500));
  4403. },t.GetRandTime(500));
  4404. }
  4405. }
  4406. },
  4407.  
  4408. DetermineCurrentPage:function() {
  4409. if(unsafeWindow.location.href.match(/kingdomsofcamelot\.com\/fb\/.*?\/standAlone\.php/i)){
  4410. this.currentPage = 'kabam_page';
  4411. }else if(unsafeWindow.location.href.match(/kingdomsofcamelot\.com\/fb\/.*?\/src\/main_src\.php/i)){
  4412. this.currentPage = "koc_game";
  4413. }else if (unsafeWindow.location.href.match(/apps\.facebook\.com\/kingdomsofcamelot\/.*?page=nogame/i)) {
  4414. this.currentPage = "domain_selection_app_page";
  4415. }else if (unsafeWindow.location.href.match(/apps\.facebook\.com\/kingdomsofcamelot/i)) {
  4416. this.currentPage = "app_page";
  4417. }else if (unsafeWindow.location.href.match(/facebook.com\/connect\/uiserver.php/i)) {
  4418. this.currentPage = "facebook_popup";
  4419. }else if(unsafeWindow.location.href.match(/kingdomsofcamelot\.com\/fb\/.*?\/src\/newgame_src\.php/i)){
  4420. this.currentPage = "domain_selection";
  4421. }else{
  4422. this.currentPage = "unknown";
  4423. }
  4424. return this.currentPage;
  4425. },
  4426.  
  4427. OnImpendingAttack:function() {
  4428. var t=this;
  4429. this.Log("impending attack");
  4430. var autoAttack=this.GetAutoAttack();
  4431. var url=t.options.impendingAttackUrl;
  4432. if(url!=undefined && url !="") {
  4433. GM_openInTab(url);
  4434. }
  4435. if(t.options.impendingStopAttack){
  4436. if(autoAttack){
  4437. t.ToggleAutoAttack();
  4438. }
  4439. }
  4440. },
  4441. CheckImpendingAttack:function() {
  4442. var r=false;
  4443. var seed=this.GetSeed();
  4444. if(seed && seed.queue_atkinc) {
  4445. for(k in seed.queue_atkinc){
  4446. m = seed.queue_atkinc[k];
  4447. if (m.marchType==3 || m.marchType==4){
  4448. var q=0;
  4449. var keys=unsafeWindow.Object.keys(seed.queue_atkinc);
  4450. if(keys.length>0 && keys.length<16) {
  4451. r=true;
  4452. }
  4453. }
  4454. }
  4455. }
  4456. //GM_log('imp'+r);
  4457. /*
  4458. var topNav=ById('topnav_msg');
  4459. if(!topNav || topNav.innerHTML.length==0) return;
  4460. var redIdx=topNav.innerHTML.indexOf(': red');
  4461. var r=redIdx>=0?true:false;
  4462. if(!r) {
  4463. GM_log('tnav'+topNav.innerHTML);
  4464. }
  4465. */
  4466.  
  4467. var t=this;
  4468. var impendingAttack=this.GetValue('ImpendingAttack',false);
  4469. if(!impendingAttack && r) {
  4470. window.setTimeout(function() {
  4471. t.OnImpendingAttack();
  4472. },0);
  4473. }
  4474. this.SetValue('ImpendingAttack',r);
  4475. return r;
  4476. },
  4477.  
  4478.  
  4479. /*
  4480. current_modal_msg_list:"",
  4481. CheckMessageLoad:function(page) {
  4482. var t=this;
  4483. var msg=ById('modal_msg_list');
  4484. if(msg && msg.innerHTML!=t.current_modal_msg_list) {
  4485. t.current_modal_msg_list=msg.innerHTML;
  4486. var messageLoad=ById('MessageLoad');
  4487. if(!messageLoad) {
  4488. messageLoad=document.createElement('div');
  4489. messageLoad.id='MessageLoad';
  4490. messageLoad.style.position='absolute';
  4491. messageLoad.style.height='600px';
  4492. messageLoad.style.overflow='scroll';
  4493. messageLoad.style.top='10px';
  4494. messageLoad.style.zIndex='900000';
  4495. messageLoad.style.border='5px solid #000';
  4496. messageLoad.style.backgroundColor='#fff';
  4497. document.body.appendChild(messageLoad);
  4498. }
  4499. var m=document.createElement('div');
  4500. m.innerHTML=msg.innerHTML;
  4501. messageLoad.appendChild(m);
  4502. page++;
  4503. this.DoUnsafeWindow("modal_messages_listshow('inbox',page);");
  4504. }
  4505. window.setTimeout(function() {
  4506. t.CheckMessageLoad(page);
  4507. },200);
  4508. },
  4509.  
  4510. ReadEmails:function() {
  4511. this.current_modal_msg_list='';
  4512. this.CheckMessageLoad();
  4513. },
  4514.  
  4515. */
  4516.  
  4517.  
  4518.  
  4519. FactoryReset:function() {
  4520. var names=this.browser_listValues();
  4521. for(var n=0; n<names.length; n++) {
  4522. this.browser_setValue(names[n],null);
  4523. }
  4524. this.SetOptions({});
  4525. },
  4526. FactoryResetCurrentServer:function() {
  4527. var names=this.browser_listValues();
  4528. var serverId=this.GetServerId();
  4529. for(var n=0; n<names.length; n++) {
  4530. var name=names[n];
  4531. var sid=this.GetServerIdFromName(name);
  4532. if(sid!=serverId) continue;
  4533. this.browser_setValue(name,null);
  4534. }
  4535. },
  4536. GetServerIdFromName:function(n) {
  4537. var nArr=n.split('_');
  4538. if(nArr.length<2) return null;
  4539. return nArr[1];
  4540. },
  4541. DeleteAllStoredAttacks:function() {
  4542. var t=this;
  4543. this.IterateAttacks(function(name,value) {
  4544. var nameI=name.split('_');
  4545. if(nameI.length<3) return;
  4546. var xy=nameI[2].split(',');
  4547. if(value=="") return;
  4548. var attack=JSON2.parse(value);
  4549. if(!attack) return;
  4550. var attackX = xy[0];
  4551. var attackY = xy[1];
  4552. if(attackX && attackY){
  4553. t.DeleteAttack(attackX, attackY);
  4554. }
  4555. return true;
  4556. });
  4557. window.alert("All stored attacks for this domain have been deleted.\nClick the ok button to reload.");
  4558. },
  4559. DeleteTransports:function() {
  4560. var t=this;
  4561. this.IterateAttacks(function(name,value) {
  4562. var nameI=name.split('_');
  4563. if(nameI.length<3) return;
  4564. var xy=nameI[2].split(',');
  4565. if(value=="") return;
  4566. var attack=JSON2.parse(value);
  4567. if(!attack) return;
  4568. var attackX = xy[0];
  4569. var attackY = xy[1];
  4570. if(attack.type == 1){
  4571. t.DeleteAttack(attackX, attackY);
  4572. }
  4573. return true;
  4574. });
  4575. window.alert("All stored transports for this domain have been deleted.\nClick the ok button to reload.");
  4576. },
  4577. ListTransports:function() {
  4578. var t=this;
  4579. var fTransport = 0;
  4580. this.IterateAttacks(function(name,value) {
  4581. var nameI=name.split('_');
  4582. if(nameI.length<3) return;
  4583. var xy=nameI[2].split(',');
  4584. if(value=="") return;
  4585. var attack=JSON2.parse(value);
  4586. if(attack.type == 1){
  4587. WinLog.write ("Name: "+name+" Value: "+value);
  4588. fTransport = 1;
  4589. return true;
  4590. }
  4591. });
  4592. if (!fTransport){
  4593. WinLog.write ("No Transports Found\n");
  4594. return true;
  4595. }
  4596. },
  4597. ListAttacks:function() {
  4598. var t=this;
  4599. this.IterateAttacks(function(name,value) {
  4600. WinLog.write (name+" "+value);
  4601. return true;
  4602. });
  4603. },
  4604. DetailAttacks:function() {
  4605. var t=this;
  4606. var names=GM_listValues();
  4607. var currentServerId = t.GetServerId();
  4608. var attackPrefix='attack_'+currentServerId+'_';
  4609. for(var n=0; n<names.length; n++) {
  4610. var name=names[n];
  4611. var nameI=name.split('_');
  4612. if(nameI.length<3) continue;
  4613. var xy=nameI[2].split(',');
  4614. if(name.substring(0,attackPrefix.length)!=attackPrefix) continue;
  4615. var value = GM_getValue(name);
  4616. if(value=="") continue;
  4617. var attack=JSON2.parse(value);
  4618. attack.xy=xy;
  4619. if(!attack) continue;
  4620. t.attacks.push(attack);
  4621. }
  4622. },
  4623. ExportAllToJSON:function() {
  4624. var names=this.browser_listValues();
  4625. var obj={};
  4626. var serverId=this.GetServerId();
  4627. for(var n=0; n<names.length; n++) {
  4628. var name=names[n];
  4629. var sid=this.GetServerIdFromName(name);
  4630. if(sid!=serverId) continue;
  4631. var v=this.browser_getValue(name,null);
  4632. if(v!=null && v!=undefined && v!="")
  4633. obj[name]=v;
  4634. }
  4635. return JSON2.stringify(obj);
  4636. },
  4637. ImportAllFromJSON:function(json) {
  4638. try {
  4639. var obj=JSON2.parse(json);
  4640. if(!obj) { return; }
  4641. this.FactoryResetCurrentServer();
  4642. var serverId=this.GetServerId();
  4643. for(var name in obj) {
  4644. var sid=this.GetServerIdFromName(name);
  4645. if(sid!=serverId) continue;
  4646. this.browser_setValue(name,obj[name]);
  4647. }
  4648. } catch(e) {
  4649. window.alert('Import failed'+e);
  4650. }
  4651. },
  4652.  
  4653. SetupMenu:function() {
  4654. var t=this;
  4655. GM_registerMenuCommand('KOCAttack - Options',function() {
  4656. t.ShowOptionsDialog();
  4657. });
  4658. GM_registerMenuCommand('KOCAttack - View Attacks',function() {
  4659. t.ShowViewAttacksDialog();
  4660. });
  4661. GM_registerMenuCommand('KOCAttack - Import/Export',function() {
  4662. t.ShowImportExportBox();
  4663. });
  4664. GM_registerMenuCommand('KOCAttack - Auto Attack',function() {
  4665. t.ToggleAutoAttack();
  4666. });
  4667. GM_registerMenuCommand('KOCAttack - Factory Reset!',function() {
  4668. t.FactoryReset();
  4669. });
  4670. },
  4671.  
  4672.  
  4673.  
  4674.  
  4675. /*
  4676. TimeoutZero:function(f,arg) {
  4677. setTimeout(function() {
  4678. f(arg);
  4679. },0);
  4680. },
  4681. */
  4682.  
  4683. pageLoaded:false,
  4684. prevCurrentCity:-1,
  4685. currentAttackCityResumed:false,
  4686. inviteFriendsTabHidden:false,
  4687. idStatus:{},
  4688. ResetIdStatus:function() {
  4689. this.idStatus={};
  4690. },
  4691. Listen:function() {
  4692. var t=this;
  4693. t.SetupMenu();
  4694. this.GetValuesCache();
  4695. t.ResetAutoAttackTarget();
  4696. this.options=this.GetOptions();
  4697. this.startListenTime=new Date();
  4698. // Determine which page we're on
  4699. t.DetermineCurrentPage();
  4700. // Code strictly for page: koc_game
  4701. if(t.currentPage == "koc_game"){
  4702. //Check for strange majic error
  4703. //setTimeout(function(){checkStrangeMagic();},15000);
  4704. window.setTimeout(function() {
  4705. if(!t.pageLoaded && t.GetAutoAttack() && !t.IsMapperRunning()) {
  4706. GM_log("whoops, game not loaded after 60 secs problem. reloading.");
  4707. t.SetValuesCache();
  4708. t.ReloadWindow();
  4709. }
  4710. },t.GetRandTime(60*1000));
  4711.  
  4712. if(t.GetAutoAttack()) {
  4713. window.setTimeout(function() {
  4714. // press start on the poc timer after we reload
  4715. if(unsafeWindow.poctoggletimer && unsafeWindow.ispaused) {
  4716. unsafeWindow.poctoggletimer();
  4717. }
  4718. },5000);
  4719. }
  4720. // Hide the invite friends tab on page load
  4721. if(!t.inviteFriendsTabHidden && this.options.disableInviteFriends){
  4722. var tabBar=ById("main_engagement_tabs");
  4723. if(tabBar){
  4724. var inviteFriendsTab=nHtml.FindByXPath(tabBar,".//a[contains(@onclick,'invite_friends_popup')]");
  4725. if(inviteFriendsTab){
  4726. inviteFriendsTab.style.display="none";
  4727. t.inviteFriendsTabHidden = true;
  4728. }
  4729. }
  4730. }
  4731. } // End of code strictly for page: koc_game
  4732. var domTickTimer=null;
  4733. var domTickUpto=0;
  4734. var domTick=function(e) {
  4735. var funcsById={};
  4736. // Handle cross-iframe commands (which are currently only being used for the domain selection page)
  4737. if (t.currentPage == "domain_selection" || t.currentPage == "domain_selection_app_page"){
  4738. if((domTickUpto%20)==0) {
  4739. t.HandleCrossIframeCommands();
  4740. }
  4741. }
  4742. if (t.currentPage == 'kabam_page'){
  4743. return;
  4744. }
  4745.  
  4746. // Code strictly for page: koc_game
  4747. if(t.currentPage == "koc_game"){
  4748. //if(e.target.className && !/(chat|city|slot)/.exec(e.target.className)) GM_log('xxx:'+e.target.className);
  4749. //if(e.target.id && e.target.id!='tooltip' && e.target.id('_l_')<0 && e.target.id.substring(0,2)!='l_' && e.target.id.substring(0,8)!='citysel_') GM_log('id:'+e.target.id);
  4750. var cityId=t.GetCurrentCityId();
  4751. var cityChanged=cityId!=t.prevCurrentCity?true:false;
  4752. if(cityChanged) {
  4753. t.prevCurrentCity=cityId;
  4754. }
  4755.  
  4756. // Resume attacks at the last city we left off on (if page was reloaded)
  4757. if(!t.currentAttackCityResumed){
  4758. var currentAttackCityNum = t.GetCurrentAttackCityNum();
  4759. var currentAttackCity=ById('citysel_'+currentAttackCityNum);
  4760. //t.Log('Last known attack city from :'+currentAttackCityNum);
  4761. if(currentAttackCity){
  4762. if(currentAttackCityNum>1){ //Do not change city if the last city saved was 1
  4763. t.Log('Changing to last city before refresh:'+currentAttackCityNum);
  4764. t.autoAttackCityUpto = currentAttackCityNum;
  4765. t.ClickChangeCity(currentAttackCity,0);
  4766. }
  4767. t.currentAttackCityResumed = true;
  4768. }
  4769. }
  4770. if((domTickUpto%10)==0) {
  4771. t.HandleChatPane();
  4772. }
  4773. if((domTickUpto%20)==0) {
  4774. t.CheckImpendingAttack();
  4775. }
  4776. if(cityChanged && cityId!=null) {
  4777. // changed city
  4778. setTimeout(function() {
  4779. t.AddOptionsLink();
  4780. t.DrawClosestFarms(); // Init auto attack tab
  4781. t.AddViewAttacksLink();
  4782. //t.AddImportExportLink();
  4783. },0);
  4784. setTimeout(function() {
  4785. t.DetermineCurrentRallyPointLevel();
  4786. t.DetermineCurrentMarchesNum();
  4787. t.CheckAutoRaiseGold();
  4788. t.CheckAbandonWilds();
  4789. t.CheckTrainTroops();
  4790. },1000);
  4791. setTimeout(function() {
  4792. t.CheckReports();
  4793. },3000);
  4794. setTimeout(function() {
  4795. t.NextAutoAttack();
  4796. },5000);
  4797. }
  4798. funcsById={
  4799. 'castleModalTabs':function(target) {
  4800. t.OnCastleBoxAppear(target.parentNode);
  4801. },
  4802. 'marketmain_bdy':function(target) {
  4803. t.OnMarketBoxAppear(target);
  4804. },
  4805. 'modal_attack':function(target) {
  4806. window.setTimeout(function() {
  4807. t.OnAttackBoxAppear(target);
  4808. },250);
  4809. },
  4810. 'barracks_train':function(target) {
  4811. t.AddTrainTroopsLink();
  4812. t.CheckTrainTroops();
  4813. },
  4814. 'modal_speedup':function(target) {
  4815. t.ClickShareToWall(target);
  4816. },
  4817. 'invitePopup':function(target) {
  4818. if(this.options.disableInviteFriends && false){
  4819. // Hide the invite popup if auto attack is enabled
  4820. target.parentNode.removeChild(target);
  4821. }
  4822. },
  4823. };
  4824. } // End of code strictly for page: koc_game
  4825. // Handle cross-domain facebook game publish requests
  4826. funcsById.RES_ID_fb_pop_dialog_table = function(target){
  4827. if (t.currentPage == "koc_game") {
  4828. // Update the current server id locally for cross-domain access
  4829. if(t.currentServerId>0 && t.currentPage == "koc_game"){
  4830. GM_setValue("KOCAttackLastKnownServerID", t.currentServerId);
  4831. }
  4832. }
  4833. }
  4834. if(t.currentPage == "facebook_popup"){
  4835. if((domTickUpto%20)==0) {
  4836. t.HandlePublishPopup();
  4837. }
  4838. }
  4839. // Log back into domain if disconnected due to server down-time
  4840. if(t.currentPage == "domain_selection" && t.options.autoLogBackIn){
  4841. if((domTickUpto%20)==0) {
  4842. t.HandleDomainLogin();
  4843. }
  4844. }
  4845. /*
  4846. if(e.target.id && funcsById[e.target.id]) {
  4847. funcsById[e.target.id](e.target);
  4848. } else
  4849. */
  4850. //if(e.target.className.indexOf('modalBox')>=0) {
  4851. var funcCalled=0;
  4852. if(funcCalled==0) {
  4853. for(var id in funcsById) {
  4854. var f=funcsById[id];
  4855. var div=ById(id);
  4856.  
  4857. if(!t.idStatus[id] && div) {
  4858. var fcall=function(func,d) {
  4859. funcCalled++;
  4860. setTimeout(function() {
  4861. try {
  4862. func(d);
  4863. } finally {
  4864. funcCalled--;
  4865. }
  4866. },0);
  4867. }
  4868. fcall(f,div);
  4869.  
  4870. //t.TimeoutZero(f,div);
  4871. }
  4872. var divStatus=div?true:false;
  4873. if(divStatus!=t.idStatus[id]) {
  4874. //t.Log("Status changed:"+id+","+divStatus);
  4875. }
  4876. t.idStatus[id]=divStatus;
  4877. }
  4878. }
  4879. if(!domTickTimer) {
  4880. domTickTimer=window.setTimeout(function() {
  4881. domTickTimer=null;
  4882. domTick();
  4883. domTickUpto++;
  4884. },250);
  4885. }
  4886. };
  4887. var withinDomInserted=false;
  4888. if(document.body){
  4889. document.body.addEventListener('DOMNodeInserted',function(e) {
  4890. if(withinDomInserted) return;
  4891. var isStatuses=(e.target.className && e.target.className=='statues')?true:false;
  4892. if(isStatuses){
  4893. t.pageLoaded=true;
  4894. }
  4895. if(e.target.id && e.target.id=='tooltip') {
  4896. withinDomInserted=true;
  4897. setTimeout(function() {
  4898. try {
  4899. if(this.options.disableDrawMapIcons)
  4900. t.DrawLevelIcons();
  4901. t.OnToolTipAppear(e.target);
  4902. } finally {
  4903. withinDomInserted=false;
  4904. }
  4905. },0);
  4906. } else if(e.target.className && e.target.className.indexOf('modal_msg_reports')>=0) {
  4907. withinDomInserted=true;
  4908. setTimeout(function() {
  4909. try {
  4910. t.RecordReports();
  4911. t.AddCheckBarbarians();
  4912. t.HighlightAllianceReports();
  4913. } finally {
  4914. withinDomInserted=false;
  4915. }
  4916. },0);
  4917. }
  4918. },false);
  4919. }
  4920.  
  4921. domTick();
  4922. },
  4923.  
  4924. };
  4925.  
  4926. unsafeWindow.aaGotoMapHide = function (x, y){
  4927. try {
  4928. unsafeWindow.Modal.hideModal();
  4929. } catch (e){ }
  4930. try {
  4931. Modal.hideModal();
  4932. } catch (e){ }
  4933. unsafeWindow.aaGotoMap (x, y);
  4934. }
  4935.  
  4936. unsafeWindow.aaGotoMap = function (x, y){
  4937. var close = document.getElementById('KOCAttackViewAttacksCancel');
  4938. nHtml.Click(close);
  4939. setTimeout (function (){
  4940. document.getElementById('mapXCoor').value = x;
  4941. document.getElementById('mapYCoor').value = y;
  4942. unsafeWindow.reCenterMapWithCoor();
  4943. var a = document.getElementById("mod_views").getElementsByTagName("a");
  4944. for (var b = 0; b < a.length; b++) {
  4945. a[b].className = ""
  4946. }
  4947. document.getElementById('mod_views_map').className = "sel";
  4948. document.getElementById("maparea_city").style.display = 'none';
  4949. document.getElementById("maparea_fields").style.display = 'none';
  4950. document.getElementById("maparea_map").style.display = 'block';
  4951. unsafeWindow.tutorialClear()
  4952. }, 0);
  4953. };
  4954.  
  4955. function SetupQuickMarchButton(useRetryMarch) {
  4956. /*
  4957. var retryMarch='var retryMarch=function() { alert("retrying march"); new (Ajax.Request)(g_ajaxpath + "ajax/march.php" + g_ajaxsuffix, {'+
  4958. 'method: "post",'+
  4959. 'parameters: params,'+
  4960. 'onSuccess: function (transport) {'+
  4961. 'var rslt = eval("(" + transport.responseText + ")");'+
  4962. 'if (!rslt.ok) {'+
  4963. 'if(rslt.error_code==3) {'+
  4964. 'window.setTimeout(function() { retryMarch(); },1000); '+
  4965. '} else {'+
  4966. 'alert("March Error:"+rslt.msg);'+
  4967. '}'+
  4968. '}'+
  4969. '}'+
  4970. '}); };';
  4971. */
  4972. var retryMarches='var retryMarch = function() { '+
  4973. 'new (Ajax.Request)(g_ajaxpath + "ajax/march.php" + g_ajaxsuffix, {'+
  4974. 'method: "post",'+
  4975. 'parameters: params,'+
  4976. 'onSuccess: function(transport) { marchSuccess(transport); },'+
  4977. 'onFailure: function () { Modal.hideModalAll(); }'+
  4978. '}); };';
  4979. if(!useRetryMarch) {
  4980. retryMarches='var retryMarch = function() { return; };';
  4981. }
  4982. var modal_attack_update_num_maxReplaces=[
  4983. [['modal_attack_update_num_max','modal_attack_update_num_maxOld']],
  4984. [['$("modal_attack_unit_ipt','var x=0; var o = getBuildingLevel(12); if(o==11){x=150000}else{x=o*10000};$("modal_attack_unit_ipt']],
  4985. [['parseInt(','x; //parseInt(']]
  4986. ];
  4987. var modalAttackReplaces=[
  4988. // *** it says "new Ajax" in the source but firefox converts it to new (Ajax
  4989. [['modal_attack_do','modal_attack_doOld']],
  4990. [['onSuccess:','onSuccess: marchSuccess=']],
  4991. [['Modal.showAlert(printLocalError(','if(rslt.error_code==3 || rslt.error_code==8) { try {window.setTimeout(function() { retryMarch(); },(3*1000)); } catch(e) { alert("retry failed:"+e); } } else { Modal.hideModalAll(); } Modal.showAlert(printLocalError(']]
  4992. ];
  4993. var attack_generatequeueReplaces=[
  4994. [['attack_generatequeue','attack_generatequeueOld']],
  4995. [
  4996. ['class=\\"army\\">" + g_js_strings.commonstr.army + ": "','style=\\"width: 145px !important\\" class=\\"army\\">"'],
  4997. ['class=\\"army\\">" + g_js_strings.commonstr.army + ": <span>"','style=\\"width: 145px !important\\" class=\\"army\\"><span style=\'display: inline\'>"']
  4998. ],
  4999. [['class=\\"name','style=\\"width: 0px !important; display: none;\\" class=\\"name']],
  5000. //[/123/g,'100']
  5001. ];
  5002. var attack_generatequeueReplacesU=[
  5003. [['var u = 0;','var u = "K:"+seed.knights["city" + currentcityid]["knt" + q].combat+", "; ']],
  5004. [['u += parseInt','var x = parseInt']],
  5005. [['"Count"]);','"Count"]); if(x>0) { var uname=unitcost["unt"+r][0]; u+=uname[0]+uname[uname.length-1]+":"+x+", "; } ']],
  5006. ];
  5007. var attack_generatequeueReplacesR=[
  5008. [['var r = 0;','var r = "K:"+seed.knights["city" + currentcityid]["knt" + t].combat+", "; ']],
  5009. [['r += parseInt','var x = parseInt']],
  5010. [['"Count"]);','"Count"]); if(x>0) { var uname=unitcost["unt"+p][0]; r+=uname[0]+uname[uname.length-1]+":"+x+", "; } ']],
  5011. ];
  5012. var attack_generatequeueReplacesS=[
  5013. [['var s = 0;','var s = "K:"+seed.knights["city" + currentcityid]["knt" + u].combat+", "; ']],
  5014. [['s += parseInt','var x = parseInt']],
  5015. [['"Count"]);','"Count"]); if(x>0) { var uname=unitcost["unt"+q][0]; s+=uname[0]+uname[uname.length-1]+":"+x+", "; } ']],
  5016. ];
  5017. var attack_generatequeueReplacesT=[
  5018. [['var t = 0;','var t = "K:"+seed.knights["city" + currentcityid]["knt" + w].combat+", "; ']],
  5019. [['t += parseInt','var x = parseInt']],
  5020. [['"Count"]);','"Count"]); if(x>0) { var uname=unitcost["unt"+q][0]; t+=uname[0]+uname[uname.length-1]+":"+x+", "; } ']],
  5021. ];
  5022. var attack_generatequeueReplacesV=[
  5023. [['var v = 0;','var v = "K:"+seed.knights["city" + currentcityid]["knt" + y].combat+", "; ']],
  5024. [['v += parseInt','var f = parseInt']],
  5025. [['"Count"]);','"Count"]); if(f>0) { var uname=unitcost["unt"+r][0]; v+=uname[0]+uname[uname.length-1]+":"+f+", "; } ']],
  5026. ];
  5027. var attack_generatequeueReplacesW=[
  5028. [['var w = 0;','var w = "K:"+seed.knights["city" + currentcityid]["knt" + A].combat+", "; ']],
  5029. [['w += parseInt','var t = parseInt']],
  5030. [['w += parseInt','var t = parseInt']],
  5031. [['"Return"])','"Return"]); if(t>0) { var uname=unitcost["unt"+s][0]; w+=uname[0]+uname[uname.length-1]+":"+t+", "; } ']],
  5032. [['"Count"])','"Count"]); if(t>0) { var uname=unitcost["unt"+s][0]; w+=uname[0]+uname[uname.length-1]+":"+t+", "; } ']],
  5033. ];
  5034. var attack_generatequeueReplacesW2=[
  5035. [['var w = 0;','var w = "K:"+seed.knights["city" + currentcityid]["knt" + E].combat+", "; ']],
  5036. [['w += y','if(y>0) { var uname=unitcost["unt"+cm.UNIT_TYPES[t]][0]; w+=uname[0]+uname[uname.length-1]+":"+y+", "; }']],
  5037. ];
  5038. /*****
  5039. if(navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
  5040. modalAttackReplaces.push([['new Ajax',"var marchSuccess=null; "+retryMarch+
  5041. (useRetryMarch?"":" Modal.hideModalAll(); ")+
  5042. "\nnew Ajax"]]);
  5043. } else {
  5044. modalAttackReplaces.push([['new (Ajax',"var marchSuccess=null; "+retryMarch+
  5045. (useRetryMarch?"":" Modal.hideModalAll(); ")+
  5046. "\nnew (Ajax"]]);
  5047. }
  5048. *****/
  5049. //modalAttackReplaces.push([['ajax.Request', "var marchSuccess=null; "+retryMarch+
  5050. //(useRetryMarch?"":" Modal.hideModalAll(); ")+ "\najax.Request"]]);
  5051.  
  5052. if(!useRetryMarch) modalAttackReplaces.push(['Modal.hideModalAll();','']);
  5053. var replaceFunc=function(name,replaces) {
  5054. var modalAttackFunc=window[name].toString();
  5055. var nameOld=name+'Old';
  5056. var foundFailed=false;
  5057. for(var a=0; a<replaces.length; a++) {
  5058. var found=false;
  5059. var repArr=replaces[a];
  5060. for(var ra=0; ra<repArr.length; ra++) {
  5061. var repI=repArr[ra];
  5062. if(typeof(repI[0])=="object") {
  5063. found=repI[0].exec(modalAttackFunc)?true:false;
  5064. } else {
  5065. found=modalAttackFunc.indexOf(repI[0])>=0?true:false;
  5066. }
  5067. if(found) break;
  5068. }
  5069. if(!found) {
  5070. var err="modalAttackReplace: cannot find: "+repI[0]+','+modalAttackFunc;
  5071. var sp=document.createElement('span');
  5072. sp.style.color='#ccc';
  5073. sp.appendChild(document.createTextNode(err));
  5074. document.body.insertBefore(sp,document.body.childNodes[0]);
  5075. foundFailed=true;
  5076. break;
  5077. }
  5078. modalAttackFunc=modalAttackFunc.replace(repI[0],repI[1]);
  5079. }
  5080. if(foundFailed) return;
  5081. try {
  5082. window[nameOld]=eval(modalAttackFunc);
  5083. //alert(window[nameOld].toString());
  5084. } catch(e) {
  5085. alert(e+', bad func:'+modalAttackFunc);
  5086. }
  5087.  
  5088. window[name]=function(e) {
  5089. // let our stuff in addListener run first.
  5090. window.setTimeout(function() {
  5091. eval(nameOld+'(e);');
  5092. },100);
  5093. }
  5094. };
  5095. var attackFuncStr=window['modal_attack_do'].toString();
  5096. //if(attackFuncStr.indexOf('ajax.Request')<0) {
  5097. modalAttackReplaces.push([
  5098. ['new (Ajax',"var marchSuccess=null; "+retryMarches+
  5099. (useRetryMarch?"":" Modal.hideModalAll(); ")+
  5100. "\nnew (Ajax"],
  5101. ['new Ajax',"var marchSuccess=null; "+retryMarches+
  5102. (useRetryMarch?"":" Modal.hideModalAll(); ")+
  5103. "\nnew Ajax"],
  5104. ['ajax.Request',"var marchSuccess=null; "+retryMarches+
  5105. (useRetryMarch?"":" Modal.hideModalAll(); ")+
  5106. "\najax.Request"]
  5107. ]);
  5108. //}
  5109. replaceFunc('modal_attack_do',modalAttackReplaces);
  5110. //replaceFunc('modal_attack_update_num_max',modal_attack_update_num_maxReplaces);
  5111. function AddArray(to,from) {
  5112. for(var c=0; c<from.length; c++) { to.push(from[c]); }
  5113. }
  5114. var arr=[];
  5115. AddArray(arr,attack_generatequeueReplaces);
  5116. var funcStr=window['attack_generatequeue'].toString();
  5117. if(funcStr.indexOf(' var w = 0;')>=0) {
  5118. // camelotmain-218
  5119. AddArray(arr,attack_generatequeueReplacesW2);
  5120. } else if(funcStr.indexOf('; var r = 0;')>=0) {
  5121. AddArray(arr,attack_generatequeueReplacesR);
  5122. } else if(funcStr.indexOf('; var s = 0;')>=0) {
  5123. AddArray(arr,attack_generatequeueReplacesS);
  5124. } else if(funcStr.indexOf('; var t = 0;')>=0) {
  5125. // camelotmain-150
  5126. AddArray(arr,attack_generatequeueReplacesT);
  5127. } else if(funcStr.indexOf('; var v = 0;')>=0) {
  5128. // camelotmain-165
  5129. AddArray(arr,attack_generatequeueReplacesV);
  5130. } else if(funcStr.indexOf('; var u = 0;')>=0) {
  5131. AddArray(arr,attack_generatequeueReplacesU);
  5132. } else {
  5133. var err="Unknown attack queue func: "+location.href+"\n"+funcStr;
  5134. GM_log(err);
  5135. }
  5136. replaceFunc('attack_generatequeue',arr);
  5137.  
  5138. //replaceFunc('modal_attack_update_num',modalAttackUpdateNumReplaces);
  5139.  
  5140. /* BAD: updateSeed.php doesn't return cityUnits
  5141. var params = Object.clone(g_ajaxparams);
  5142. new Ajax.Request(g_ajaxpath + "ajax/updateSeed.php" + g_ajaxsuffix, {
  5143. method: "post",
  5144. parameters: params,
  5145. onSuccess: function (message) {
  5146. alert(message.responseText);
  5147. }
  5148. });
  5149. */
  5150. }
  5151.  
  5152. /*
  5153. function SetupClearMessages() {
  5154. modal_messages_reports_chkdelOld=modal_messages_reports_chkdel;
  5155. modal_messages_reports_chkdel=function(type) {
  5156. var d=document.createElement('div');
  5157. d.id='modal_msg_reports_tablediv';
  5158. document.body.appendChild(d);
  5159. modal_messages_reports_chkdelOld(type);
  5160. if(type=='deleteAll') {
  5161. document.getElementById('ClearMessages').click();
  5162. }
  5163. };
  5164. }
  5165. */
  5166.  
  5167. function CreateMsgDiv() {
  5168. var m=document.getElementById('KOCAttackMsgDiv');
  5169. if(!m) {
  5170. var ml=document.getElementById('modal_msg_list');
  5171. if(!ml) {
  5172. ml=document.createElement('div');
  5173. ml.id='modal_msg_list';
  5174. }
  5175. m=document.createElement('div');
  5176. m.style.position='absolute';
  5177. m.style.top='0px';
  5178. m.style.left='0px';
  5179. m.style.width='700px';
  5180. m.style.zIndex='900000';
  5181. m.style.border='5px solid #000';
  5182. m.style.backgroundColor='#fff';
  5183. //m.id='modal_attack';
  5184. var close=document.createElement('a');
  5185. close.addEventListener('click',function() {
  5186. m.style.display='none';
  5187. m.removeChild(ml);
  5188. },false);
  5189. close.innerHTML='Close';
  5190. close.style.fontSize='20px';
  5191. var center=document.createElement('center');
  5192. center.appendChild(close);
  5193. m.appendChild(center);
  5194. m.appendChild(ml);
  5195. if(!document.getElementById('modal_msg_list_pagination')) {
  5196. p=document.createElement('div'); p.id='modal_msg_list_pagination';
  5197. ml.appendChild(p);
  5198. }
  5199. //document.body.insertBefore(m,document.body.childNodes[0]);
  5200. if(document.body){
  5201. document.body.appendChild(m);
  5202. }
  5203. }
  5204. m.style.display='block';
  5205. return m;
  5206. }
  5207.  
  5208. function AddScript(js) {
  5209. var scr=document.createElement('script');
  5210. scr.innerHTML=js;
  5211. document.body.appendChild(scr);
  5212. }
  5213. function SetupScripts() {
  5214. var options=KOCAttack.GetOptions();
  5215. var scr=document.createElement('script');
  5216. scr.innerHTML="CreateMsgDiv="+CreateMsgDiv+
  5217. ";\n"+
  5218. // SetupClearMessages+"\n; SetupClearMessages();\n"+
  5219. ";\n"+SetupQuickMarchButton+"\n; SetupQuickMarchButton("+options.retryMarch+"); \n";
  5220. document.body.appendChild(scr);
  5221. }
  5222.  
  5223. /******************* Anti-anticheat measures ******************/
  5224. var mixpanelRemoved=false;
  5225. function DisableMixpanel() {
  5226. if(unsafeWindow.cm) {
  5227. unsafeWindow.cm.MixPanelTracker.track=function() { };
  5228. }
  5229. if(unsafeWindow.MixpanelLib) {
  5230. unsafeWindow.MixpanelLib.prototype={
  5231. register:function() { },
  5232. track:function(t) {
  5233. }
  5234. };
  5235. }
  5236. if(!unsafeWindow.cm || !unsafeWindow.MixpanelLib) {
  5237. window.setTimeout(function() {
  5238. DisableMixpanel();
  5239. },100);
  5240. } else {
  5241. GM_log('Mixpanel removed');
  5242. mixpanelRemoved=true;
  5243. }
  5244. }
  5245.  
  5246.  
  5247.  
  5248. /******************* Check strange majic error ******************/
  5249. function checkWhiteScreen (){
  5250. window.setTimeout(function(){
  5251. GM_log("Check iFrame");
  5252. var checknumber = 0;
  5253. function checkiFrame() {
  5254. var iFrame = document.getElementById('iframe_canvas');
  5255. if (!iFrame && checknumber<10){
  5256. checknumber++;
  5257. setTimeout (checkiFrame, 1000);
  5258. return;
  5259. } else if (checknumber>=10){
  5260. KOCAttack.ReloadWindow();
  5261. GM_log("White screen error. Refreshing.....");
  5262. }
  5263. return;
  5264. }
  5265. checkiFrame();
  5266. }, 10000);
  5267. }
  5268. function checkStrangeMagic (){
  5269. GM_log("Check strange majic");
  5270. if (!document.getElementById("kochead")){
  5271. window.setTimeout ( function() { GM_log ("checkStrangeMajik REloading..."); KOCAttack.ReloadWindow(); }, 5000);
  5272. popup (100,100,500,275, "<BR><CENTER>checkStrangeMajik <BR><BR>KofC NOT FOUND<BR>Refreshing in 5 seconds ...<BR><BR>");
  5273. }
  5274. }
  5275.  
  5276. function popup (left, top, width, height, content){
  5277. var div = document.createElement('div');
  5278. if (width)
  5279. div.style.width = width;
  5280. if (height)
  5281. div.style.height = height;
  5282. if (left || top) {
  5283. div.style.position = "relative";
  5284. if (left)
  5285. div.style.left = left;
  5286. if (top)
  5287. div.style.top = top;
  5288. }
  5289. if (content)
  5290. div.innerHTML = content;
  5291. div.style.background = "#ffc";
  5292. div.style.border = "2px solid #000";
  5293. div.style.zIndex = "999999"; // KOC modal is 100210 ?
  5294. div.style.display = 'block';
  5295. window.document.body.insertBefore(div, window.document.body.childNodes[0]);
  5296. return div;
  5297. }
  5298.  
  5299. /******************* Function calls ******************/
  5300. KOCAttack.Listen();
  5301. if(unsafeWindow.cm){
  5302. unsafeWindow.cm.cheatDetector={
  5303. a:function(){ },
  5304. detect:function() { }
  5305. };
  5306. }
  5307. if(document.URL.search('apps.facebook.com/kingdomsofcamelot/')>=0) {
  5308. checkWhiteScreen();
  5309. } else {
  5310. StartAll();
  5311. }
  5312. var startAllTimeout=null;
  5313. function StartAll() {
  5314. DisableMixpanel();
  5315. var now=new Date().getTime();
  5316. if(startAllTimeout==null) {
  5317. startAllTimeout=now+5000;
  5318. }
  5319. if(mixpanelRemoved || startAllTimeout<now) {
  5320. if(startAllTimeout<now) {
  5321. GM_log("Did not remove mixpanel, starting anyways");
  5322. }
  5323. KOCAttack.SetupClearMessages();
  5324.  
  5325. SetupScripts();
  5326. } else {
  5327. window.setTimeout(function() { StartAll(); },200);
  5328. }
  5329. }
  5330.  
  5331. var WINLOG_MAX_ENTRIES = 1000; // TODO
  5332. var WinLog = {
  5333. state : null,
  5334. win: null,
  5335. eOut : null,
  5336. lastE : null,
  5337. enabled : true,
  5338. reverse : true,
  5339. busy : false,
  5340. isOpening : false,
  5341.  
  5342. open : function (){
  5343. var t = WinLog;
  5344. GM_log("opening WinLog");
  5345.  
  5346. function eventButClear(){
  5347. var t = WinLog;
  5348. t.lastE = null;
  5349. t.eOut.innerHTML ='';
  5350. }
  5351. function eventButReverse(){
  5352. var t = WinLog;
  5353. if (t.busy)
  5354. return;
  5355. t.busy = true;
  5356. if (t.reverse){
  5357. t.win.document.getElementById('wlRev').value= 'Top';
  5358. t.reverse = false;
  5359. } else{
  5360. t.win.document.getElementById('wlRev').value= 'Bottom';
  5361. t.reverse = true;
  5362. }
  5363. var n = t.eOut.childNodes.length;
  5364. if (n < 2)
  5365. return;
  5366. for (i=n-2; i>=0; i--){
  5367. t.eOut.appendChild (t.eOut.childNodes[i]);
  5368. }
  5369. t.busy = false;
  5370. }
  5371. if (!t.win || t.win.closed){
  5372. t.isOpening = true;
  5373. t.win = window.open('', 'uwtrace', 'top=30,left=0,width=900,height=700,scrollbars=no,location=no,menubar=no,directories=no,status=no');
  5374. t.isOpening = false;
  5375. t.state = null;
  5376. }
  5377. if (t.state == null){
  5378. t.win.document.body.innerHTML = '<STYLE>pre{margin:0px} hr{margin:3px; height:1px; border:0px; color:#cee; background-color:#cee}</style>\
  5379. <BODY style="margin:0px; padding:0px; border:none">\
  5380. <DIV id=winlogtop style="background-color:#d0d0d0; margin:0px; padding:0px; border:1px solid">\
  5381. <INPUT id=wlClear type=submit value="Clear"> &nbsp; <INPUT id=wlRev type=submit value="Bottom"></div>\
  5382. <DIV id=wlOut style="overflow-y:auto; height:100%; max-height:100%"></div></body>';
  5383. t.win.document.getElementById('wlClear').addEventListener('click', eventButClear, false);
  5384. t.win.document.getElementById('wlRev').addEventListener('click', eventButReverse, false);
  5385. t.eOut = t.win.document.getElementById('wlOut');
  5386. t.state = 1;
  5387. }
  5388. },
  5389. write : function (msg){
  5390. var t = WinLog;
  5391. if (!t.enabled || t.isOpening){
  5392. return;
  5393. }
  5394. t.open();
  5395. return;
  5396. var te = document.createElement('pre');
  5397. var now = new Date();
  5398. var m = [];
  5399. var millis = now.getMilliseconds();
  5400. m.push (now.toTimeString().substring (0,8));
  5401. m.push ('.');
  5402. if (millis<100)
  5403. m.push('0');
  5404. if (millis<10)
  5405. m.push('0');
  5406. m.push(millis);
  5407. m.push (': ');
  5408. m.push (msg);
  5409. te.innerHTML = m.join('');
  5410. if (t.reverse){
  5411. if (t.lastE == null){
  5412. t.eOut.appendChild(te);
  5413. t.lastE = te;
  5414. } else {
  5415. t.eOut.insertBefore(te, t.lastE);
  5416. }
  5417. var hr = document.createElement('hr');
  5418. t.eOut.insertBefore(hr, te);
  5419. t.lastE = hr;
  5420. } else {
  5421. t.eOut.appendChild(te);
  5422. t.eOut.appendChild(document.createElement('hr'));
  5423. }
  5424. },
  5425. };