// ==UserScript== // @name KOCAttack - Extra Features! // @version 0.7.6 // @namespace KOCAttack-Extra // @homepage http://userscripts.org/scripts/show/89473 // @description Same as the KOCAttack script from niknah (as of Oct. 24, 2010), but with some extra features. // @include *apps.facebook.com/kingdomsofcamelot* // @include *kingdomsofcamelot.com/*main_src.php* // @include *kingdomsofcamelot.com/*newgame_src.php* // @include *facebook.com/connect/uiserver.php* // @require http://sizzlemctwizzle.com/updater.php?id=89473 // ==/UserScript== // Override the default alert functionality of the web browser (which causes the script to pause) // Instead of displaying alert popups, messages will be displayed in the firefox console unsafeWindow.alert = function(message) { console.info("Javascript Alert: "+message); if(typeof(GM_log)=="function"){ GM_log("Javascript Alert: "+message); } } alert = unsafeWindow.alert; // String prototypes String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); } String.prototype.StripQuotes = function() { return this.replace(/"/g,''); }; /* // Array remove function (found at http://ejohn.org/blog/javascript-array-remove/) Examples: Remove the second item from the array: ArrayRemoveItem(array, 1); Remove the second-to-last item from the array: ArrayRemoveItem(array, -2); Remove the second and third items from the array: ArrayRemoveItem(array, 1,2); Remove the last and second-to-last items from the array: ArrayRemoveItem(array, -2,-1); */ ArrayRemoveItem = function(array, from, to) { var rest = array.slice((to || from) + 1 || array.length); array.length = from < 0 ? array.length + from : from; return array.push.apply(array, rest); }; if(!this.JSON2){JSON2={};} (function(){function f(n){return n<10?'0'+n:n;} if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return this.getUTCFullYear()+'-'+ f(this.getUTCMonth()+1)+'-'+ f(this.getUTCDate())+'T'+ f(this.getUTCHours())+':'+ f(this.getUTCMinutes())+':'+ f(this.getUTCSeconds())+'Z';};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};} 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+'"';} 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);} if(typeof rep==='function'){value=rep.call(holder,key,value);} 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';} 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';} v=partial.length===0?'[]':gap?'[\n'+gap+ partial.join(',\n'+gap)+'\n'+ mind+']':'['+partial.join(',')+']';gap=mind;return v;} 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);}}}} v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+ mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}} 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;} rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');} return str('',{'':value});};} 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];}}}} return reviver.call(holder,key,value);} cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\\u'+ ('0000'+a.charCodeAt(0).toString(16)).slice(-4);});} 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;} throw new SyntaxError('JSON.parse');};}})(); if(!this.GM_log) { GM_log=function(m) { console.log(m); } GM_registerMenuCommand=function(text,f) { } } if(!this.unsafeWindow) { //~~~ need helper to return values? unsafeWindow={}; } function inspect(obj, maxLevels, level){ var str = '', type, msg; // Start Input Validations // Don't touch, we start iterating at level zero if(level == null) level = 0; // At least you want to show the first level if(maxLevels == null) maxLevels = 1; if(maxLevels < 1) return '<font color="red">Error: Levels number must be > 0</font>'; // We start with a non null object if(obj == null) return '<font color="red">Error: Object <b>NULL</b></font>'; // End Input Validations // Each Iteration must be indented str += '<ul>'; // Start iterations for all objects in obj for(property in obj) { try { // Show "property" and "type property" type = typeof(obj[property]); str += '<li>(' + type + ') ' + property + ( (obj[property]==null)?(': <b>null</b>'):(': '+obj[property])) + '</li>'; // We keep iterating if this property is an Object, non null // and we are inside the required number of levels if((type == 'object') && (obj[property] != null) && (level+1 < maxLevels)) str += inspect(obj[property], maxLevels, level+1); } catch(err) { // Is there some properties in obj we can't access? Print it red. if(typeof(err) == 'string') msg = err; else if(err.message) msg = err.message; else if(err.description) msg = err.description; else msg = 'Unknown'; str += '<li><font color="red">(Error) ' + property + ': ' + msg +'</font></li>'; } } // Close indent str += '</ul>'; return str; } function MinDigits(num,digits) { while((""+num).length<digits) { num="0"+num; } return num; }; function SecsToStr(secs) { secs=Math.floor(secs); return Math.floor(secs/60/60/24%60)+ ":"+MinDigits(Math.floor(secs/60/60%60),2)+ ":"+MinDigits(Math.floor(secs/60%60),2); // ":"+MinDigits(Math.floor(secs%60),2); }; var nHtml={ FindByXPath:function(obj,xpath,nodetype) { if(!nodetype){ nodetype = XPathResult.FIRST_ORDERED_NODE_TYPE; } try { var q=document.evaluate(xpath,obj,null,nodetype,null); } catch(e) { GM_log('bad xpath:'+xpath); } if(nodetype == XPathResult.FIRST_ORDERED_NODE_TYPE){ if(q && q.singleNodeValue) { return q.singleNodeValue; } }else{ if(q){ return q; } } return null; }, ClickWin:function(win,obj,evtName) { var evt = win.document.createEvent("MouseEvents"); evt.initMouseEvent(evtName, true, true, win, 0, 0, 0, 0, 0, false, false, false, false, 0, null); return !obj.dispatchEvent(evt); }, Click:function(obj) { return this.ClickWin(window,obj,'click'); }, ClickTimeout:function(obj,millisec) { window.setTimeout(function() { return nHtml.ClickWin(window,obj,'click'); },millisec+Math.floor(Math.random()*500)); }, SetSelect:function(obj,v) { for(var o=0; o<obj.options.length; o++) { if(v==obj.options[o].value) { obj.options[o].selected=true; return true; } } return false; } }; function ById(id) { return document.getElementById(id); } function ByName(name) { return document.getElementsByName(name); } function AddText(box1,txt) { var txtObj; box1.appendChild(txtObj=document.createTextNode(txt)); return txtObj; } function AddHtml(box1,txt) { var txtObj; var sp=document.createElement('span'); sp.innerHTML=txt; box1.appendChild(sp); return txtObj; } var Seed = unsafeWindow.seed; var KOCAttack={ startListenTime:null, prevAttack:{'x':"350",'y':'350'}, options:null, iframeCommunicator:{}, isChrome:navigator.userAgent.toLowerCase().indexOf('chrome') > -1, valuesCache:{}, seed:{}, cselectedCity : {}, Cities : {}, currentPage:null, DoUnsafeWindow:function(func, execute_by_embed) { if(this.isChrome || execute_by_embed) { var scr=document.createElement('script'); scr.innerHTML=func; document.body.appendChild(scr); } else { try { eval("unsafeWindow."+func); } catch (error) { this.Log("A javascript error has occurred when executing a function via DoUnsafeWindow. Error description: "+error.description); } } }, GetSeed:function() { return unsafeWindow.seed; }, ReloadWindow:function() { //this.DoUnsafeWindow('window.location.href=window.location.href.toString().replace(/¤t_time=[0-9]*/i, "")+"¤t_time="+Math.round(new Date().getTime() / 1000);'); if(this.options.useAlternateReloadMethod){ setTimeout (function (){window.location.href=window.location.href.toString().replace(/¤t_time=[0-9]*/i, "")+"¤t_time="+Math.round(new Date().getTime() / 1000);}, 0); }else{ this.DoUnsafeWindow('window.location.reload(true);'); } }, ShowViewAttacksDialog:function() { var t=this; t.attacks=[]; var div=ById('KOCAttackViewAttacks'); if(!div) { div=document.createElement('div'); div.id='KOCAttackViewAttacks'; div.style.zIndex=100000; div.style.position='absolute'; div.style.left='8px'; div.style.top='8px'; div.style.backgroundColor='#fff'; div.style.border='3px solid #888'; div.style.padding='10px'; document.body.appendChild(div); } var cities=this.GetSeed().cities; //WinLog.write(inspect(cities)); var citysel ='<select id=srcCity>'; citysel += '<option value=All>All Cities</option>'; for(var c=0; c<cities.length; c++) { citysel += '<option value="'+cities[c][1]+'">'+cities[c][1]+'</option>'; } citysel += '</select>'; var levelsel ='<select id=srcLevel>'; levelsel += '<option value="All">All Levels</option>'; for(var c=1; c<=10; c++) { levelsel += '<option value="'+c+'">Level '+c+'</option>'; } levelsel += '</select>'; var typesel ='<select id=srcAttackType>'; typesel += '<option value="All">All</option>'; typesel += '<option value="normal">Attacks</option>'; typesel += '<option value="transport">Transports</option>'; typesel += '<option value="bulkadded">Bulk Adds</option>'; typesel += '</select>'; div.style.display='block'; div.innerHTML=''; var m = '<DIV id="srcAttackOpts" style="height:30px">\ <TABLE><TR valign=bottom><TD class=xtab width=100 align=center>Search for: </td><TD align=left>\ <SELECT id=srcAttack>\ <OPTION value=All>All</option>\ <OPTION value=Camp>Barb Camp</option>\ <OPTION value=Wilderness>Wilderness</option>\ <OPTION value=Grassland>Grassland</option>\ <OPTION value=Lake>Lake</option>\ <OPTION value=Mountains>Mountains</option>\ <OPTION value=Forest>Woods</option>\ <OPTION value=Hills>Hills</option>\ <OPTION value=Plain>Plains</option>\ <OPTION value=City>City</option>\ </select></td>\ <td class=xtab width=100 align=center>Select City: </td>\ <td align=left><span id=ptattackcity></span></td>\ <td class=xtab width=100 align=center>Select Level: </td>\ <td align=left><span id=ptattacklevel></span></td>\ <td class=xtab width=100 align=center>Select Type: </td>\ <td align=left><span id=ptattacktype></span></td></tr>\ </table></div>\ <a id="KOCAttackViewAttacksCancel" class="button20"><span>Cancel</span></a>\ <a id="KOCAttackViewAttacksList" class="button20"><span>List Attacks</span></a>\ <a id="KOCAttackViewAttacksClearList" class="button20"><span>Clear List</span></a>\ <a id="KOCAttackViewAttacksDelete" class="button20"><span>Delete Selected</span></a>\ <a id="KOCAttackViewAttacksIgnore" class="button20"><span>Ignore/UnIgnore</span></a>\ <br><br><DIV id="srcAttackResults" style="height:470px; max-height:470px; overflow-y:auto;"></div>\ '; var srcAttackResults = ById("srcAttackResults"); if (srcAttackResults != null){ ById('KOCAttackViewAttacksClearList').click(); } div.innerHTML = m; ById('ptattackcity').innerHTML = citysel; ById('ptattacklevel').innerHTML = levelsel; ById('ptattacktype').innerHTML = typesel; ById('KOCAttackViewAttacksClearList').addEventListener('click',function() { ById('srcAttackResults').innerHTML=''; },false); ById('KOCAttackViewAttacksCancel').addEventListener('click',function() { div.style.display='none'; },false); ById('KOCAttackViewAttacksList').addEventListener('click',function() { t.attacks=[]; t.DetailAttacks(); //WinLog.write(inspect(t.attacks,10)); var typeQuery = ById('srcAttackType').value; var cityQuery = ById('srcCity').value; var levelQuery = ById('srcLevel').value; var attackQuery = ById('srcAttack').value; var h = '<table>'; h += '<tr><td><input type=checkbox id=selAllAttacks></td><td> </td><td>City</td><td>Coords</td><td nowrap>What</td>'; h += '<td>Type</td><td>Attack Troops</td><td>Suicide Troops/Resources</td><td>Time</td><td>Ignore</td></tr>'; var tableRows= ''; var count = 1 for(var a=0; a<t.attacks.length; a++) { var levelInfo=t.GetLevelInfo(t.attacks[a]); if (levelInfo==undefined) levelInfo=''; var type; if (levelInfo.type){ type = levelInfo.type; } else { type = 'City'; } var displayRow = ''; if (cityQuery != 'All'){ if (t.GetCityName(t.attacks[a]['fromCity']) != cityQuery){ continue; } } if (levelQuery != 'All'){ if (levelInfo.level != levelQuery){ continue; } } if (typeQuery != 'All'){ if (t.attacks[a].currenttattackwavetype != typeQuery){ continue; } } if (attackQuery != 'All'){ if (type != attackQuery){ continue; } } tableRows += '<tr id=row'+count+' style="display: '+displayRow+';">'; tableRows += '<td><input type=checkbox id=sel'+count+'>'; tableRows += '<td>'+count+'</td><td>'+t.GetCityName(t.attacks[a]['fromCity'])+'</td>'; tableRows += '<td id=coords'+count+'>'+t.attacks[a].xy[0]+','+t.attacks[a].xy[1]+'</td>'; tableRows += '<td nowrap>'+type+' Level '+levelInfo.level+'</td>'; tableRows += '<td>'+t.attacks[a].currenttattackwavetype+'</td>'; tableRows += '<td>'; if(typeof(t.attacks[a].troops)=="object") { var troops=''; for(var i=1; i<t.attacks[a].troops.length; i++) { troops += t.attacks[a].troops[i]+','; } troops = troops.substring(0, troops.length - 1); tableRows += troops; } else{ tableRows += ' '; } tableRows += '</td>'; tableRows += '<td>'; if(typeof(t.attacks[a].suicidewave)=="object") { var suicide=''; for(var i=1; i<t.attacks[a].suicidewave.length; i++) { suicide += t.attacks[a].suicidewave[i]+','; } suicide = suicide.substring(0, suicide.length - 1); tableRows += suicide; } else if (typeof(t.attacks[a].resources)=="object"){ var resources=''; for(var i=1; i<t.attacks[a].resources.length; i++) { resources += t.attacks[a].resources[i]+','; } resources = resources.substring(0, resources.length - 1); tableRows += resources; } else { tableRows += ' '; } tableRows += '</td>'; var nowSecs=new Date().getTime()/1000; tableRows += '<td>'+SecsToStr(nowSecs-t.attacks[a].time)+'</td>'; var ignChecked = ''; if (t.attacks[a].ignore == null || t.attacks[a].ignore==undefined){ ignChecked = ''; }else{ ignChecked = 'CHECKED'; } tableRows += '<td><input type=checkbox name=chkIgnore id='+count+' '+ignChecked+'></td>'; tableRows += '</tr>'; count++; } h += tableRows + '</table>'; ById('srcAttackResults').innerHTML = h; ById('KOCAttackViewAttacksDelete').addEventListener('click',function() { for (var i=1; i<count; i++){ var row = 'sel'+i; if (ById(row) == undefined) continue; if (ById(row).checked == true){ //ById(row).checked == false; var c = ById('coords'+i).innerHTML; var xy = c.split(","); GM_log('Coords '+xy[0]+' '+xy[1]); t.DeleteAttack(xy[0],xy[1]); } } var listBtn=ById('KOCAttackViewAttacksList'); nHtml.Click(listBtn); },false); for (var i=1; i<count; i++){ var ignore = i; t.addEvent(ById(ignore), "click", t.ChangeIgnore); } ById('selAllAttacks').addEventListener('click',function() { var myChecked = true; if (ById('selAllAttacks').checked == false){ myChecked = false; } for (var i=1; i<count; i++){ var row = 'sel'+i; ById(row).checked=myChecked; } },false); },false); }, addEvent:function(obj, type, fn){ if (obj.attachEvent) { obj['e' + type + fn] = fn; obj[type + fn] = function(){obj['e' + type + fn](window.event);} obj.attachEvent('on' + type, obj[type + fn]); } else{ obj.addEventListener(type, fn, false); } }, ChangeIgnore:function(e){ var c = ById('coords'+e.target.id).innerHTML; var xy = c.split(","); var serverID; var m=/^[a-zA-Z]+([0-9]+)\./.exec(document.location.hostname); if(m) { ServerId = m[1]; } if(this.currentServerId<0){ ServerId = GM_getValue("KOCAttackLastKnownServerID",-1); } var attackname = 'attack_'+ServerId+'_'+xy[0]+','+xy[1]; var str = GM_getValue(attackname,'') if(!str) return null; attack= JSON2.parse(str); attack.ignore=e.target.checked?true:undefined; //WinLog.write (inspect(attack,10)); GM_setValue(attackname,JSON2.stringify(attack)); }, GetAttack:function(x,y) { var str=this.browser_getValue(this.GetAttackName(x,y),''); if(!str) return null; return JSON2.parse(str); }, GetCityName:function(cityid) { var cityName; for(var a=0; a<Seed.cities.length; a++) { if(Seed.cities[a][0] == cityid){ var cityName = Seed.cities[a][1]; } } return cityName; }, ShowOptionsDialog:function() { var div=ById('KOCAttackOptions'); if(!div) { div=document.createElement('div'); div.id='KOCAttackOptions'; div.style.zIndex=100000; div.style.position='absolute'; div.style.left='8px'; div.style.top='8px'; div.style.backgroundColor='#fff'; div.style.border='3px solid #888'; div.style.padding='10px'; document.body.appendChild(div); } var okCitiesHtml="<span onmousedown='return false; '>"; for(var c=1; c<=8; c++) { okCitiesHtml+= "<a style='font-size: 11px; padding: 2px; cursor: pointer; text-decoration: none' id='KOCAttackOkCities_"+c+"'>"+c+"</a> "; } okCitiesHtml+='</span>'; div.style.display='block'; div.innerHTML=''; this.options=this.GetOptions(); div.innerHTML="<form><table>"+ "<tr><td valign='top' align='center'><img src='img/units/unit_6_50.jpg' /></td><td valign='top'>"+ "Attack Order: <select id='KOCAttackOrder'><option value='mostTroops'>Use most troops first</option><option value='closest'>Closest targets first</option></select><br />"+ "Attack Type: <input type='checkbox' "+(this.options.attackTypeCamp?'checked':'')+" id='KOCAttackTypeCamp'>Camp "+ "<input type='checkbox' "+(this.options.attackTypeWild?'checked':'')+" id='KOCAttackTypeWild'>Wilderness "+ "<input type='checkbox' "+(this.options.attackTypeCity?'checked':'')+" id='KOCAttackTypeCity'>City "+ "<input type='checkbox' "+(this.options.attackTypeTransport?'checked':'')+" id='KOCAttackTypeTransport'>Transport<br> "+ "<br />"+ "<input id='KOCAttackDelay' value='"+this.options.attackDelay+"' size='3' /> seconds inbetween sending each attack<br />"+ "Time inbetween sending to the <u>same target</u>...<br />"+ "<div style='margin-left: 40px'>"+ "Attacking camp:<input id='KOCAttackHoursSinceLastCamp' value='"+(this.options.attackSecsSinceLastCamp/(60*60))+"' size='3' />hrs<br />"+ "Attacking wilderness:<input id='KOCAttackHoursSinceLastWild' value='"+(this.options.attackSecsSinceLastWild/(60*60))+"' size='3' />hrs<br />"+ " Attacking city:<input id='KOCAttackHoursSinceLastCity' value='"+(this.options.attackSecsSinceLastCity/(60*60))+"' size='3' />hrs<br />"+ " Transporting:<input id='KOCAttackMinsSinceLastTransport' value='"+(this.options.attackSecsSinceLastTransport/(60))+"' size='3' />mins"+ "</div>"+ "<br />"+ "<input id='KOCAttackMaxDistance' value='"+(this.options.attackMaxDistance)+"' size='3' /> max distance away from city to attack.<br />"+ "<input id='KOCAttackLockAttackFromCity' type='checkbox' "+(this.options.lockAttackFromCity?'checked':'')+" /> Only launch attacks from city they were first launched from.<br />"+ "<br />"+ "<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 />"+ "Open up this url in a tab when we're under attack...<br /><input id='KOCAttackImpendingAttackUrl' size='60' value='"+(this.options.impendingAttackUrl)+"' /><br />"+ "</td></tr>"+ //http://cdn1.kingdomsofcamelot.com/fb/e2/src/img/units/unit_6_50.jpg?6545 "<tr><td valign='top' align='center'><img src='img/chrome_message_up.png' /></td><td valign='top'>"+ "<input id='KOCAttackRemoveReports' type='checkbox' "+(this.options.autoRemoveReports?'checked':'')+" /> Auto remove barbarian/wilderness attack reports.<br />"+ "<input id='KOCAttackKeepReports' value='"+this.options.keepReports+"' size='3' /> attack reports to keep maximum in the attack dialog.<br />"+ "<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 />"+ "</td></tr>"+ "<tr><td valign='top' align='center'><img src='img/happiness.png' /></td><td valign='top'>"+ "<input id='KOCAttackPercentOfPopToTrain' value='"+this.options.percentOfPopToTrain+"' size='3' />% of idle population available before we do auto training.<br />"+ "<input id='KOCAttackAutoGoldHappiness' value='"+this.options.autoGoldHappiness+"' size='3' />% happiness before we click auto gold.<br />"+ "</td></tr>"+ "<tr><td valign='top' align='center'><img src='img/chome_alliance_up.png' /></td><td valign='top'>"+ "<input id='KOCAttackDisableInviteFriends' type='checkbox' "+(this.options.disableInviteFriends?'checked':'')+" /> Disable the annoying \"Invite Friends\" popup dialog in-game.<br />"+ "<input id='KOCAttackAutoHelpAlliance' type='checkbox' "+(this.options.autoHelpAlliance?'checked':'')+" /> Automatically help alliance members with building/researching.<br />"+ "<input id='KOCAttackHideAllianceHelpRequests' type='checkbox' "+(this.options.hideAllianceHelpRequests?'checked':'')+" /> Hide alliance help requests/reports in chat (if above is checked, then after helping).<br />"+ "<input id='KOCAttackAutoPublishGamePopups' type='checkbox' "+(this.options.autoPublishGamePopups?'checked':'')+" /> Automatically publish game popups (such as help requests) to facebook wall.<br />"+ "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 />"+ "</td></tr>"+ "</td></tr>"+ "<tr><td valign='top' align='center'><img src='img/gems.png' /></td><td valign='top'>"+ "<input id='KOCAttackAutoLogBackIn' type='checkbox' "+(this.options.autoLogBackIn?'checked':'')+" /> Automatically log back into domain if disconnected due to maintenance or server down-time.<br />"+ "<input id='KOCAttackUseAlternateReload' type='checkbox' "+(this.options.useAlternateReloadMethod?'checked':'')+" /> Use alternate reload method (potentially useful if you keep getting the \"To display this page, Firefox must send information that will repeat any action\" error message).<br />"+ "<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 />"+ "</td></tr>"+ "<tr><td valign='top' align='center'><img src='img/buildings/castle_lvl10.png' /></td><td valign='top'>"+ "<input id='KOCAttackChangeCitySecs' value='"+(this.options.changeCitySecs)+"' size='3' /> seconds inbetween changing cities.<br />"+ "Cycle thru all the cities <input id='KOCAttackCitiesDoneMax' value='"+(this.options.autoAttackCitiesDoneMax)+"' size='3' /> times and then wait "+ "<input id='KOCAttackCitiesDelay' value='"+this.options.waitAfterCitiesDone+"' size='3' />secs before refreshing.<br />"+ "Cities to attack from: "+okCitiesHtml+'<br />'+ "<tr><td valign='top' align='center'></td><td valign='top'>"+ "<input id='KOCAttackRandom' value='"+this.options.randomPercent+"' size='3' />% random adjustment for all delays (to look more human).<br />"+ "Import/Export: Paste or copy the settings here...<br /><textarea id='KOCAttackImport'></textarea>"+ "<a class='button20' id='KOCAttackImportButton'><span>Import</span></a> <a class='button20' id='KOCAttackExportButton'><span>Export</span></a><br />"+ "</td></tr>"+ "</table>"+ "<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> <a id='KOCAttackDeleteAllStoredAttacks' class='button20'><span>Delete all stored attacks</span></a><a id='KOCAttackDeleteTransports' class='button20'><span>Delete transports</span></a><a id='KOCAttackListAttacks' class='button20'><span>List attacks</span></a><a id='KOCAttackListTransports' class='button20'><span>List transports</span></a></form>"; var t=this; var importText=ById('KOCAttackImport'); importText.addEventListener('focus',function() { importText.select(); },false); ById('KOCAttackImportButton').addEventListener('click',function() { if(importText.value=="") return; t.ImportAllFromJSON(importText.value); },false); ById('KOCAttackExportButton').addEventListener('click',function() { GM_log("In Event Listen"); importText.value=t.ExportAllToJSON(); },false); nHtml.SetSelect(ById('KOCAttackOrder'),this.options.attackOrder); ById('KOCAttackOptionsCancel').addEventListener('click',function() { div.style.display='none'; },false); ById('KOCAttackOptionsReset').addEventListener('click',function() { t.ClearOptions(); this.options=t.GetOptions(); div.style.display='none'; },false); ById('KOCAttackOptionsResetAll').addEventListener('click',function() { t.FactoryReset(); //window.location.reload(true); t.ReloadWindow(); },false); ById('KOCAttackDeleteAllStoredAttacks').addEventListener('click',function() { t.DeleteAllStoredAttacks(); //window.location.reload(true); t.ReloadWindow(); },false); ById('KOCAttackDeleteTransports').addEventListener('click',function() { t.DeleteTransports(); //window.location.reload(true); t.ReloadWindow(); },false); ById('KOCAttackListTransports').addEventListener('click',function() { t.ListTransports(); //window.location.reload(true); },false); ById('KOCAttackListAttacks').addEventListener('click',function() { t.ListAttacks(); //window.location.reload(true); },false); nHtml.SetSelect(ById('KOCAttackAutoPublishPrivacy'),this.options.autoPublishPrivacySetting); for(var c=1; c<=8; c++) { var sp=ById('KOCAttackOkCities_'+c); var SetCity=function(target,set) { target.style.border=set?'2px solid #080':''; target.style.margin=set?'2px':'4px'; }; sp.addEventListener('click',function(evt) { SetCity(evt.target,evt.target.style.border==''?true:false); },false); //sp.onmousedown=function() { return false; } SetCity(sp,t.options.okCities[c]); } ById('KOCAttackOptionsSave').addEventListener('click',function() { t.options.attackTypeCamp=ById('KOCAttackTypeCamp').checked; t.options.attackTypeCity=ById('KOCAttackTypeCity').checked; t.options.attackTypeWild=ById('KOCAttackTypeWild').checked; t.options.attackTypeTransport=ById('KOCAttackTypeTransport').checked; t.options.attackDelay=parseInt(ById('KOCAttackDelay').value); t.options.waitAfterCitiesDone=parseInt(ById('KOCAttackCitiesDelay').value); t.options.keepReports=parseInt(ById('KOCAttackKeepReports').value); t.options.changeCitySecs=parseInt(ById('KOCAttackChangeCitySecs').value); t.options.autoGoldHappiness=parseInt(ById('KOCAttackAutoGoldHappiness').value); t.options.percentOfPopToTrain=parseFloat(ById('KOCAttackPercentOfPopToTrain').value); var prev_disableInviteFriends = t.options.disableInviteFriends; t.options.disableInviteFriends=ById('KOCAttackDisableInviteFriends').checked; if(prev_disableInviteFriends != t.options.disableInviteFriends){ 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!"); } t.options.autoHelpAlliance=ById('KOCAttackAutoHelpAlliance').checked; t.options.hideAllianceHelpRequests=ById('KOCAttackHideAllianceHelpRequests').checked; t.options.autoPublishGamePopups=ById('KOCAttackAutoPublishGamePopups').checked; t.options.autoPublishPrivacySetting=ById('KOCAttackAutoPublishPrivacy').value; t.options.autoLogBackIn=ById('KOCAttackAutoLogBackIn').checked; t.options.useAlternateReloadMethod=ById('KOCAttackUseAlternateReload').checked; t.options.enableLogging=ById('KOCAttackEnableLogging').checked; t.options.attackSecsSinceLastCamp=parseFloat(ById('KOCAttackHoursSinceLastCamp').value)*60*60; t.options.attackSecsSinceLastWild=parseFloat(ById('KOCAttackHoursSinceLastWild').value)*60*60; t.options.attackSecsSinceLastCity=parseFloat(ById('KOCAttackHoursSinceLastCity').value)*60*60; t.options.attackSecsSinceLastTransport=parseFloat(ById('KOCAttackMinsSinceLastTransport').value)*60; t.options.randomPercent=parseFloat(ById('KOCAttackRandom').value); t.options.attackMaxDistance=parseFloat(ById('KOCAttackMaxDistance').value); t.options.autoAttackCitiesDoneMax=parseInt(ById('KOCAttackCitiesDoneMax').value); t.options.attackOrder=ById('KOCAttackOrder').value; t.options.lockAttackFromCity=ById('KOCAttackLockAttackFromCity').checked; t.options.autoRemoveReports=ById('KOCAttackRemoveReports').checked; t.options.retryMarch=ById('KOCAttackRetryMarch').checked; t.options.impendingAttackUrl=ById('KOCAttackImpendingAttackUrl').value; t.options.noViewReports=ById('KOCAttackNoViewReports').checked; for(var c=1; c<=8; c++) { var okcity=ById('KOCAttackOkCities_'+c); t.options.okCities[c]=okcity.style.border!=""?true:false; } t.SetOptions(t.options); div.style.display='none'; },false); }, AddOptionsLink:function() { var t=this; var a=ById('KOCAttackOptionsLink'); if(a) return; a=this.AddTabLink('Options'); if(!a) { window.setTimeout(function() { t.AddOptionsLink(); },t.GetRandTime(250)); return; } a.id='KOCAttackOptionsLink'; a.addEventListener('click',function() { t.ShowOptionsDialog(); },false); }, AddViewAttacksLink:function() { var t=this; var a=ById('KOCAttackViewAttacksLink'); if(a) return; a=this.AddTabLink('View Attacks'); if(!a) { window.setTimeout(function() { t.AddViewAttacksLink(); },t.GetRandTime(250)); return; } a.id='KOCAttackViewAttacksLink'; a.addEventListener('click',function() { t.ShowViewAttacksDialog(); },false); }, AddTabLink:function(html) { // Resize main tab bar container var tab_container = ById("main_engagement_tabs"); tab_container.style.width = "715px"; // Create new tab var a=document.createElement('a'); a.className='tab'; a.style.color='#fff'; a.innerHTML='<span>'+html+'</span>'; var tabs=ById('KOCAttackTabs'); if(!tabs) { var ptabs=ById('main_engagement_tabs'); if(!ptabs) { ptabs=ById('topnav_msg'); if(ptabs)ptabs=ptabs.parentNode; } if(!ptabs) { ptabs=document.body; } tabs=document.createElement('span'); tabs.id='KOCAttackTabs'; ptabs.insertBefore(tabs,ptabs.childNodes[0]); } if(tabs) { tabs.style.whiteSpace='nowrap'; tabs.style.width='1600px'; tabs.appendChild(a); return a; } return null; }, ToggleAutoAttack:function() { var t=this; var a=t.GetAutoAttack(); if(!a) { t.SetAutoAttack({'barbarian':true,'cities':{}}); t.RestartAutoAttack(); } else { t.ClearAutoAttackTimeout(); t.SetAutoAttack(null); } /* // toggle for this city, if(!a.cities) a.cities={}; var city=t.GetCurrentCityId(); a.cities[city]=a.cities[city]?undefined:true; var attackCities=0; for(city in a.cities) { attackCities++; } if(attackCities==0) { t.ClearAutoAttackTimeout(); t.SetAutoAttack(null); } */ t.SetAttackStatusMessage(); }, SetAttackStatusMessage:function() { //var mess=this.GetStatusMessage(); var toggle=ById('KOCAttackToggle'); if(!toggle) { var t=this; toggle=this.AddTabLink('Auto Attack'); if(!toggle) { window.setTimeout(function() { t.SetAttackStatusMessage(); },t.GetRandTime(250)); return; } toggle.id='KOCAttackToggle'; toggle.addEventListener('click',function() { t.ToggleAutoAttack(); },false); } var autoAttack=this.GetAutoAttack(); // if(autoAttack && autoAttack.cities && autoAttack.cities[t.GetCurrentCityId()]) { if(autoAttack) { toggle.innerHTML='<span>Auto Attack - On</span>'; } else { toggle.innerHTML='<span>Auto Attack - Off</span>'; } }, SetStatusMessage:function(str) { var mess=this.GetStatusMessage(); var txt=ById('KOCAttackMessage'); if(!txt) { txt=document.createElement('span'); mess.appendChild(txt); } txt.innerHTML=str; }, GetStatusMessage:function() { var mess=ById('KOCAttackStatus'); if(!mess) { var timeHead=ById('kochead_time'); mess=document.createElement('span'); mess.id='KOCAttackStatus'; timeHead.parentNode.appendChild(mess); } return mess; }, Log:function(str) { if(this.options.enableLogging){ str=this.GetServerId()+":"+str; GM_log(str); } }, currentServerId:-1, GetServerId:function() { var m=/^[a-zA-Z]+([0-9]+)\./.exec(document.location.hostname); if(m) { this.currentServerId = m[1]; } // Attempt to pull current server id from greasemonkey cache for cross-domain calls if(this.currentServerId<0){ this.currentServerId = GM_getValue("KOCAttackLastKnownServerID",-1); } return this.currentServerId; }, GetValue:function(prefix,def) { var n=prefix+'_'+this.GetServerId(); return this.browser_getValue(n,def); }, SetValue:function(prefix,val) { var n=prefix+'_'+this.GetServerId(); this.browser_setValue(n,val); }, GetValuesCache:function(doneFunc) { if(!this.isChrome) { if(doneFunc) { doneFunc.call(this); } return; } /* var t=this; chrome.extension.sendRequest({func:"get","n":'KOCAttack'}, function(response) { //~~~ this.valuesCache=JSON2.parse(unescape(response.v)); if(doneFunc) { doneFunc.call(t); } }); return def; */ var idx=0; var cookie='kocattack'; var doccookie=document.cookie; while(true) { var i=doccookie.indexOf(cookie+'=',idx); if(i<0) { this.valuesCache={}; return; } idx=i+cookie.length+1; var ch=doccookie.substring(i-1,i); if(i==0 || ch==';' || ch==' ' || ch=='=') { break; } } var idxEnd=doccookie.indexOf(";",idx); if(idxEnd<0) { idxEnd=doccookie.length; } var cookieVal=doccookie.substring(idx,idxEnd); this.valuesCache=JSON2.parse(unescape(cookieVal)); }, SetValuesCache:function() { if(!this.isChrome) return; document.cookie='kocattack='+escape(JSON2.stringify(this.valuesCache))+'; expires='+ (new Date(new Date().getTime()+(60*60*24*365*5)).toGMTString() ); }, browser_listValues:function() { if(this.isChrome) { var ns=[]; for(var n in this.valuesCache) { ns.push(n); } return ns; } return GM_listValues(); }, browser_getValue:function(n,def) { if(this.isChrome) { if(this.valuesCache==null) { this.GetValuesCache(); } if(this.valuesCache[n]==undefined) { return def; } return this.valuesCache[n]; } return GM_getValue(n,def); }, browser_setValue:function(n,val) { if(this.isChrome) { this.valuesCache[n]=val; return; } if(val==null || val==undefined) { GM_deleteValue(n); } else { GM_setValue(n,val); } }, GetMinHours:function() { var m=this.GetValue('MinHours',1); if(m=="" || m==undefined) m=1; return m; }, SetMinHours:function(val) { this.SetValue('MinHours',val); }, ClearOptions:function() { this.SetValue('Options',JSON.stringify({})); }, GetOptions:function() { var json=this.GetValue('Options','{}'); if(json=='') json='{}'; var options=JSON2.parse(json); var defOptions={"attackDelay":15, "attackTypeCamp":true, "attackOrder":"closest", "autoRemoveReports":true, "attackSecsSinceLastCity":60*60*12, "attackSecsSinceLastCamp":3600, "attackSecsSinceLastWild":3600, "attackSecsSinceLastTransport":60, "randomPercent":10, "keepReports":10, "attackMaxDistance":60, "lockAttackFromCity":true, "waitAfterCitiesDone":20, "autoAttackCitiesDoneMax":2, "changeCitySecs":20, "retryMarch":true, "noViewReports":false, "chromeKeepReports":2, "percentOfPopToTrain":75, "autoGoldHappiness":99, "disableInviteFriends":true, "autoHelpAlliance":true, "hideAllianceHelpRequests":false, "autoPublishGamePopups":false, "autoPublishPrivacySetting":"80", "autoLogBackIn":true, "useAlternateReloadMethod":false, "enableLogging":false, "okCities":[1,1,1,1,1,1,1,1,1,1], 'impendingAttackUrl':''}; for(var n in defOptions) { if(options[n]!=undefined) { continue; } options[n]=defOptions[n]; } return options; }, SetOptions:function(v) { this.SetValue('Options',JSON2.stringify(v)); }, ClearCrossIframeCommands:function() { this.SetValue('CrossIframeCommands',JSON.stringify({})); }, GetCrossIframeCommands:function() { var json=this.GetValue('CrossIframeCommands','{}'); if(json=='') json='{}'; var commands=JSON2.parse(json); if(!commands.queue || commands.queue instanceof Array !== true){ commands.queue = new Array(); } return commands; }, SetCrossIframeCommands:function(v) { this.SetValue('CrossIframeCommands',JSON2.stringify(v)); }, AddCrossIframeCommand:function(pageName, functionCall, functionParameters) { var command = {}; command.pageName = pageName; command.functionCall = functionCall; var commands = this.GetCrossIframeCommands(); commands.queue.push(command); this.SetCrossIframeCommands(commands); }, GetAttackName:function(x,y) { return 'attack_'+this.GetServerId()+'_'+x+','+y; }, SetAttack:function(x,y,attack) { this.browser_setValue(this.GetAttackName(x,y), JSON2.stringify(attack)); }, GetAttack:function(x,y) { var str=this.browser_getValue(this.GetAttackName(x,y),''); if(!str) return null; return JSON2.parse(str); }, DeleteAttack:function(x,y) { var str=this.browser_getValue(this.GetAttackName(x,y),''); if(!str) return; GM_deleteValue(this.GetAttackName(x,y)); }, isSuicideAttackDefinedAtLocation:function(x,y) { var attack=this.GetAttack(x,y); if(!attack){ return false; } if(attack.suicidewave) { return true; } if(attack.a && attack.a.suicidewave){ return true; } return false; }, IsFirstAttackAtLocation:function(x,y) { if(this.prevAttack.x && this.prevAttack.y){ if(this.prevAttack.x==x && this.prevAttack.y==y) { this.Log("Previous attack matches current attack. This is not first attack!"); return false; } } var attack=this.GetAttack(x,y); if(!attack){ this.Log("Previous attack not defined. This is first attack!"); return true; } if(attack.a) { attack = attack.a; } if(!attack.suicidewavetime || !attack.time){ this.Log("Suicide wave time: "+attack.suicidewavetime+". Attack time: "+attack.time+". This is first attack!"); return true; } var nowSecs=new Date().getTime()/1000; // If the suicide attack was launched before the attack time allowed beween the same // camp/wilderness/city/transport, and the normal attack was launched *after* the suicide attack, // then we can safely re-launch the suicide attack by pretending that this is the "First Attack" again. var attackDelay=this.GetAttackDelay(attack); //this.Log("Attack Delay for ("+x+","+y+"): "+attackDelay); if( attack.suicidewavetime <= (nowSecs-(this.options.attackDelay+attackDelay)) && attack.time > attack.suicidewavetime && attack.time < nowSecs-attackDelay){ this.Log("Suicide wave attack timer expired. This is first attack!"); return true; } return false; //if(!this.prevAttack) return true; //return ((this.prevAttack.x==x && this.prevAttack.y==y)?false:true); }, GetCommandHistory:function(history_log_name) { if(!history_log_name){ var history_log_name = "default"; } var json=this.GetValue('PreviousCommandHistory_'+history_log_name,'{}'); if(json=='') json='{}'; var json_object=JSON2.parse(json); if(!json_object['items']){ json_object['items'] = Array(); } return json_object; }, AddToCommandHistory:function(command_string, history_log_name, log_length_limit) { if(!command_string){ return false; } if(!history_log_name){ var history_log_name = "default"; } // Default to a history length of 20 commands if(!log_length_limit){ var log_length_limit = 20; } // Get the previous history of commands var previous_commands = this.GetCommandHistory(history_log_name); var items = previous_commands['items']; // Add the new command items.push(command_string); // Limit the history length if(items.length>log_length_limit){ items = items.slice(items.length-log_length_limit); } previous_commands['items'] = items; this.SetValue('PreviousCommandHistory_'+history_log_name,JSON2.stringify(previous_commands)); }, FindInCommandHistory:function(command_string, history_log_name) { if(!command_string){ return false; } if(!history_log_name){ var history_log_name = "default"; } // Get the previous history of commands var previous_commands = this.GetCommandHistory(history_log_name); var items = previous_commands['items']; for(var i=0; i<items.length; i++){ if(items[i] == command_string){ return true; } } return false; }, GetGuiCoords:function() { var x=ById('modal_attack_target_coords_x'); var y=ById('modal_attack_target_coords_y'); if(!x || !y) { this.Log("Cannot find gui coords"); return null; } return [x.value,y.value]; }, SetAttackFromGui:function(box) { var xy=this.GetGuiCoords(); if(!xy) return null; return this.SetAttackFromGuiXY(xy[0],xy[1],box); }, AttackLastSentTime:0, UpdateAttackLastSentTime:function(){ this.AttackLastSentTime = new Date().getTime()/1000; this.SetValue('AttackLastSentTime',this.AttackLastSentTime); }, SendingMultipleWaves:false, IsCurrentlySendingMultipleWaves:function() { if(this.AttackLastSentTime == 0){ this.AttackLastSentTime = this.GetValue('AttackLastSentTime',0); } var nowSecs = new Date().getTime()/1000; var waveTimerDelay = this.options.attackDelay*2; var timeDifference = nowSecs-this.AttackLastSentTime; //this.Log("nowSecs: "+nowSecs+" waveTimerDelay: "+waveTimerDelay+" timeDifference: "+timeDifference+" SendingMultipleWaves: "+this.SendingMultipleWaves); // If the last attack was sent at a time ago that is more than twice the attack delay, // then we assume something failed and we reset the multiple wave tracker so everything can continue. if(timeDifference > waveTimerDelay && this.SendingMultipleWaves==true){ this.SendingMultipleWaves=false; this.Log("Multiple wave timer \("+waveTimerDelay+"\ seconds) has expired. Last known attack was sent "+timeDifference+" seconds ago. Resetting timer and continuing..."); } return this.SendingMultipleWaves; }, SetAttackFromGuiXY:function(x,y,box,isSuicideWave) { if(!isSuicideWave){ var isSuicideWave = false; } var troops=[]; var totalTroops=0; for(var tr=0; tr<100; tr++) { var troop=ById('modal_attack_unit_ipt'+tr); if(!troop) continue; try { var v=parseInt(troop.value); troops[tr]=v; totalTroops+=v; } catch(e) { continue; } } var comment=ById('KocAttackComment'); var type=ById('modal_attack_atktype'); if(!type) { throw("Cannot find attack type"); } if(totalTroops<=0) { this.Log("No troops, not saving attack"); return null; } // ignore anything other than attack if(type.selectedIndex==0) { var attack=this.GetAttack(x,y); if(!attack) attack={}; attack.type=type.selectedIndex; if(comment){ attack.comment=comment.value; } var nowSecs=new Date().getTime()/1000; var SuicideAttackDefined=this.isSuicideAttackDefinedAtLocation(x,y); var firstAttack=this.IsFirstAttackAtLocation(x,y); this.Log("First attack?: "+firstAttack); this.Log("Suicide attack defined? : "+SuicideAttackDefined); if(totalTroops>0 && (((troops[1]+troops[2]+troops[10])==totalTroops && firstAttack) || isSuicideWave)) { if(totalTroops>0 && ((troops[1]+troops[2]+troops[10])==totalTroops && firstAttack)){ this.Log("Suicide attack determined by troop type and by first attack"); }else if(isSuicideWave){ this.Log("Suicide attack determined by checkbox"); } // nothing but supply troops and/or militiamen and/or ballista. This must be an anti-defense suicide wave attack this.Log("Suicide wave :"+troops); attack.suicidewave=troops; attack.currenttattackwavetype = "suicide"; attack.suicidewavetime = nowSecs; this.SendingMultipleWaves = true; } else { this.Log("Normal wave :"+troops); attack.time=nowSecs; if(firstAttack) { attack.suicidewave=undefined; } attack.currenttattackwavetype = "normal"; attack.troops=troops; this.SendingMultipleWaves = false; } //if (this.options.lockAttackFromCity) { attack.fromCity=this.GetCurrentCityId(); //} //attack.ignore=undefined; this.prevAttack={'x':x,'y':y}; this.SetAttack(x,y,attack); return attack; } else if(type.selectedIndex==1) { // try to parse transports var attack=this.GetAttack(x,y); if(!attack) attack={}; attack.type=type.selectedIndex; //attack.ignore=true; // We set this to ignore for now until I can get the auto attack working if(comment) attack.comment=comment.value; var nowSecs=new Date().getTime()/1000; var SuicideAttackDefined=this.isSuicideAttackDefinedAtLocation(x,y); attack.time=nowSecs; attack.troops=troops; var resources=[]; var resourceTypes = new Array( 'gold', 'rec1', 'rec2', 'rec3', 'rec4' ); for(var res=0; res<resourceTypes.length; res++) { var resource=ById('modal_attack_'+resourceTypes[res]); if(!resource) continue; try { var v=parseInt(resource.value); resources[res]=v; totalResources+=v; } catch(e) { continue; } } attack.resources=resources; //if (this.options.lockAttackFromCity) { attack.fromCity=this.GetCurrentCityId(); //} //attack.ignore=undefined; attack.currenttattackwavetype = "transport"; this.prevAttack={'x':x,'y':y}; this.SetAttack(x,y,attack); return attack; } else { // Reset it this.prevAttack={'x':"350",'y':'350'}; } return null; }, ToggleCurrenttAttackWaveType:function(x,y,manual_setting) { var original_attack = this.GetAttack(x,y); if(original_attack) { var attack = original_attack; if(original_attack.a){ attack = original_attack.a; } var previousattackwavetype = 'undefined'; if(attack){ //this.Log("Inspecting attack: "+inspect(attack,10)); if(attack.currenttattackwavetype){ previousattackwavetype = attack.currenttattackwavetype; } if(manual_setting){ attack.currenttattackwavetype = manual_setting; }else if(attack.suicidewave && attack.currenttattackwavetype == "bulkadded"){ attack.currenttattackwavetype = "suicide"; }else{ // Toggle back and forth if(attack.suicidewave && attack.currenttattackwavetype == "normal"){ attack.currenttattackwavetype = "suicide"; }else{ attack.currenttattackwavetype = "normal"; } } this.Log("Toggling attack for ("+x+", "+y+") from "+previousattackwavetype+" to "+attack.currenttattackwavetype); if(original_attack.a){ original_attack.a = attack; attack = original_attack; } this.SetAttack(x,y,attack); return attack.currenttattackwavetype; }else{ return false; } }else{ return false; } }, BulkAddCoords:function(box,coordsText,force,locationType,isSuicideWave) { if(!locationType){ var locationType = "Camp"; } if(!isSuicideWave){ var isSuicideWave = false; } var coordRows=coordsText.split("\n"); var added=0; for(var r=0; r<coordRows.length; r++) { var row=coordRows[r]; var m=/^\s*([0-9]+)\s*,\s*([0-9]+)/.exec(row); if(!m) { m=/^\s*([0-9]+)\s+([0-9]+)/.exec(row); if(!m) continue; } var x=m[1]; var y=m[2]; var attack=this.GetAttack(x,y); var currenttattackwavetype = "bulkadded"; var SuicideAttackDefined=this.isSuicideAttackDefinedAtLocation(x,y); var previous_suicidewave = undefined; if(attack && (SuicideAttackDefined || isSuicideWave)){ previous_suicidewave = attack.suicidewave; } if(attack && !force) { if(SuicideAttackDefined && isSuicideWave==true){ this.Log('Suicide wave for '+x+','+y+' has already been added. Try over-writing it.'); continue; }else if(attack.troops){ this.Log('Attack wave for '+x+','+y+' has already been added. Try over-writing it.'); continue; } } var attack=this.SetAttackFromGuiXY(x,y,box,isSuicideWave); if(attack) { attack.levelInfo={'type':locationType,'level':0}; attack.fromCity=this.GetCurrentCityId(); var nowSecs=new Date().getTime()/1000; var monthAgo=nowSecs-(60*60*24*31); attack.time=monthAgo; if(SuicideAttackDefined || isSuicideWave || previous_suicidewave){ // set up suicide wave before attack time, according to "seconds in between sending each attack" attack.suicidewavetime = attack.time - this.options.attackDelay; if(previous_suicidewave && (!SuicideAttackDefined || !isSuicideWave)){ this.Log("Previous suicide wave for this attack was over-written by new attack. Merging and restoring..."); attack.suicidewave = previous_suicidewave; } } attack.ignore=undefined; attack.currenttattackwavetype=currenttattackwavetype; this.SetAttack(x,y,attack); this.Log(x+','+y+' attack added: '+inspect(attack)); this.Log("current attack wave type: "+attack.currenttattackwavetype); added++; } } // Redraw attacks on map listing this.DrawClosestFarms(); // done return added; }, BulkAddAttackLink:function(box) { var div=ById('BulkAddAttackDiv'); var t=this; if(!div) { div=document.createElement('div'); div.id='BulkAddAttackDiv'; div.style.display='inline'; } div.innerHTML=''; var bulkAddDiv=document.createElement('div'); bulkAddDiv.style.display='none'; AddHtml(bulkAddDiv,"<hr />"); 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' /> Overwrite existing attack if one already exists<br />"); // radio boxes for defining bulk coordinate type AddHtml(bulkAddDiv,"<hr />"); AddHtml(bulkAddDiv,"Type of Locations (All coordinates must match this type):<br />"); var arrData = [["Camp", "Camps"],["Wilderness", "Wildernesses"]]; for (var i=0; i < arrData.length; i++){ var objRadItem = document.createElement("input"); objRadItem.type = "radio"; objRadItem.name = "KOCAttackBulkAddLocationType"; objRadItem.id = "KOCAttackBulkAddLocationType_" + arrData[i][0]; objRadItem.value = arrData[i][0]; if(i == 0) {objRadItem.defaultChecked = true; objRadItem.checked = true; }; var objTextNode = document.createTextNode(" " + arrData[i][1]); var objLabel = document.createElement("label"); objLabel.htmlFor = objRadItem.id; objLabel.appendChild(objRadItem); objLabel.appendChild(objTextNode); bulkAddDiv.appendChild(objLabel); AddHtml(bulkAddDiv," "); }; AddHtml(bulkAddDiv,"<hr />"); AddHtml(bulkAddDiv,"<input id='KOCAttackBulkAddSuicideWave' type='checkbox' onClick='javascript:document.getElementById(\"KOCAttackBulkAddLocationType_Wilderness\").checked=true;' /> This is an initial suicide wave to wipe out traps on a wilderness.<br />"); AddHtml(bulkAddDiv,"<hr />"); var coords=document.createElement('textarea'); coords.wrap='off'; coords.style.whiteSpace='nowrap'; coords.cols=10; coords.rows=8; bulkAddDiv.appendChild(coords); AddHtml(bulkAddDiv,"<br />"); var bulkAdd=document.createElement('a'); bulkAdd.className='buttonDown20'; bulkAdd.innerHTML='<span>Bulk Add</span>'; bulkAddDiv.appendChild(bulkAdd); bulkAdd.addEventListener('click',function() { // Determine location type var locationType = "Camp"; // Default value var locationTypeRadioBoxes = ByName('KOCAttackBulkAddLocationType'); for(var i = 0; i < locationTypeRadioBoxes.length; i++) { if(locationTypeRadioBoxes[i].checked) { locationType = locationTypeRadioBoxes[i].value; break; } } // Determine attack wave type var isSuicideWave = ById('KOCAttackBulkAddSuicideWave').checked; // Add the coordinates var added=t.BulkAddCoords(box,coords.value,ById('KOCAttackBulkAddForce').checked,locationType,isSuicideWave); bulkAddDiv.style.display='none'; bulkAddAttackLink.style.display='inline'; window.alert('Bulk added '+added+' coords'); },false); AddHtml(bulkAddDiv,"<br />"); var bulkAddAttackLink=document.createElement('a'); bulkAddAttackLink.className='buttonDown20'; bulkAddAttackLink.innerHTML='<span>Bulk add coords</span>'; bulkAddAttackLink.addEventListener('click',function() { bulkAddDiv.style.display='inline'; bulkAddAttackLink.style.display='none'; },false); div.appendChild(bulkAddDiv); div.appendChild(bulkAddAttackLink); return div; }, HideAttackEfforts:function() { var items=ById('modal_attack_items'); if(!items) return; var type=ById('modal_attack_atktype'); if(!type) { throw("Cannot find attack type"); } //items=items.parentNode.parentNode; var a=document.createElement('a'); a.innerHTML='Hide/Show attack efforts'; //a.href='javascript:;'; a.style.cursor='pointer'; items.style.display='none'; a.addEventListener('click',function() { items.style.display=items.style.display=='none'?'block':'none'; },false); return a; }, SetResourceInput:function(num,resourceCount) { var resource=ById('modal_attack_'+num); if(!resource) return null; resource.value=resourceCount; resource.style.backgroundColor=''; // send a shift key so that it recalculates var evt = document.createEvent("KeyboardEvent"); if(evt.initKeyboardEvent) { evt.initKeyboardEvent("keyup",true,true,null,false,false,false,false,0x10,0); } else { evt.initKeyEvent("keyup",true,true,null,false,false,false,false,0x10,0); } resource.dispatchEvent(evt); if(parseInt(resourceCount)>0) { if(resource.value!=resourceCount) { this.Log('Not able to set resource count:'+num+',wanted:'+resourceCount+', count:'+resource.value); resource.style.backgroundColor='#f88'; return 'notfull'; } else { resource.style.backgroundColor='#ff8'; return 'full'; } } return 'none'; }, SetTroopInput:function(num,troopCount) { var troop=ById('modal_attack_unit_ipt'+num); if(!troop) return null; troop.value=troopCount; troop.style.backgroundColor=''; // send a shift key so that it recalculates var evt = document.createEvent("KeyboardEvent"); if(evt.initKeyboardEvent) { evt.initKeyboardEvent("keyup",true,true,null,false,false,false,false,0x10,0); } else { evt.initKeyEvent("keyup",true,true,null,false,false,false,false,0x10,0); } troop.dispatchEvent(evt); if(parseInt(troopCount)>0) { if(troop.value!=troopCount) { this.Log('Not able to set troop count:'+num+',wanted:'+troopCount+', count:'+troop.value); troop.style.backgroundColor='#f88'; return 'notfull'; } else { troop.style.backgroundColor='#ff8'; return 'full'; } } return 'none'; }, GetRandTime:function(millis) { var millisPerc=millis*(this.options.randomPercent/100); var randSecs=Math.floor((Math.random()*millisPerc*2)-millisPerc)+millis; return randSecs; }, GetAutoGold:function() { return this.GetValue('AutoGold,'+this.GetCurrentCityId(),true); }, SetAutoGold:function(v) { return this.SetValue('AutoGold,'+this.GetCurrentCityId(),v); }, GetAbandonWilds:function() { return this.GetValue('AbandonWilds_'+this.GetCurrentCityId(),false); }, SetAbandonWilds:function(v) { return this.SetValue('AbandonWilds_'+this.GetCurrentCityId(),v); }, CheckAutoRaiseGold:function() { if(!this.GetAutoGold()) return; var happiness=parseInt(this.GetSeed().citystats["city" + this.GetCurrentCityId()].pop[2]); if(happiness>=this.options.autoGoldHappiness) { this.DoUnsafeWindow("modal_raise_gold();"); } }, CheckAbandonWilds:function() { if(!this.GetAbandonWilds()) return; var t=this; var castle=ById('slot_0'); nHtml.Click(castle); this.DoUnsafeWindow("changeCastleModalTabs(2);"); var wildsWindow=ById('castle_2'); var rows=wildsWindow.getElementsByTagName('tr'); if (rows.length==1) { //no wilds this.DoUnsafeWindow("Modal.hideModal();"); return; } var commands = new Array(); for (i=0;i<rows.length;i++) { var abandonButton=rows[i].getElementsByTagName('a')[0]; if (abandonButton==undefined) { continue; } var command=abandonButton.getAttribute('onclick'); command=command.substring(0,command.length-13); if(command.indexOf("wilderness_abandon")>-1){ var tmp_obj = new Object; tmp_obj.command = command; tmp_obj.clicked = false; commands.push(tmp_obj); } } var command_timer=0; var milliseconds_between=4000; for (var i=0;i<commands.length;i++) { window.setTimeout(function() { // Determine next unclicked button var unclicked_commandObj = undefined; for (var j=0;j<commands.length;j++) { if(!commands[j].clicked){ t.DoUnsafeWindow(commands[j].command); window.setTimeout(function() { var mainbody = ById("mainbody"); if(mainbody){ var okay_btn=nHtml.FindByXPath(mainbody,".//a[contains(@class,'okay')]"); if(okay_btn){ nHtml.Click(okay_btn); } } },500); commands[j].clicked = true; break; } } },t.GetRandTime(command_timer)); command_timer+=milliseconds_between; } window.setTimeout(function() { t.DoUnsafeWindow("Modal.hideModal();"); },t.GetRandTime(command_timer)); }, GetDisplayName:function(){ var DisplayName = ById('topnavDisplayName'); if(DisplayName){ DisplayName = DisplayName.innerHTML; }else{ DisplayName = null; } return DisplayName }, HandleChatPane:function() { var t=this; // Determine our own name so we can ignore our own requests var DisplayName = t.GetDisplayName(); // Process chat pane var AllianceChatBox=ById('mod_comm_list2'); if(AllianceChatBox){ var chatPosts = document.evaluate(".//div[contains(@class,'chatwrap')]", AllianceChatBox, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null ); if(chatPosts){ // Loop through each post for (var i = 0; i < chatPosts.snapshotLength; i++) { thisPost = chatPosts.snapshotItem(i); //t.Log(thisPost.innerHTML); // Automatically help out with alliance requests if(this.options.autoHelpAlliance){ // Make sure that this isn't our own request var postAuthor = document.evaluate('.//*[@class="nm"]', thisPost, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null ); if(postAuthor.snapshotItem(0)){ var postAuthorName = postAuthor.snapshotItem(0).innerHTML; if(postAuthorName != DisplayName){ // Look for any alliance assist links in this current post item var helpAllianceLinks=document.evaluate(".//a[contains(@onclick,'claimAllianceChatHelp')]", thisPost, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null ); if(helpAllianceLinks){ for (var j = 0; j < helpAllianceLinks.snapshotLength; j++) { thisLink = helpAllianceLinks.snapshotItem(j); // Check to see if link has already been clicked var alreadyClicked = thisLink.getAttribute("clicked"); if(!alreadyClicked){ // Mark it as clicked thisLink.setAttribute('clicked', 'true'); // Execute the onclick code var myregexp = /(claimAllianceChatHelp\(.*\);)/; var match = myregexp.exec(thisLink.getAttribute("onclick")); if (match != null) { onclickCode = match[0]; //t.Log(onclickCode); // Check alliance help command history to make sure link hasn't already been processed if(!t.FindInCommandHistory(onclickCode, 'alliance_help')){ t.DoUnsafeWindow(onclickCode); // Add the onclick code to the alliance help command history this.AddToCommandHistory(onclickCode, 'alliance_help'); }else{ //t.Log("already clicked"); } } }else{ //t.Log("already clicked"); } } }else{ //t.Log("no alliance links found in current post"); } }else{ //t.Log("current post is by yourself"); } }else{ //t.Log("unable to find post's author"); } } // Hide alliance requests in chat if(this.options.hideAllianceHelpRequests){ // Look for any alliance assist links in this current post item var helpAllianceLinks=document.evaluate(".//a[contains(@onclick,'claimAllianceChatHelp')]", thisPost, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null ); if(helpAllianceLinks){ for (var j = 0; j < helpAllianceLinks.snapshotLength; j++) { thisLink = helpAllianceLinks.snapshotItem(j); // Delete the post item from the DOM thisLink.parentNode.parentNode.parentNode.parentNode.parentNode.removeChild(thisLink.parentNode.parentNode.parentNode.parentNode); } } } // Hide alliance reports in chat if(this.options.hideAllianceHelpRequests){ // Look for any alliance assist links in this current post item var myregexp1 = /You are # [1-5] of 5 to help/i; var myregexp2 = /\'s Kingdom does not need help\./i; var myregexp3 = /\'s project has already been completed\./i; var myregexp4 = /\'s project has received the maximum amount of help\./i; if (thisPost.innerHTML.match(myregexp1) || thisPost.innerHTML.match(myregexp2) || thisPost.innerHTML.match(myregexp3) || thisPost.innerHTML.match(myregexp4)) { // Delete the post item from the DOM thisPost.parentNode.removeChild(thisPost); } } } } } }, HandlePublishPopup:function() { var t=this; if (t.currentPage == "facebook_popup") { if(t.options.autoPublishGamePopups){ // Check the app id (we only want to handle the popup for kingdoms of camelot) var FBInputForm = ById('uiserver_form'); if(FBInputForm){ var channel_input = nHtml.FindByXPath(FBInputForm,".//input[contains(@name,'channel')]"); if(channel_input){ var current_channel_url = channel_input.value; if (current_channel_url.match(/http:\/\/.{0,100}kingdomsofcamelot\.com\/.{0,100}\/cross\.htm/i)) { var publish_button = nHtml.FindByXPath(FBInputForm,".//input[@type='submit' and contains(@name,'publish')]"); var privacy_setting = nHtml.FindByXPath(FBInputForm,".//input[@type='hidden' and contains(@name, 'privacy_data') and contains(@name, 'value')]"); if(publish_button && privacy_setting){ // 80: Everyone // 50: Friends of Friends // 40: Friends Only // 10: Only Me privacy_setting.value = t.options.autoPublishPrivacySetting; nHtml.Click(publish_button); } } } } } } }, domainLoginTimer:null, domainLoginStartTime:null, domainLoginCurrentTime:null, domainLoginSeconds:30, domainLoginActionTaken:false, HandleDomainLogin:function() { var t=this; if (t.currentPage == "domain_selection" && t.options.autoLogBackIn && !t.domainLoginActionTaken) { if(!t.domainLoginStartTime){ t.domainLoginStartTime = Math.round(new Date().getTime() / 1000); } t.domainLoginCurrentTime = Math.round(new Date().getTime() / 1000); var timeDifference = Math.round(t.domainLoginStartTime+t.domainLoginSeconds - t.domainLoginCurrentTime); if(timeDifference<0){ timeDifference=0; } var statusDiv=ById('KOCAttackLoginStatus'); if(!statusDiv) { statusDiv=document.createElement('div'); statusDiv.id='KOCAttackLoginStatus'; statusDiv.style.position='relative'; statusDiv.style.backgroundColor='#fff'; statusDiv.style.border='3px solid #888'; statusDiv.style.margin='30px 0px 0px 0px'; statusDiv.style.padding='10px'; statusDiv.style.display='none'; var loginBox = ById("formoptions0"); loginBox.appendChild(statusDiv); } // Find the top-most domain in the list (the most recent one) var playButtons=document.evaluate(".//a[contains(@class,'button20')]", unsafeWindow.document.body, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null ); if(playButtons && playButtons.snapshotLength>0){ //var firstPlayButton = playButtons.snapshotItem(0); //var domain_name = firstPlayButton.parentNode.parentNode.firstChild.innerHTML; //statusDiv.innerHTML='<center>KoCAttack Extra: Automatically logging into '+domain_name+' in '+timeDifference+' seconds...</center>'; statusDiv.innerHTML='<center>KoCAttack Extra: Automatically logging back into KoC in '+timeDifference+' seconds...</center>'; if(timeDifference==0){ //t.Log("Loading URL: "+firstPlayButton.href); t.Log("Loading URL: http://apps.facebook.com/kingdomsofcamelot/"); //statusDiv.innerHTML='<center>KoCAttack Extra: Automatically logging into '+domain_name+' now...</center>'; statusDiv.innerHTML='<center>KoCAttack Extra: Automatically logging back into KoC now...</center>'; var functionCall = { 'action':'load_url', //'parameters':firstPlayButton.href 'parameters':'http://apps.facebook.com/kingdomsofcamelot/' }; t.AddCrossIframeCommand("domain_selection_app_page", functionCall); t.domainLoginActionTaken=true; // Reload current window if things are unsuccessful window.setTimeout(function() { t.ReloadWindow(); },10000); } }else{ statusDiv.innerHTML='<center>KoCAttack Extra: Automatically reloading page in '+timeDifference+' seconds...</center>'; if(timeDifference==0){ statusDiv.innerHTML='<center>KoCAttack Extra: Automatically reloading page now...</center>'; t.ReloadWindow(); t.domainLoginActionTaken=true; } } statusDiv.style.display='block'; if(!t.domainLoginTimer && !t.domainLoginActionTaken) { t.domainLoginTimer=window.setTimeout(function() { t.domainLoginTimer=null; t.HandleDomainLogin(); },1000); } } }, HandleCrossIframeCommands:function() { var t=this; var commands = t.GetCrossIframeCommands(); if(!commands.queue) return false; var commandsUpdated = false; for(var i=0; i<commands.queue.length; i++) { var command = commands.queue[i]; // Cross-iframe Command structure: // commands { // command { // 'pageName' (string) - The page to execute the code on // 'functionCall' (string) - The function to call // } // } if(t.currentPage == command.pageName){ if(command.functionCall.action == "load_url"){ setTimeout (function (){window.location.href=command.functionCall.parameters;}, 0); } ArrayRemoveItem(commands.queue, i); commandsUpdated=true; } } if(commandsUpdated){ this.SetCrossIframeCommands(commands); } }, OnCastleBoxAppear:function(box) { var raiseGold=nHtml.FindByXPath(box,".//a[contains(@onclick,'raiseGold')]"); var a=document.createElement('a'); a.className='button25'; var t=this; function SetAutoGoldA() { var str=t.GetAutoGold()?'Auto - On':'Auto - Off'; a.innerHTML='<span>'+str+'</span>'; } a.addEventListener('click',function() { var autoGold=t.GetAutoGold(); t.SetAutoGold(autoGold?false:true); SetAutoGoldA(); },false); SetAutoGoldA(); raiseGold.parentNode.insertBefore(a,raiseGold.nextSibling); var productionHeader=nHtml.FindByXPath(box,".//div[contains(@class,'prodtableheader')]"); productionHeader=productionHeader.parentNode; var b=document.createElement('a'); b.className='button25'; function SetAbandonWildsA() { var str=t.GetAbandonWilds()?'Abandon Wilds - On':'Abandon Wilds - Off'; b.innerHTML='<span>'+str+'</span>'; } b.addEventListener('click',function() { var abandonWilds=t.GetAbandonWilds(); if(!abandonWilds){ var abandonWildsConfirm = confirm("Are you sure you want to automatically abandon all wildernesses?\n") if (!abandonWildsConfirm){ return false; } } t.SetAbandonWilds(abandonWilds?false:true); SetAbandonWildsA(); },false); SetAbandonWildsA(); //raiseGold.parentNode.insertBefore(b,raiseGold.nextSibling); productionHeader.parentNode.insertBefore(b,productionHeader); }, ClickShareToWall:function(box) { var t=this; if(t.options.autoPublishGamePopups){ var sharetowall_btn = nHtml.FindByXPath(box,".//a[contains(@onclick,'gethelp')]"); nHtml.Click(sharetowall_btn); } }, marketBoxTimeout:null, OnMarketBoxAppear:function(box) { var marketBox=ById('marketmain_bdy'); var t=this; if(marketBox) { window.setTimeout(function() { t.OnMarketBoxAppear(); },250); var amt=ById('marketmod_amount'); if(amt && amt.value=="0") amt.value='999000'; var price=ById('marketmod_price'); if(price && price.value=="0") price.value='1'; } }, nextAutoAttackTimeout:null, onclickTimeRe:/,([0-9]+),[0-9]+,[0-9]+,[0-9]+[^,]*$/, waitForAttackBoxAppear:null, OnAttackBoxAppear:function(box) { var btnMarch=ById('btnMarch'); var t=this; if(!btnMarch) { this.Log('no march button'); window.setTimeout(function() { t.OnAttackBoxAppear(box); },1000); return; } this.StopWaitForAttackBoxAppear(); if(ById('KocAttackComment')) { this.Log("We already have an attack dialog opened"); return; } btnMarch.addEventListener('click',function(e) { window.setTimeout(function() { t.SetAttackFromGui(box); t.SetValuesCache(); // we want to keep the scroll bar at the same position, don't redraw //~~~ mmm... need to wait for attack to finish before the numbers will update. t.DrawClosestFarms(); },0); },false); var comment=document.createElement('input'); comment.id='KocAttackComment'; comment.size='30'; var nowSecs=new Date().getTime()/1000; var div=document.createElement('div'); div.style.overflow='scroll'; div.style.height='280px'; AddText(div,'Comment:'); div.appendChild(document.createElement('br')); div.appendChild(comment); div.appendChild(document.createElement('br')); var div2=document.createElement('div'); var ignore=document.createElement('input'); ignore.type='checkbox'; div2.appendChild(ignore); AddText(div2,'Ignore in the attack list'); var nextElement=ById('marchTypeDesc'); nextElement.parentNode.insertBefore(div2, nextElement.nextSibling); //div.appendChild(document.createElement('br')); var xy=this.GetGuiCoords(); var attack=null; if(xy) { attack=this.GetAttack(xy[0],xy[1]); } var notFullTroops=false; var notFullResources=false; var knightSelect=ById('modal_attack_knight') var totalTroops=0; var totalResources=0; if(attack) { ignore.checked=attack.ignore?true:false; if(attack.time) { AddHtml(div,'Last attack: '+SecsToStr(nowSecs-attack.time)+' ago<br />'); } if(attack.comment){ comment.value=attack.comment; } var attackTypeSelect=ById('modal_attack_atktype'); // only fill things in if we're in attack mode. if(attackTypeSelect.selectedIndex==0 && attack.type==0) { if(this.prevAttack) { this.Log('Previous attack:'+this.prevAttack.x+'=='+xy[0] +','+this.prevAttack.y+'=='+xy[1] ); } var firstAttack = this.IsFirstAttackAtLocation(xy[0], xy[1]); this.Log("current attack wave type: "+attack.currenttattackwavetype); if(attack.suicidewave && attack.currenttattackwavetype=="suicide" && firstAttack) { // anti traps suicide wave attack if(typeof(attack.suicidewave)=="object") { for(var i=1; i<attack.suicidewave.length; i++) { this.SetTroopInput(i,attack.suicidewave[i]); totalTroops+=attack.suicidewave[i]; } } else { this.SetTroopInput(2,attack.suicidewave); totalTroops+=attack.suicidewave; } } else if(attack.troops) { for(var tr=0; tr<attack.troops.length; tr++) { var troopCount=attack.troops[tr]; if(!troopCount) continue; totalTroops+=troopCount; if(this.SetTroopInput(tr,troopCount)=='notfull') { notFullTroops=true; } } } //attackTypeSelect.selectedIndex=attack.type; knightSelect.selectedIndex=1+Math.floor(Math.random()*(knightSelect.options.length-1)); } else if (attackTypeSelect.selectedIndex==1 && attack.type==1) { attackTypeSelect.selectedIndex=attack.type; var resourceTypes = new Array( 'gold', 'rec1', 'rec2', 'rec3', 'rec4' ); for(var tr=0; tr<attack.troops.length; tr++) { var troopCount=attack.troops[tr]; if(!troopCount) continue; totalTroops+=troopCount; if(this.SetTroopInput(tr,troopCount)=='notfull') { notFullTroops=true; } } for(var res=0; res<attack.resources.length; res++) { var resourceCount=attack.resources[res]; if(!resourceCount) continue; totalResources+=resourceCount; if(this.SetResourceInput(resourceTypes[res],resourceCount)=='notfull') { notFullResources=true; } } // We don't send a knight with transports } if(attack.messages) { div.appendChild(document.createElement('br')); for(var m=attack.messages.length-1; m>=0; m--) { var message=attack.messages[m]; var ma=document.createElement('a'); var mess=message[0]; var timeNumM=this.onclickTimeRe.exec(message[1]); if(timeNumM) { var secs=nowSecs-parseInt(timeNumM[1]); mess=SecsToStr(secs)+' ago, '+mess; //mess=(new Date(parseFloat(timeNumM[1])*1000).toLocalString())+', '+mess; } ma.innerHTML=mess; //{"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;"]]} ma.setAttribute('onclick',"var m=CreateMsgDiv(); "+ message[1]+''); ma.href='javascript:;'; div.appendChild(ma); div.appendChild(document.createElement('br')); } div.appendChild(document.createElement('br')); } var deleteBtn=document.createElement('a'); deleteBtn.className='button25'; deleteBtn.innerHTML='<span>Delete Attack</span>'; deleteBtn.addEventListener('click',function() { t.DeleteAttack(xy[0],xy[1]); t.DoUnsafeWindow('Modal.hideModalAll();'); t.DrawClosestFarms(); },false); attackTypeSelect.parentNode.insertBefore(deleteBtn,attackTypeSelect.nextSibling); } var ChangeAttack=function() { var xy=t.GetGuiCoords(); var attack=null; var attackTypeSelect=ById('modal_attack_atktype'); if(xy) { attack=t.GetAttack(xy[0],xy[1]); } if(!attack) attack={}; if(attackTypeSelect.selectedIndex!=attack.type) { t.Log('We wont change an attack if the type is different. You must delete the attack to change the type'); return; } attack.comment=comment.value; attack.ignore=ignore.checked?true:undefined; t.SetAttack(xy[0],xy[1],attack); } comment.addEventListener('change',function() { ChangeAttack(); },false); ignore.addEventListener('change',function() { ChangeAttack(); },false); var parentDiv=ById('modal_attack_items'); parentDiv.parentNode.insertBefore(div,parentDiv); parentDiv.parentNode.insertBefore(this.HideAttackEfforts(),parentDiv); parentDiv.parentNode.insertBefore(this.BulkAddAttackLink(box),parentDiv); this.AttachXYPaste('modal_attack_target_coords_x','modal_attack_target_coords_y'); var autoAttack=this.GetAutoAttack(); if(autoAttack && autoAttack.x==xy[0] && autoAttack.y==xy[1] && !ignore.checked) { autoAttack.x=autoAttack.y=-1; this.SetAutoAttack(autoAttack); if(totalTroops>0 && knightSelect.options.length>1 && !notFullTroops && !notFullResources && btnMarch.style.opacity!=0.5 ) { this.Log('Auto attack:'+xy[0]+','+xy[1]+', from city:'+this.autoAttackCityUpto); var t=this; window.setTimeout(function() { t.autoAttacksThisCity++; nHtml.Click(btnMarch); //t.ResetIdStatus(); window.setTimeout(function() { var mist=nHtml.FindByXPath(document,".//div[@class='mistwarn']"); if(mist) { t.DoUnsafeWindow("Modal.hideModal();"); t.DoUnsafeWindow("modal_attack_do();"); } },t.GetRandTime(200)); },t.GetRandTime(1000)); if(!this.nextAutoAttackTimeout) { this.nextAutoAttackTimeout=setTimeout(function() { // let's attack again in a few secs. t.nextAutoAttackTimeout=null; t.NextAutoAttack(); },t.GetRandTime(1000*this.options.attackDelay)); } else { this.Log('Cannot continue auto attacking, about to attack or change city'); } return; } else { this.Log('auto attack, not enough troops/knights: '+xy[0]+','+xy[1]+ ", knights avail:"+(knightSelect.options.length-1)+", Not enough troops/resources:"+notFullTroops+'/'+notFullResources+', needed:'+totalTroops+'/'+totalResources); this.DoUnsafeWindow("Modal.hideModal();"); this.NextAutoAttackCity(); } } }, coordsRe:/\(([0-9]+),([0-9]+)\)/, maptileRe:/modal_maptile.([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+),([^,]+)/, OnToolTipAppear:function(box) { var box1=box.childNodes[0].childNodes[0]; var m=this.coordsRe.exec(box.innerHTML); if(!m || m.length==0) return; var x=m[1]; var y=m[2]; var a=ById('l_'+x+'_t_'+y); if(a) { var onclick=a.getAttribute('onclick'); if(onclick) { var titleM=this.maptileRe.exec(onclick); if(titleM && titleM[8].indexOf('null')<0) { AddHtml(box1,'Title: '+titleM[8].StripQuotes()+'<br />'); } } } var attack=this.GetAttack(x,y); if(!attack) return; var troops=attack.troops; if(troops && troops.length>0) { var lastAttack=parseInt(attack.time); var nowSecs=new Date().getTime()/1000; var lastAttackStr='Last attack: '+SecsToStr(nowSecs-lastAttack)+' ago'+(attack.ignore?' <b>(ignore)</b> ':''); AddHtml(box1,lastAttackStr+'<br />'); if(attack.comment) { AddHtml(box1,attack.comment+'<br />'); } } }, /* // don't know why but messages get duped sometimes. FixMessages:function(attack) { var fixed=0; var done={}; for(var m=0; m<attack.messages.length; m++) { if(!done[attack.messages[m][1]]) { done[attack.messages[m][1]]=true; GM_log('ffff:'+attack.messages[m][1]+'####'+typeof(attack.messages[m][1])); } else { attack.messages.splice(m,1); fixed++; } } return fixed; }, */ CalcXYDist:function(a,b) { var xdist=parseInt(a.x)-parseInt(b.x); xdist=Math.abs(xdist); if(xdist>=375) xdist=750-xdist; var ydist=parseInt(a.y)-parseInt(b.y); ydist=Math.abs(ydist); if(ydist>=375) ydist=750-ydist; return Math.sqrt((xdist*xdist)+(ydist*ydist)); }, //attackRe:/\s+(\S+)\s+Lv\.\s*([0-9]+)/, squareTypeNums:{ '51':'Camp', '10':'Grassland', '11':'Lake', '20':'Forest', '30':'Hills', '40':'Mountains', '50':'Plain', '0':'Bog' }, FindLevelFromMessages:function(attack) { if(!attack || !attack.messages) return null; for(var a=0; a<attack.messages.length; a++) { var m=this.onclickReportRe.exec(attack.messages[a][1]); if(!m) { this.Log("Unable to find location level/type information in cached reports!"); continue; } var typeNum=m[3].replace('"',''); var type=this.squareTypeNums[typeNum]; if(!type) { this.Log("Unable to find location type information in cached reports!"); continue; } if(typeNum=="51" && m[5]!='0') { type=''; } //this.Log("Target Type: "+type+", Target Level: "+m[4]); return {'type':type,'level':m[4]}; } return null; }, DrawLevelIcons:function() { var mapwindow=ById('mapwindow'); if(!mapwindow) return; var levelIcons=ById('LevelIcons'); if(levelIcons) return; var ss=document.evaluate(".//a[contains(@class,'slot')]",mapwindow,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null); var lvRe=/_([0-9]+)/; var idDone=false; for(var s=0; s<ss.snapshotLength; s++) { var a=ss.snapshotItem(s); var onclick=a.getAttribute('onclick'); var owner=''; if(onclick) { var onclickM=this.maptileRe.exec(onclick); if(onclickM && onclickM[6]!='"null"' && onclickM[12]!='"city"') { var might=onclickM[7].StripQuotes(); //var alliance=onclickM[9].StripQuotes(); //+"<br />"+(alliance=="null"?"":alliance); owner=" "+onclickM[6].StripQuotes()+'<br />Might:'+might; } } var m=lvRe.exec(a.className); if(!m) continue; var sp=a.getElementsByTagName('span'); if(sp.length==0) continue; if(!idDone) { a.id='levelIcons'; idDone=true; } sp[0].style.color='#cc0'; //sp[0].innerHTML='<center>'+m[1]+'</center>'; sp[0].innerHTML=' '+m[1]+owner; } }, AttachXYPaste:function(xId,yId,func) { var x=ById(xId); if(!x) { this.Log('Cannot find x coord box: '+xId); return; } var attached=x.getAttribute('KOCpasteAttached'); if(attached) return; x.setAttribute('maxlength','20'); var onchange=function() { var xValue=x.value.trim(); var xI=/^\s*([0-9]+)[\s,]+([0-9]+)/.exec(xValue); if(xI) { var y=ById(yId); x.value=xI[1] y.value=xI[2] if(func!=undefined) func(xI[0],xI[1]); } } x.setAttribute('KOCpasteAttached',true); x.addEventListener('keyup',function() { onchange(); },false); x.addEventListener('change',function() { onchange(); },false); }, GetClosestAttacks:function(x,y) { var attacks=[]; var t=this; this.IterateAttacks(function(name,value) { var nameI=name.split('_'); if(nameI.length<3) return; var xy=nameI[2].split(','); if(value=="") return; var attack=JSON2.parse(value); if(!attack) return; if(attack.ignore) return; var dist=t.CalcXYDist({'x':xy[0],'y':xy[1]},{'x':x,'y':y}); if (dist==0) { return; } // Don't attack yourself if(dist>=t.options.attackMaxDistance) { return; } attacks.push({'dist':dist,'x':xy[0],'y':xy[1],'a':attack}); }); attacks.sort(function(a,b) { return a.dist-b.dist; }); return attacks; }, IsEnoughTroops:function(currentTroops,neededTroops) { for(var t=0; t<neededTroops.length; t++) { if(!neededTroops[t]) continue; if(parseInt(neededTroops[t])>parseInt(currentTroops[t])) { return false; } } return true; }, IsEnoughResources:function(currentResources,neededResources) { for(var t=0; t<neededResources.length; t++) { if(!neededResources[t]) continue; if(parseInt(neededResources[t])>parseInt(currentResources[t])) { return false; } } return true; }, currentMarchesNum:0, DetermineCurrentMarchesNum:function() { var marchesnum = 0; var troopactivity = ById("untqueue_list"); if(troopactivity && troopactivity.style.display!="none" && troopactivity.style.visibility!="hidden"){ marchesnum = troopactivity.childNodes.length; } //this.Log("Current number of marches in this city: "+marchesnum); this.currentMarchesNum = marchesnum; return marchesnum; }, currentRallyPointLevel:0, DetermineCurrentRallyPointLevel:function() { var rallypointlevel = 0; var citymap = ById("citymap"); if(citymap){ var citylinks = nHtml.FindByXPath(citymap,'.//a[contains(@class, "bldg")]', XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); for (var i = 0; i < citylinks.snapshotLength; i++){ var building = citylinks.snapshotItem(i); var style = window.getComputedStyle(building, false); var css_bgimg = style.backgroundImage; //this.Log("building background image "+i+": "+css_bgimg); var myregexp = /rally_point_lvl/i; var match = myregexp.exec(css_bgimg); if (match != null) { // Determine the rally point level based on the level tag overlay var leveltag = nHtml.FindByXPath(building,'.//span[contains(@class, "level")]'); if(!leveltag){ continue; } var levelnum = parseInt(leveltag.innerHTML); if(levelnum>rallypointlevel){ rallypointlevel = levelnum; } } } if(rallypointlevel==0){ // Couldn't find the rally point based on the background image. Odds are that the rally point exists, // but is currently under construction. Let's see if we can deduce the rally point's level based on this assumption. // Note: This will bug out if the city has literally no rally point at all, but who's really that stupid? for (var i = 0; i < citylinks.snapshotLength; i++){ var building = citylinks.snapshotItem(i); var style = window.getComputedStyle(building, false); var css_bgimg = style.backgroundImage; //this.Log("building background image "+i+": "+css_bgimg); var myregexp = /construction/i; var match = myregexp.exec(css_bgimg); if (match != null) { // Determine the rally point level based on the level tag overlay var leveltag = nHtml.FindByXPath(building,'.//span[contains(@class, "level")]'); if(!leveltag){ continue; } var levelnum = parseInt(leveltag.innerHTML); if(levelnum>rallypointlevel){ rallypointlevel = levelnum-1; } } } } //this.Log("Rally point level in this city is: "+rallypointlevel); } this.currentRallyPointLevel = rallypointlevel; return rallypointlevel; }, GetLevelInfo:function(attack) { if(!attack) throw('GetLevelInfo: attack is null'); var levelI=attack.levelInfo; //if((!levelI || levelI.level==0) && attack.messages && attack.messages.length>0) { if((!levelI || levelI.level==0) && attack.messages && attack.messages.length>0) { levelI=this.FindLevelFromMessages(attack); } if (!levelI && (attack.currenttattackwavetype == 'transport')){ return {'type':'transport','level':0}; } return levelI; }, GetAttackDelay:function(attack) { if(!attack) throw('GetAttackDelay: attack is null'); var attackDelay = 0; var wilderness={ 'Lake':1, 'Mountains':1, 'Woods':1, 'Forest':1, 'Plain':1, 'Hills':1, 'Grassland':1, 'Wilderness':1 // Unknown wilderness type }; var levelInfo=this.GetLevelInfo(attack); if(!levelInfo) { this.Log("Unable to calculate attack delay: Missing level info for coordinates ("+attack.x+","+attack.y+"). Assuming delay of 0."); }else{ if(levelInfo.type=='Camp') { // Camp attackDelay = this.options.attackSecsSinceLastCamp; } else if(wilderness[levelInfo.type]) { // Wilderness attackDelay = this.options.attackSecsSinceLastWild; } else if (levelInfo.type!='Camp' && !wilderness[levelInfo.type]) { var tempAttack=this.GetAttack(attack.x,attack.y); if(tempAttack.type==0) { // City attackDelay = this.options.attackSecsSinceLastCity; } else if(tempAttack.type==1) { // Transport attackDelay = this.options.attackSecsSinceLastTransport; }else{ this.Log("Unknown attack type for ("+attack.x+","+attack.y+"). Assuming delay of 0."); } }else{ this.Log("Unknown attack type for ("+attack.x+","+attack.y+"). Assuming delay of 0."); } } return attackDelay; }, FindBiggestCampAttack:function(attacks,currentTroops,currentResources) { var bestAttack=null; var bestAttackSize=0; var bestAttackDist=10000; var nowSecs=new Date().getTime()/1000; var currentCity = this.GetCurrentCityId(); // Determine the current rally point level and current marches this.DetermineCurrentRallyPointLevel(); this.DetermineCurrentMarchesNum(); this.Log("Current Rally Point Level: "+this.currentRallyPointLevel+" Current Marches: "+this.currentMarchesNum); var wilderness={ 'Lake':1, 'Mountains':1, 'Woods':1, 'Forest':1, 'Plain':1, 'Hills':1, 'Grassland':1, 'Wilderness':1 // Unknown wilderness type }; for(var a=0; a<attacks.length; a++) { var attack=attacks[a]; //this.Log("Inspecting attack #"+a+": "+inspect(attack,10)); var levelInfo=this.GetLevelInfo(attack.a); if(!levelInfo) { this.Log("Not attacking: Missing level info! for coordinates ("+attack.x+","+attack.y+")"); continue; } if(levelInfo.type=='Camp') { if(this.options.attackTypeCamp!=true) { this.Log("Not attacking: Not attacking camps! for coordinates ("+attack.x+","+attack.y+")"); continue; } } else if(wilderness[levelInfo.type]) { if(this.options.attackTypeWild!=true) { this.Log("Not attacking: Not attacking wildernesses! for coordinates ("+attack.x+","+attack.y+")"); continue; } } else if (levelInfo.type!='Camp' && !wilderness[levelInfo.type]) { var tempAttack=this.GetAttack(attack.x,attack.y); if(tempAttack.type==0) { if(this.options.attackTypeCity!=true) { this.Log("Not attacking: Not attacking cities for coordinates ("+attack.x+","+attack.y+")"); continue; } } else if(tempAttack.type==1) { if(this.options.attackTypeTransport!=true) { this.Log("Not attacking: Not sending transports for coordinates ("+attack.x+","+attack.y+")"); continue; } } } else { if(levelInfo.type!='' && levelInfo.type!='Camp') { this.Log("Not attacking: Unknown attack type for coordinates ("+attack.x+","+attack.y+")"); continue; } } if(!attack.a.troops) { this.Log("inspect1: "+inspect(attack.a),10); this.Log("Not attacking: No troops defined for coordinates ("+attack.x+","+attack.y+")"); continue; } if(attack.a.ignore) { this.Log("Not attacking: Location ignored for coordinates ("+attack.x+","+attack.y+")"); continue; } if(attack.dist>=this.options.attackMaxDistance) { this.Log("Not attacking: Distance too far for coordinates ("+attack.x+","+attack.y+")"); continue; } if(this.options.lockAttackFromCity) { //this.Log('fromCity='+attack.a.fromCity+', currentCity='+this.GetCurrentCityId()); if(attack.a.fromCity!=undefined) { if(currentCity!=attack.a.fromCity) { continue; } } } var troops_to_send = attack.a.troops; if(attack.a.suicidewave){ // count up all the troops in *both* attack waves. // we don't want to launch suicide wave if we can't follow it up. var suicide_troops = attack.a.suicidewave; for(var t=0; t<suicide_troops.length; t++) { if(!suicide_troops[t]) continue; troops_to_send[t] = troops_to_send[t] + suicide_troops[t]; } } //if(!this.currentMarchesNum || this.currentMarchesNum==undefined) { // this.Log("Not attacking: Unable to determine current number of marches (refresh your window?) for coordinates ("+attack.x+","+attack.y+")"); // continue; //} // 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) var available_marches_num = this.currentRallyPointLevel - this.currentMarchesNum; //this.Log("Available marches: "+available_marches_num); if(attack.a.suicidewave && attack.a.currenttattackwavetype != "normal"){ //this.Log("Current attack wave type: "+attack.a.currenttattackwavetype); if(available_marches_num < 2 || this.currentRallyPointLevel < 2){ // 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 if(this.prevAttack.x != attack.x && this.prevAttack.y != attack.y) { // This is the first wave 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+")"); break; } } } // Make sure we have at least one available slot in attack queue for normal attack if(available_marches_num<1){ this.Log("Not attacking: Not enough marching slots at rally point to launch attack for coordinates ("+attack.x+","+attack.y+")"); break; } if(!this.IsEnoughTroops(currentTroops,troops_to_send)) { this.Log("Not attacking: Not enough troops for coordinates ("+attack.x+","+attack.y+")"); continue; } if (attack.a.type==1) { if(!this.IsEnoughResources(currentResources,attack.a.resources)) { this.Log("Not attacking: Not enough resources for coordinates ("+attack.x+","+attack.y+")"); continue; } } var lastAttack; if(!attack.a.time) { lastAttack=60*60*24*31; } else { lastAttack=nowSecs-parseInt(attack.a.time); } if(levelInfo.type=='transport') { if(attack.a.type==0) { if(lastAttack<this.options.attackSecsSinceLastCity) { this.Log("Not attacking: last attack ("+lastAttack+") < this.options.attackSecsSinceLastCity ("+this.options.attackSecsSinceLastCity+") for coordinates ("+attack.x+","+attack.y+")"); continue; } } else { if(lastAttack<this.options.attackSecsSinceLastTransport){ this.Log("Not attacking: last attack ("+lastAttack+") < this.options.attackSecsSinceLastTransport ("+this.options.attackSecsSinceLastTransport+") for coordinates ("+attack.x+","+attack.y+")"); continue; } } } else if(levelInfo.type.toUpperCase()=='C') { if(lastAttack<this.options.attackSecsSinceLastCamp) { this.Log("Not attacking: last attack ("+lastAttack+") < this.options.attackSecsSinceLastCamp ("+this.options.attackSecsSinceLastCamp+") for coordinates ("+attack.x+","+attack.y+")"); continue; } } else { if(lastAttack<this.options.attackSecsSinceLastWild) { this.Log("Not attacking: last attack ("+lastAttack+") < this.options.attackSecsSinceLastWild ("+this.options.attackSecsSinceLastWild+") for coordinates ("+attack.x+","+attack.y+")"); continue; } } var armySize=0; for(var t=0; t<attack.a.troops.length; t++) { if(!attack.a.troops[t]) { continue; } armySize+=parseInt(attack.a.troops[t]); } if(attack.a.suicidewave) { var suicideArmySize=0; for(var t=0; t<attack.a.suicidewave.length; t++) { if(!attack.a.suicidewave[t]) { continue; } suicideArmySize+=parseInt(attack.a.suicidewave[t]); } if(suicideArmySize<=0) { this.Log('Invalid suicide wave army size (not enough!) for coordinates ('+attack.x+','+attack.y+')'); continue; } } if(armySize<=0) { this.Log('Invalid suicide wave army size (not enough!)for coordinates ('+attack.x+','+attack.y+')'); continue; } var ok=0; if(this.options.attackOrder=='mostTroops') { if(bestAttackSize<armySize) { ok=1; } } else { if(this.options.attackOrder!='closest') { this.Log('Unknown order:'+this.options.attackOrder); } if(bestAttackDist>attack.dist) { ok=1; bestAttackDist=attack.dist; } } if(ok) { bestAttack=attack; bestAttack.type=attack.a.type; bestAttackSize=armySize; } } return bestAttack; }, IsMapperRunning:function() { if(ById('SendMap')) { //GM_log('mapper is running, do not auto attack'); return true; } return false; }, GetAutoAttack:function() { var aStr=this.GetValue('AutoAttack',''); //var aStr=GM_getValue('AutoAttack_'+this.GetServerId(),''); if(aStr=='') { return null; } try { return JSON2.parse(aStr); } catch(e) { GM_log('failed to parse autoattack:'+aStr); return null; } }, SetAutoAttack:function(s) { if(s==null) { this.SetValue('AutoAttack',''); //GM_setValue('AutoAttack_'+this.GetServerId(),''); return; } this.SetValue('AutoAttack',JSON2.stringify(s)); //GM_setValue('AutoAttack_'+this.GetServerId(),JSON.stringify(s)); }, ResetAutoAttackTarget:function() { var autoAttack=this.GetAutoAttack(); if(autoAttack) { autoAttack.x=autoAttack.y=undefined; this.SetAutoAttack(autoAttack); } }, GetCurrentMapCoord:function() { var xcoord=ById('mapXCoor'); var ycoord=ById('mapYCoor'); return {'x':xcoord.value,'y':ycoord.value}; }, hrsInput:null, viewTypeOnly:"", expandedInfo:false, DrawClosestFarms:function() { this.SetAttackStatusMessage(); var t=this; //unsafeWindow.statusupdate(); var bookmark=ById('maparea_map'); if(!bookmark) throw("Cannot find bookmark box"); bookmark=nHtml.FindByXPath(bookmark.parentNode,".//div[@class='coords']"); var div=ById('ClosestFarms'); if(!div) { div=document.createElement('div'); var titleA=document.createElement('a'); titleA.innerHTML='Attacks '; titleA.title='Closest attacks, more than ? hrs since last attack'; titleA.style.cursor='pointer'; titleA.addEventListener('click',function() { div.style.display=div.style.display=='block'?'none':'block'; setTimeout(function() { t.SetValue('ClosestFarmDisplay',div.style.display); },0); },false); var viewTypeOnlyInp=document.createElement('input'); viewTypeOnlyInp.style.width='10px'; viewTypeOnlyInp.style.fontSize="8px"; viewTypeOnlyInp.title="Type of target. ex: P, W, M, P1"; this.hrsInput=document.createElement('input'); this.hrsInput.style.width='16px'; this.hrsInput.value=this.GetMinHours(); var hrsChanged=function() { var v=parseFloat(t.hrsInput.value); t.viewTypeOnly=viewTypeOnlyInp.value; if(v!=undefined && v!=NaN) { t.SetMinHours(t.hrsInput.value); t.DrawClosestFarms(); } } this.hrsInput.addEventListener('change',function() { hrsChanged(); },false); this.hrsInput.addEventListener('keyup',function() { hrsChanged(); },false); viewTypeOnlyInp.addEventListener('keyup',function() { hrsChanged(); },false); bookmark.appendChild(document.createElement('br')); bookmark.appendChild(titleA); AddText(bookmark,'>'); bookmark.appendChild(this.hrsInput); AddText(bookmark,'hrs '); var expandA=document.createElement('a'); expandA.innerHTML='E'; expandA.title='Expand information'; expandA.addEventListener('click',function() { t.expandedInfo=t.expandedInfo?false:true; t.DrawClosestFarms(); },false); bookmark.appendChild(viewTypeOnlyInp); bookmark.appendChild(expandA); bookmark.appendChild(document.createElement('br')); } div.innerHTML=''; div.id='ClosestFarms'; div.style.overflow='scroll'; div.style.height='200px'; div.style.display=this.GetValue('ClosestFarmDisplay','block'); var currentTroops=this.GetArmySize(); var currentResources=this.GetResourcesSize(); var mapCoord=this.GetCurrentMapCoord(); var nowSecs=new Date().getTime()/1000; var attacks=this.GetClosestAttacks(mapCoord.x,mapCoord.y); //var bestAttack=this.FindBiggestCampAttack(attacks,currentTroops,currentResources); var GoClosestFarm=function(e) { var xy=e.target.parentNode.parentNode.getAttribute('xy').split(','); t.DoUnsafeWindow("setBookmarkCoord("+xy[0]+","+xy[1]+");"); }; var AttackClosestFarm=function(e) { var xy=e.target.parentNode.parentNode.getAttribute('xy').split(','); var attack=t.GetAttack(xy[0],xy[1]); if(!attack) throw("Cannot find:"+xy[0]+','+xy[1]); if(attack.type==0) { t.DoUnsafeWindow("modal_attack(4,"+xy[0]+","+xy[1]+");"); } else if(attack.type==1) { t.DoUnsafeWindow("modal_attack(1,"+xy[0]+","+xy[1]+");"); } }; var IgnoreFarm=function(e) { var xy=e.target.parentNode.parentNode.getAttribute('xy').split(','); var attack=t.GetAttack(xy[0],xy[1]); if(!attack) throw("Cannot find:"+xy[0]+','+xy[1]); attack.ignore=true; t.SetAttack(xy[0],xy[1],attack); setTimeout(function() { t.DrawClosestFarms(); },0); }; var DeleteFarm=function(e) { var xy=e.target.parentNode.parentNode.getAttribute('xy').split(','); t.DeleteAttack(xy[0],xy[1]); setTimeout(function() { t.DrawClosestFarms(); },0); }; var aDone=0; var table=document.createElement('table'); table.className=''; var minHrsSinceAttack=parseFloat(this.hrsInput.value); var viewType=this.viewTypeOnly.trim().toUpperCase(); for(var aUpto=0; aUpto<attacks.length; aUpto++) { var attackI=attacks[aUpto]; try { //attackI.a.levelInfo=this.FindLevelFromMessages(attackI.a); //this.SetAttack(attackI.x,attackI.y,attackI.a); if(!attackI.a.time) { lastAttack=60*60*24*31; } else { lastAttack=nowSecs-parseInt(attackI.a.time); } //if(lastAttack<(60*60*minHrsSinceAttack)) continue; var levelI=this.GetLevelInfo(attackI.a); var m=( (levelI!=null && levelI.type) ?(levelI.type.charAt(0)+levelI.level):''); //this.Log("Location Type: "+m); if(this.viewTypeOnly!="") { if(this.viewTypeOnly==" ") { if(m!="") { continue; } } else if(viewType.length==0 || m.substring(0,viewType.length)!=viewType) { continue; } } var dist=this.CalcXYDist({'x':attackI.x,'y':attackI.y},mapCoord); if(dist>=this.options.attackMaxDistance) { break; } var tr=table.insertRow(-1); tr.setAttribute('xy',attackI.x+','+attackI.y); var td=tr.insertCell(-1); td.style.whiteSpace='nowrap'; var a=document.createElement('a'); a.style.fontSize='10px'; a.innerHTML=attackI.x+','+attackI.y; a.addEventListener('click',function(e) { GoClosestFarm(e); },false); td.appendChild(a); AddText(td,' '); //td=tr.insertCell(-1); var attackA=document.createElement('a'); attackA.style.fontSize='10px'; /* ~~~ disabled: incorrect numbers due to having to wait for attack to update. if(bestAttack && attackI.x==bestAttack.x && attackI.y==bestAttack.y) { attackA.style.color='#f88'; } */ attackA.title=(levelI!=null?(levelI.type+' '+levelI.level):''); if(attackI.a.comment) { attackA.title+=", "+attackI.a.comment; } if(attackI.a.time && !isNaN(lastAttack)) { // if we only scouted or transported to someone they won't have a last attack time. m=m+' @'+SecsToStr(lastAttack); } attackA.innerHTML=m; attackA.addEventListener('click',function(e) { AttackClosestFarm(e); },false); td.appendChild(attackA); if(t.expandedInfo) { var troops=attackI.a.troops; if(troops) { for(var tupto=0; tupto<troops.length; tupto++) { var num=troops[tupto]; if(attackI.a.suicidewave) { var am=attackI.a.suicidewave[tupto]; if(am) num+=" ("+am+")"; } AddText(tr.insertCell(-1),num); } } } var aDelete=document.createElement('a'); aDelete.innerHTML='X'; aDelete.title='Delete'; aDelete.addEventListener('click',function(e) { DeleteFarm(e); },false); tr.insertCell(-1).appendChild(aDelete); aDone++; } catch(e) { this.Log('Error:'+e); } } div.appendChild(table); //bookmark.parentNode.insertBefore(div,bookmark); //bookmark.parentNode.appendChild(document.createElement('br')); bookmark.appendChild(div); this.AttachXYPaste('mapXCoor','mapYCoor'); }, // ?,1,square type, level, player id?, // target player name, target gender, player name, player gender, ?, target x, target y, report id, 0, x y onclickReportRe:/(["0-9]+),(["0-9]+),(["0-9]+),(["0-9]+),(["0-9]+),("[^"]+"),("[^"]+"),("[^"]+"),("[^"]+"),(["0-9]+),(["0-9]+),(["0-9]+),/, //modal_messages_viewreports_view("897422",0,51,9,2485358,"niknah","M","niknah","M",1,333,110,1275178036,1,286,181); // remove the read/unread flag onclickReadRe:/^(.*,)([0-9]+)(,[0-9]+,[0-9]+[^,]*)$/, FixOnClick:function(a) { var m=this.onclickReadRe.exec(a); if(m) { return m[1]+"0"+m[3]; } return a; }, IterateArmy:function(f) { if(!this.GetSeed()) return; var armyDiv=ById('cityinfo_3'); var units=this.GetSeed().units["city"+unsafeWindow.currentcityid]; //var unitKeys=Object.keys(units); //for(var u=0; u<unitKeys; u++) { var uRe=/([0-9]+)$/; for(var u in units) { var m=uRe.exec(u); if(!m) continue; f.call(this,m[1],units[u]); } /* var ss=document.evaluate(".//div[@class='unit']",armyDiv,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null); for(var s=0; s<ss.snapshotLength; s++) { var unit=ss.snapshotItem(s); var amt=unit.textContent; f.call(s,amt); } */ }, GetArmySize:function() { var troops=[]; this.IterateArmy(function(s,amt) { troops[s]=amt; }); return troops; }, GetResourcesSize:function() { var resources=[]; var cityID = this.GetCurrentCityId(); resources[0] = parseInt(Seed.citystats['city'+cityID].gold[0]); resources[1] = parseInt(Seed.resources['city'+cityID]['rec'+1][0] / 3600); resources[2] = parseInt(Seed.resources['city'+cityID]['rec'+2][0] / 3600); resources[3] = parseInt(Seed.resources['city'+cityID]['rec'+3][0] / 3600); resources[4] = parseInt(Seed.resources['city'+cityID]['rec'+4][0] / 3600); return resources; }, OpenViewReports:function() { this.Log('Open View Reports'); this.DoUnsafeWindow("modal_messages();"); this.DoUnsafeWindow('track_chrome_btn("messages_btn");'); this.DoUnsafeWindow('modal_messages_viewreports();'); }, //autoAttackCitiesDoneMax:3, autoAttackCitiesDone:0, autoAttackCityUpto:1, autoAttackModalWaiting:false, autoAttackTimeout:null, autoAttacksThisCity:0, ClearAutoAttackTimeout:function() { if(this.autoAttackTimeout!=null) { this.Log('reload page timer killed'); window.clearTimeout(this.autoAttackTimeout); this.autoAttackTimeout=null; } }, RestartAutoAttack:function() { this.autoAttacksThisCity=0; this.autoAttackCitiesDone=0; this.autoAttackCityUpto=1; this.autoAttackModalWaiting=false; this.NextAutoAttack(); }, StartReloadPageTimer:function(secs) { var t=this; if(!secs) secs=this.options.waitAfterCitiesDone; var refreshMSecs=t.GetRandTime(1000*secs); this.Log('refreshing in '+(refreshMSecs/1000)+' secs, all cities done:'+this.autoAttackCityUpto); this.ClearAutoAttackTimeout(); this.autoAttackTimeout=window.setTimeout(function() { if(t.autoAttackTimeout==null) return; t.autoAttackTimeout=null; if(t.IsMapperRunning() || t.IsCurrentlySendingMultipleWaves()) { if(t.IsMapperRunning()){ t.Log("Waiting for mapping to finish"); }else{ t.Log("Waiting for multiple wave attack to finish"); } // don't reload until the mapper or multi-wave attack has finished. window.setTimeout(function() { t.StartReloadPageTimer(); },0); return; } t.SetValuesCache(); //window.location.reload(true); t.ReloadWindow(); },refreshMSecs); this.Log('reload page timer started'); }, multipleWaveTimeout:null, ClearMultipleWaveTimeout:function() { if(this.multipleWaveTimeout!=null) { this.Log('city switching timer killed'); window.clearTimeout(this.multipleWaveTimeout); this.multipleWaveTimeout=null; } }, StartMultipleWaveTimer:function(secs) { var t=this; if(!secs) secs=t.options.attackDelay; var attackDelayMSecs=t.GetRandTime(1000*secs); this.Log('Waiting '+(attackDelayMSecs/1000)+' secs to retry second wave attack...'); this.ClearMultipleWaveTimeout(); this.multipleWaveTimeout=window.setTimeout(function() { if(t.multipleWaveTimeout==null) return; t.multipleWaveTimeout=null; if(t.IsCurrentlySendingMultipleWaves()) { t.Log("Waiting for multiple wave attack to finish..."); // don't switch cities until the multi-wave attack has finished. window.setTimeout(function() { t.StartMultipleWaveTimer(); },0); return; } t.NextAutoAttackCity(); },attackDelayMSecs); this.Log('Multiple wave attack timer started'); }, lastOpenViewReports:0, CheckReports:function() { var t=this; var autoAttack=this.GetAutoAttack(); if(!autoAttack) return; // Load the reports every minute or on initial page load if(!this.options.noViewReports) { var nowSecs=new Date().getTime()/1000; if((this.lastOpenViewReports+(60*1))<nowSecs) { this.lastOpenViewReports=nowSecs; this.OpenViewReports(); this.bringUpReports=true; if(this.options.autoRemoveReports) { this.autoAttackRemoveReports=true; } } } }, ClickChangeCity:function(cityA,tries) { var t=this; nHtml.Click(cityA); t.nextAutoAttackWanted=window.setTimeout(function() { if(t.nextAutoAttackWanted!=null) { if(tries>4) { t.Log("Skip city, too many retries"); t.NextAutoAttackCity(); return; } t.Log("We clicked change city but the city did not change, trying again"); // Didn't change city t.ClickChangeCity(cityA,tries+1); } },10000); }, NextAutoAttackCity:function() { var t=this; var autoAttack=this.GetAutoAttack(); if(!autoAttack) return; if(this.IsCurrentlySendingMultipleWaves()){ this.Log('Cannot change city. Waiting for multiple wave attack to finish...'); t.ClearMultipleWaveTimeout(); t.StartMultipleWaveTimer(); return; }else{ t.ClearMultipleWaveTimeout(); } // change to next city this.autoAttacksThisCity=0; var cityA=null; while(true) { this.autoAttackCityUpto++; cityA=ById('citysel_'+this.autoAttackCityUpto); //~~~ problem here when under attack, the city isn't marked as selected? if(cityA && cityA.className && cityA.className.indexOf('city_selected')>=0) { this.Log('Skip city, current city:'+this.autoAttackCityUpto); this.autoAttackCityUpto++; cityA=ById('citysel_'+this.autoAttackCityUpto); } break; } if(!cityA) { // go back to the 1st city //this.Log('Start from 1st city again'); if(this.autoAttackCityUpto<=2) { // only one city. } else { this.autoAttackCityUpto=1; cityA=ById('citysel_'+this.autoAttackCityUpto); } this.autoAttackCitiesDone++; } if(!cityA || this.autoAttackCitiesDone>=this.options.autoAttackCitiesDoneMax) { // ran out of cities, let's refresh in a minute this.StartReloadPageTimer(); return; } else { if(this.nextAutoAttackTimeout==null) { var secs=t.GetRandTime(1000*t.options.changeCitySecs); this.Log('changing city to:'+this.autoAttackCityUpto+', in '+(secs/1000)+'secs, loop:'+this.autoAttackCitiesDone); this.nextAutoAttackTimeout=setTimeout(function() { t.nextAutoAttackTimeout=null; t.SetValuesCache(); t.ClickChangeCity(cityA,0); },secs); } else { this.Log('cannot change city, about to attack or change city'); } // this.autoAttackCityUpto++; } }, StopWaitForAttackBoxAppear:function() { if(this.waitForAttackBoxAppear!=null) { window.clearTimeout(this.waitForAttackBoxAppear); this.waitForAttackBoxAppear=null; } }, OpenAttackDialog:function(bestAttack) { var t=this; t.StopWaitForAttackBoxAppear(); t.waitForAttackBoxAppear=window.setTimeout(function() { if(t.waitForAttackBoxAppear==null) return; t.waitForAttackBoxAppear=null; t.DoUnsafeWindow('Modal.hideModalAll();'); t.DoUnsafeWindow('Modal.hideModalAll();'); try { // something in the script is triggering a bug in t.DoUnsafeWindow('Modal.hideCurtain();'); t.DoUnsafeWindow('Modal.hideWindow();'); } catch(e) { // ignore } //window.location.reload(true); t.ResetIdStatus(); t.Log("Attack box has not appeared, let's reload the page"); t.ReloadWindow(); //window.setTimeout(function() { // t.OpenAttackDialog(bestAttack); //},0); },15*1000); //~~~ strange things here, sometimes the attack dialog is on screen but modalid is not updated if(ById('modal_attack')) { try { var countOut=10; while(countOut-->=0) { t.Log('modal attck still up'+unsafeWindow.Modal.modalid); var maxi=0; for(var i=0; i<20; i++) { if(ById('modalBox'+i)) { maxi=i; } } t.Log('Closing: '+maxi); unsafeWindow.Modal.modalid=maxi; if(maxi>0) { unsafeWindow.Modal.hideCurtain(); unsafeWindow.Modal.hideWindow(); } else { break; } } }catch(e) { t.Log("Mmm..."+e); } } else { //t.Log('hide all: '+unsafeWindow.Modal.modalid); unsafeWindow.Modal.hideModalAll(); } if (bestAttack.type==0) { unsafeWindow.modal_attack(4,bestAttack.x,bestAttack.y); // Toggle attack waves between suicide and normal mode this.ToggleCurrenttAttackWaveType(bestAttack.x,bestAttack.y); // Update the last attack sent time this.UpdateAttackLastSentTime(); } else if (bestAttack.type==1) { unsafeWindow.modal_attack(1,bestAttack.x,bestAttack.y); } }, nextAutoAttackWanted:null, NextAutoAttack:function() { if(this.nextAutoAttackWanted!=null) { window.clearTimeout(this.nextAutoAttackWanted); this.nextAutoAttackWanted=null; } var autoAttack=this.GetAutoAttack(); if(!this.options.okCities[this.autoAttackCityUpto]) { this.Log('Skip city set in options:'+this.autoAttackCityUpto); this.NextAutoAttackCity(); return; } if(!autoAttack || (autoAttack.x!=undefined && autoAttack.x!=-1)) return; if(this.IsMapperRunning()) { this.StartReloadPageTimer(); return; } var currentTroops=this.GetArmySize(); var currentResources=this.GetResourcesSize(); var mapCoord=this.GetCurrentMapCoord(); var attacks=this.GetClosestAttacks(mapCoord.x,mapCoord.y); //this.Log("Current attacks in system: "+inspect(attacks,10)); var bestAttack=this.FindBiggestCampAttack(attacks,currentTroops,currentResources); if(bestAttack && this.autoAttacksThisCity<10) { // attack closest biggest barbarian/wilderness autoAttack.x=bestAttack.x; autoAttack.y=bestAttack.y; this.SetAutoAttack(autoAttack); this.autoAttackModalWaiting=true; var t=this; // *** we need to wait until the current attack box is off first. var waitedCount=0; var startAttack=function() { waitedCount++; //t.Log('waiting'+waitedCount); if(waitedCount>20) { t.Log('Force close the attack dialog'); t.DoUnsafeWindow('Modal.hideModalAll();'); } var attackBox=document.getElementById('modal_attack'); if(!attackBox) { t.OpenAttackDialog(bestAttack); /* attackBox=document.getElementById('modal_attack'); if(attackBox) { //*** for some reason it doesn't trigger DOMInserted sometimes for the "modal_attack" div if(t.waitForAttackBoxAppear) { t.OnAttackBoxAppear(attackBox); } } */ return; } window.setTimeout(function() { startAttack(); },1000); } startAttack(); } else { autoAttack.x=autoAttack.y=-1; this.SetAutoAttack(autoAttack); // no valid attacks for this city. this.Log("No valid targets, need to attack more targets or wait for troops to return."); this.NextAutoAttackCity(); } }, ///////////////////////// RemoveEmptyReportsDivs:function() { var ss=document.evaluate("./div[@id='modal_msg_reports_tablediv']",document.body,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null); for(var s=0; s<ss.snapshotLength; s++) { var div=ss.snapshotItem(s); if(div.innerHTML=="") { div.parentNode.removeChild(div); } } }, IterateAllianceReports:function(f) { return this.IterateReports('modal_alliance_reports_tablediv',0,f); }, IterateMsgReports:function(f) { return this.IterateReports('modal_msg_reports_tablediv',1,f); }, IterateReports:function(id,colStart,f) { this.RemoveEmptyReportsDivs(); var msgs=ById(id); if(!msgs) return; var trs=msgs.getElementsByTagName('tr'); for(var tUpto=0; tUpto<trs.length; tUpto++) { var tr=trs[tUpto]; var a=nHtml.FindByXPath(tr,".//a[contains(@onclick,'modal_messages_viewreports') or contains(@onclick,'modal_alliance_report_view') or contains(@onclick,'viewMarchReport')]"); if(!a) continue; if(tr.cells.length<(colStart+2)) continue; var descCol=tr.cells[colStart+1]; var dateCol=tr.cells[colStart+0]; var desc=descCol.textContent; var m=this.coordsRe.exec(desc); var x=null,y=null; if(m) { x=m[1]; y=m[2]; } var onclick=a.getAttribute('onclick'); if(onclick) { var m=this.onclickReportRe.exec(onclick); if(m) { x=m[11]; y=m[12]; } } if(!f.call(this,a,tr,desc,x,y)) break; } }, recordingReports:false, replaceReturnRe:/return[^{}]*$/, RecordReports:function() { try { if(this.recordingReports) return; this.recordingReports=true; this.IterateMsgReports(function(a,tr,desc,x,y) { if(x==null || y==null) return true; var onclick=a.getAttribute('onclick').trim(); if(this.IsOnclickMyselfToMyself(onclick)) { return true; } var attack=this.GetAttack(x,y); var saveReportAsAttack = true; if(!attack) { // Don't record reports as attacks if the attack doesn't already exist in the system var saveReportAsAttack = false; } if(!attack) { attack={}; } if(!attack.messages) attack.messages=[]; var onclickWithoutReturn=onclick.replace(this.replaceReturnRe,''); a.href='javascript:'+onclickWithoutReturn; onclick=this.FixOnClick(onclick); var addedAlready=false; for(var m=0; m<attack.messages.length; m++) { if(attack.messages[m][1]==onclick) { addedAlready=true; break; } } var changed=false; if(!addedAlready) { attack.messages.push([desc,onclick]); //this.Log("attack messages: "+attack.messages); var li=this.GetLevelInfo(attack); if(li) attack.levelInfo=li; changed=true; } if(!attack.levelInfo) { // to fix up old scripts where this didn't work. attack.levelInfo=this.GetLevelInfo(attack); if(attack.levelInfo) changed=true; } if(changed && saveReportAsAttack) { this.SetAttack(x,y,attack); } return true; }); } finally { this.recordingReports=false; } }, IsOnclickMyselfToMyself:function(onclick) { if(!onclick) return false; var m=this.onclickReportRe.exec(onclick); if(m && m[6]==m[8] && m[7]==m[9]) { return true; } return false; }, DeleteWildBarbAttacks:function() { var deletes=0; this.IterateMsgReports(function(a,tr,desc,x,y) { var onclick=a.getAttribute('onclick'); if(!onclick) return false; onclick=onclick.trim(); var m=this.onclickReportRe.exec(onclick); if(this.IsOnclickMyselfToMyself(onclick)) { // message to myself } else if(m && m[5]!='0') { return true; } var inps=tr.getElementsByTagName('input'); if(inps.length>=1) { inps[0].checked=true; } deletes++; return true; }); if(deletes>0) { this.DoUnsafeWindow('modal_messages_reports_chkdel();'); } return deletes; }, bringUpReports:false, AddCheckBarbarians:function() { //var msgBody=ById('modal_msg_reports'); var msgBody=ById('modal_msg_reports_tablediv'); if(!msgBody) return; var t=this; var closeReports=true; if(this.autoAttackRemoveReports) { var reportsRemoved=this.DeleteWildBarbAttacks(); if(reportsRemoved==0) { this.autoAttackRemoveReports=false; } else { closeReports=false; } } if(this.bringUpReports && closeReports) { window.setTimeout(function() { t.DoUnsafeWindow('Modal.hideModalAll();'); },t.GetRandTime(3000)); this.bringUpReports=false; } this.ClearMessages(); var a=document.createElement('a'); var t=this; a.addEventListener('click',function() { t.DeleteWildBarbAttacks(); },false); a.className='buttonDown20'; //a.style.paddingLeft='30px'; a.innerHTML='<span>Delete Wild/Barb/Transp</span>'; if(msgBody.nextSibling) { msgBody.nextSibling.insertBefore(a,msgBody.nextSibling.childNodes[0]); //msgBody.nextSibling.appendChild(a); } else { msgBody.appendChild(a); } }, HighlightAllianceReports:function() { var mapCoord=this.GetCurrentMapCoord(); var cities=this.GetSeed().cities; this.IterateAllianceReports(function(a,tr,desc,x,y) { if(x==null || y==null) return true; var closestDist=999999; var closestLoc=null; for(var c=0; c<cities.length; c++) { var city=cities[c]; var cityLoc={'x':city[2],'y':city[3]}; var dist=this.CalcXYDist({'x':x,'y':y},cityLoc); if(dist<closestDist) { closestDist=dist; closestLoc=cityLoc; } } var onclick=a.getAttribute('onclick'); var m=this.onclickReportRe.exec(onclick); if(m && m[5]=='0') { tr.cells[1].style.color='#888'; } if(closestLoc!=null) { var td=tr.insertCell(-1); td.style.textAlign='right'; var loctd=tr.insertCell(-1); AddText(loctd,closestLoc.x+','+closestLoc.y); AddText(td,Math.floor(closestDist) ); } return true; }); }, IterateAttacks:function(f) { if(this.isChrome) { return; } var names=this.browser_listValues(); var attackPrefix='attack_'+this.GetServerId()+'_'; for(var n=0; n<names.length; n++) { var name=names[n]; if(name.substring(0,attackPrefix.length)!=attackPrefix) continue; f(name,this.browser_getValue(name)); } }, prevClearMessages:0, ClearMessages:function() { var nowSecs=new Date().getTime()/1000; if((this.prevClearMessages+(10*60)) > nowSecs) { return; } this.prevClearMessages=nowSecs; var keepReports=this.isChrome?this.options.chromeKeepReports:this.options.keepReports; this.Log('Clear old messages, keeping '+keepReports); if(keepReports<=0) { // must keep at least 1 report to get level information. keepReports=1; } var t=this; this.IterateAttacks(function(name,value) { var attack=JSON2.parse(value); if(attack.messages && attack.messages.length>keepReports) { attack.messages.splice(0,attack.messages.length-keepReports+1); } t.browser_setValue(name,JSON2.stringify(attack)); }); }, SetupClearMessages:function() { var t=this; var cm=document.createElement('input'); cm.type='button'; cm.id='ClearMessages'; cm.style.display='none'; document.body.appendChild(cm); cm.addEventListener('click',function(e) { setTimeout(function() { t.ClearMessages(); },0); },false); }, trainTroopsOnclick:/\(([0-9]+)\)/, AddTrainTroopsLink:function() { var startObj=ById('unit_btns_start'); if(!startObj) return; var onclick=startObj.getAttribute('onclick'); var m=this.trainTroopsOnclick.exec(onclick); if(!m) { return; } var t=this; var type=m[1]; var pnode=startObj.parentNode; var a=document.createElement('a'); a.className='button25'; var setTrainTroopsA=function() { var trainTroops=JSON2.parse(t.GetValue('TrainTroops','{}')); a.innerHTML='<span>'+(trainTroops[t.GetCurrentCityId()]==type?'Auto Train - On':'Auto Train - Off')+'</span>'; } a.addEventListener('click',function() { var trainTroops=JSON2.parse(t.GetValue('TrainTroops','{}')); trainTroops[t.GetCurrentCityId()]=trainTroops[t.GetCurrentCityId()]==type?undefined:type; t.SetValue('TrainTroops',JSON2.stringify(trainTroops)); setTrainTroopsA(); },false); setTrainTroopsA(); //pnode.appendChild(document.createElement('br')); AddText(pnode,' '); pnode.appendChild(a); }, GetCurrentCityId:function() { if(!unsafeWindow.currentcityid) return null; return unsafeWindow.currentcityid; }, // returns {count, maxlevel} getCityBuilding: function(cityId, buildingId){ var b = unsafeWindow.seed.buildings['city'+cityId]; var ret = {count:0, maxLevel:0}; for (var i=1; i<33; i++){ if (b['pos'+i] && b['pos'+i][0] == buildingId){ ++ret.count; if (parseInt(b['pos'+i][1]) > ret.maxLevel) ret.maxLevel = parseInt(b['pos'+i][1]); } } return ret; }, lastTrainTroops:{}, CheckTrainTroops:function() { var t=this; if(!this.GetSeed()) return; var cityid=this.GetCurrentCityId(); var trainTroops=JSON2.parse(this.GetValue('TrainTroops','{}')); //var trainTroops=GM_getValue('TrainTroops_'+this.GetServerId(),0); if(!trainTroops || !trainTroops[cityid]) { return; } var trainTroopId=trainTroops[cityid]; //GM_log('buildTroops'+unsafeWindow.seed.citystats["city" +cityid ]["pop"][0]+"=="+unsafeWindow.seed.citystats["city" + cityid]["pop"][1]); var popAvail=parseInt(unsafeWindow.seed.citystats["city" +cityid ]["pop"][0]); var popTotal=parseInt(unsafeWindow.seed.citystats["city" + cityid]["pop"][1]); var labourTotal=parseInt(unsafeWindow.seed.citystats["city" + cityid]["pop"][3]); var idleTotal=popTotal-labourTotal; var popNeeded=((t.options.percentOfPopToTrain/100)*idleTotal)+labourTotal; // Determine number of available training slots var availableTrainingSlots = 0; try{ var barracksTotal = this.getCityBuilding(cityid, 13).count; var trainingSlotsUsed = unsafeWindow.seed.queue_unt['city'+cityid].length; if(trainingSlotsUsed!=null){ var availableTrainingSlots = barracksTotal-trainingSlotsUsed; } }finally{ if(availableTrainingSlots<1){ return false; } } //GM_log('idleTotal:'+idleTotal+', labourTotal:'+labourTotal+', popneeded:'+popNeeded); if(popAvail>0 && popAvail>=popNeeded) { // avoid over training. var lastTrain=this.lastTrainTroops[cityid]; var nowSecs=new Date().getTime()/1000; if(nowSecs<(lastTrain+(3*60))) { return; } var startButton=ById('unit_btns_start'); if(!startButton) { // let's bring up build troops this.DoUnsafeWindow('modal_barracks_train('+trainTroopId+');') return; } var onclick=startButton.getAttribute('onclick'); var onclickM=/\(([0-9]+)\)/.exec(onclick); if(!onclickM || trainTroopId!=onclickM[1]) { return; } this.lastTrainTroops[cityid]=nowSecs; // let's build troops var numInp=ById('modal_barracks_num'); var maxObj=ById('modal_barracks_max_num'); if(numInp && maxObj) { numInp.value=Math.floor(parseInt(maxObj.textContent)*0.9); var t=this; window.setTimeout(function() { if(numInp.value>maxObj.textContent) { t.Log('Not training troops:'+numInp.value+'>'+maxObj.textContent); return; } //var n=unsafeWindow.modal_barracks_train_max(6); onclick=onclick.replace('return false;',''); window.setTimeout(function() { eval('unsafeWindow.'+onclick); },t.GetRandTime(500)); },t.GetRandTime(500)); } } }, DetermineCurrentPage:function() { if(unsafeWindow.location.href.match(/kingdomsofcamelot\.com\/fb\/.*?\/src\/main_src\.php/i)){ this.currentPage = "koc_game"; }else if (unsafeWindow.location.href.match(/apps\.facebook\.com\/kingdomsofcamelot\/.*?page=nogame/i)) { this.currentPage = "domain_selection_app_page"; }else if (unsafeWindow.location.href.match(/apps\.facebook\.com\/kingdomsofcamelot/i)) { this.currentPage = "app_page"; }else if (unsafeWindow.location.href.match(/facebook.com\/connect\/uiserver.php/i)) { this.currentPage = "facebook_popup"; }else if(unsafeWindow.location.href.match(/kingdomsofcamelot\.com\/fb\/.*?\/src\/newgame_src\.php/i)){ this.currentPage = "domain_selection"; }else{ this.currentPage = "unknown"; } return this.currentPage; }, OnImpendingAttack:function() { var t=this; this.Log("impending attack"); var url=t.options.impendingAttackUrl; if(url!=undefined && url !="") { GM_openInTab(url); } }, CheckImpendingAttack:function() { var r=false; var seed=this.GetSeed(); if(seed && seed.queue_atkinc) { var q=0; // if(unsafeWindow.Object.isArray(seed.queue_atkinc)) { var keys=unsafeWindow.Object.keys(seed.queue_atkinc); if(keys.length>0 && keys.length<16) { //GM_log('impppp'+keys.length); r=true; } // } } //GM_log('imp'+r); /* var topNav=ById('topnav_msg'); if(!topNav || topNav.innerHTML.length==0) return; var redIdx=topNav.innerHTML.indexOf(': red'); var r=redIdx>=0?true:false; if(!r) { GM_log('tnav'+topNav.innerHTML); } */ var t=this; var impendingAttack=this.GetValue('ImpendingAttack',false); if(!impendingAttack && r) { window.setTimeout(function() { t.OnImpendingAttack(); },0); } this.SetValue('ImpendingAttack',r); return r; }, /* current_modal_msg_list:"", CheckMessageLoad:function(page) { var t=this; var msg=ById('modal_msg_list'); if(msg && msg.innerHTML!=t.current_modal_msg_list) { t.current_modal_msg_list=msg.innerHTML; var messageLoad=ById('MessageLoad'); if(!messageLoad) { messageLoad=document.createElement('div'); messageLoad.id='MessageLoad'; messageLoad.style.position='absolute'; messageLoad.style.height='600px'; messageLoad.style.overflow='scroll'; messageLoad.style.top='10px'; messageLoad.style.zIndex='900000'; messageLoad.style.border='5px solid #000'; messageLoad.style.backgroundColor='#fff'; document.body.appendChild(messageLoad); } var m=document.createElement('div'); m.innerHTML=msg.innerHTML; messageLoad.appendChild(m); page++; this.DoUnsafeWindow("modal_messages_listshow('inbox',page);"); } window.setTimeout(function() { t.CheckMessageLoad(page); },200); }, ReadEmails:function() { this.current_modal_msg_list=''; this.CheckMessageLoad(); }, */ FactoryReset:function() { var names=this.browser_listValues(); for(var n=0; n<names.length; n++) { this.browser_setValue(names[n],null); } this.SetOptions({}); }, FactoryResetCurrentServer:function() { var names=this.browser_listValues(); var serverId=this.GetServerId(); for(var n=0; n<names.length; n++) { var name=names[n]; var sid=this.GetServerIdFromName(name); if(sid!=serverId) continue; this.browser_setValue(name,null); } }, GetServerIdFromName:function(n) { var nArr=n.split('_'); if(nArr.length<2) return null; return nArr[1]; }, DeleteAllStoredAttacks:function() { var t=this; this.IterateAttacks(function(name,value) { var nameI=name.split('_'); if(nameI.length<3) return; var xy=nameI[2].split(','); if(value=="") return; var attack=JSON2.parse(value); if(!attack) return; var attackX = xy[0]; var attackY = xy[1]; if(attackX && attackY){ t.DeleteAttack(attackX, attackY); } return true; }); window.alert("All stored attacks for this domain have been deleted.\nClick the ok button to reload."); }, DeleteTransports:function() { var t=this; this.IterateAttacks(function(name,value) { var nameI=name.split('_'); if(nameI.length<3) return; var xy=nameI[2].split(','); if(value=="") return; var attack=JSON2.parse(value); if(!attack) return; var attackX = xy[0]; var attackY = xy[1]; if(attack.type == 1){ t.DeleteAttack(attackX, attackY); } return true; }); window.alert("All stored transports for this domain have been deleted.\nClick the ok button to reload."); }, ListTransports:function() { var t=this; var fTransport = 0; this.IterateAttacks(function(name,value) { var nameI=name.split('_'); if(nameI.length<3) return; var xy=nameI[2].split(','); if(value=="") return; var attack=JSON2.parse(value); if(attack.type == 1){ WinLog.write ("Name: "+name+" Value: "+value); fTransport = 1; return true; } }); if (!fTransport){ WinLog.write ("No Transports Found\n"); return true; } }, ListAttacks:function() { var t=this; this.IterateAttacks(function(name,value) { WinLog.write (name+" "+value); return true; }); }, DetailAttacks:function() { var t=this; var names=GM_listValues(); var currentServerId; var m=/^[a-zA-Z]+([0-9]+)\./.exec(document.location.hostname); if(m) { currentServerId = m[1]; } // Attempt to pull current server id from greasemonkey cache for cross-domain calls if(currentServerId<0){ currentServerId = GM_getValue("KOCAttackLastKnownServerID",-1); } var attackPrefix='attack_'+currentServerId+'_'; for(var n=0; n<names.length; n++) { var name=names[n]; var nameI=name.split('_'); if(nameI.length<3) continue; var xy=nameI[2].split(','); if(name.substring(0,attackPrefix.length)!=attackPrefix) continue; var value = GM_getValue(name); if(value=="") continue; var attack=JSON2.parse(value); attack.xy=xy; if(!attack) continue; t.attacks.push(attack); } }, ExportAllToJSON:function() { var names=this.browser_listValues(); var obj={}; var serverId=this.GetServerId(); for(var n=0; n<names.length; n++) { //for(var n=273; n<names.length; n++) { var name=names[n]; var sid=this.GetServerIdFromName(name); if(sid!=serverId) continue; var v=this.browser_getValue(name,null); if(v!=null && v!=undefined && v!=""){ obj[name]=v; } //n=names.length; } return JSON2.stringify(obj); }, ImportAllFromJSON:function(json) { try { var obj=JSON2.parse(json); if(!obj) { return; } this.FactoryResetCurrentServer(); var serverId=this.GetServerId(); for(var name in obj) { var sid=this.GetServerIdFromName(name); if(sid!=serverId) continue; this.browser_setValue(name,obj[name]); } } catch(e) { window.alert('Import failed'+e); } }, SetupMenu:function() { var t=this; GM_registerMenuCommand('KOCAttack - Options',function() { t.ShowOptionsDialog(); }); GM_registerMenuCommand('KOCAttack - View Attacks',function() { t.ShowViewAttacksDialog(); }); GM_registerMenuCommand('KOCAttack - Auto Attack',function() { t.ToggleAutoAttack(); }); GM_registerMenuCommand('KOCAttack - Factory Reset!',function() { t.FactoryReset(); }); }, /* TimeoutZero:function(f,arg) { setTimeout(function() { f(arg); },0); }, */ pageLoaded:false, prevCurrentCity:-1, inviteFriendsTabHidden:false, idStatus:{}, ResetIdStatus:function() { this.idStatus={}; }, Listen:function() { var t=this; t.SetupMenu(); this.GetValuesCache(); t.ResetAutoAttackTarget(); this.options=this.GetOptions(); this.startListenTime=new Date(); // Determine which page we're on t.DetermineCurrentPage(); // Code strictly for page: koc_game if(t.currentPage == "koc_game"){ window.setTimeout(function() { if(!t.pageLoaded && t.GetAutoAttack() && !t.IsMapperRunning()) { GM_log("whoops, game not loaded after 60 secs problem. reloading."); t.SetValuesCache(); //window.location.reload(true); t.ReloadWindow(); //window.history.go(0); } },t.GetRandTime(60*1000)); if(t.GetAutoAttack()) { window.setTimeout(function() { // press start on the poc timer after we reload if(unsafeWindow.poctoggletimer && unsafeWindow.ispaused) { unsafeWindow.poctoggletimer(); } },5000); } // Hide the invite friends tab on page load if(!t.inviteFriendsTabHidden && t.options.disableInviteFriends){ var tabBar=ById("main_engagement_tabs"); if(tabBar){ var inviteFriendsTab=nHtml.FindByXPath(tabBar,".//a[contains(@onclick,'invite_friends_popup')]"); if(inviteFriendsTab){ inviteFriendsTab.style.display="none"; t.inviteFriendsTabHidden = true; } } } } // End of code strictly for page: koc_game var domTickTimer=null; var domTickUpto=0; var domTick=function(e) { var funcsById={}; // Handle cross-iframe commands (which are currently only being used for the domain selection page) if (t.currentPage == "domain_selection" || t.currentPage == "domain_selection_app_page"){ if((domTickUpto%20)==0) { t.HandleCrossIframeCommands(); } } // Code strictly for page: koc_game if(t.currentPage == "koc_game"){ //if(e.target.className && !/(chat|city|slot)/.exec(e.target.className)) GM_log('xxx:'+e.target.className); //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); var cityId=t.GetCurrentCityId(); var cityChanged=cityId!=t.prevCurrentCity?true:false; if(cityChanged) { t.prevCurrentCity=cityId; } if((domTickUpto%10)==0) { t.HandleChatPane(); } if((domTickUpto%20)==0) { t.CheckImpendingAttack(); } if(cityChanged && cityId!=null) { // changed city setTimeout(function() { t.AddOptionsLink(); t.AddViewAttacksLink(); t.DrawClosestFarms(); },0); setTimeout(function() { t.DetermineCurrentRallyPointLevel(); t.DetermineCurrentMarchesNum(); t.CheckAutoRaiseGold(); t.CheckAbandonWilds(); t.CheckTrainTroops(); },1000); setTimeout(function() { t.CheckReports(); },3000); setTimeout(function() { t.NextAutoAttack(); },5000); } funcsById={ 'castleModalTabs':function(target) { t.OnCastleBoxAppear(target.parentNode); }, 'marketmain_bdy':function(target) { t.OnMarketBoxAppear(target); }, 'modal_attack':function(target) { window.setTimeout(function() { t.OnAttackBoxAppear(target); },250); }, 'barracks_train':function(target) { t.AddTrainTroopsLink(); t.CheckTrainTroops(); }, 'modal_speedup':function(target) { t.ClickShareToWall(target); }, 'invitePopup':function(target) { if(t.options.disableInviteFriends){ // Hide the invite popup if auto attack is enabled target.parentNode.removeChild(target); } }, }; } // End of code strictly for page: koc_game // Handle cross-domain facebook game publish requests funcsById.RES_ID_fb_pop_dialog_table = function(target){ if (t.currentPage == "koc_game") { // Update the current server id locally for cross-domain access if(t.currentServerId>0 && t.currentPage == "koc_game"){ GM_setValue("KOCAttackLastKnownServerID", t.currentServerId); } } } if(t.currentPage == "facebook_popup"){ if((domTickUpto%20)==0) { t.HandlePublishPopup(); } } // Log back into domain if disconnected due to server down-time if(t.currentPage == "domain_selection" && t.options.autoLogBackIn){ if((domTickUpto%20)==0) { t.HandleDomainLogin(); } } /* if(e.target.id && funcsById[e.target.id]) { funcsById[e.target.id](e.target); } else */ //if(e.target.className.indexOf('modalBox')>=0) { var funcCalled=0; if(funcCalled==0) { for(var id in funcsById) { var f=funcsById[id]; var div=ById(id); if(!t.idStatus[id] && div) { var fcall=function(func,d) { funcCalled++; setTimeout(function() { try { func(d); } finally { funcCalled--; } },0); } fcall(f,div); //t.TimeoutZero(f,div); } var divStatus=div?true:false; if(divStatus!=t.idStatus[id]) { //t.Log("Status changed:"+id+","+divStatus); } t.idStatus[id]=divStatus; } } if(!domTickTimer) { domTickTimer=window.setTimeout(function() { domTickTimer=null; domTick(); domTickUpto++; },250); } }; var withinDomInserted=false; if(document.body){ document.body.addEventListener('DOMNodeInserted',function(e) { if(withinDomInserted) return; var isStatuses=(e.target.className && e.target.className=='statues')?true:false; if(isStatuses){ t.pageLoaded=true; } if(e.target.id && e.target.id=='tooltip') { withinDomInserted=true; setTimeout(function() { try { t.DrawLevelIcons(); t.OnToolTipAppear(e.target); } finally { withinDomInserted=false; } },0); } else if(e.target.className && e.target.className.indexOf('modal_msg_reports')>=0) { withinDomInserted=true; setTimeout(function() { try { t.RecordReports(); t.AddCheckBarbarians(); t.HighlightAllianceReports(); } finally { withinDomInserted=false; } },0); } },false); } domTick(); }, }; KOCAttack.Listen(); KOCAttack.SetupClearMessages(); function SetupQuickMarchButton(useRetryMarch) { /* var retryMarch='var retryMarch=function() { alert("retrying march"); new (Ajax.Request)(g_ajaxpath + "ajax/march.php" + g_ajaxsuffix, {'+ 'method: "post",'+ 'parameters: params,'+ 'onSuccess: function (transport) {'+ 'var rslt = eval("(" + transport.responseText + ")");'+ 'if (!rslt.ok) {'+ 'if(rslt.error_code==3) {'+ 'window.setTimeout(function() { retryMarch(); },1000); '+ '} else {'+ 'alert("March Error:"+rslt.msg);'+ '}'+ '}'+ '}'+ '}); };'; */ var retryMarch='var retryMarch=function() { '+ 'new (Ajax.Request)(g_ajaxpath + "ajax/march.php" + g_ajaxsuffix, {'+ 'method: "post",'+ 'parameters: params,'+ 'onSuccess: function(transport) { marchSuccess(transport); },'+ 'onFailure: function () { Modal.hideModalAll(); }'+ '}); };'; if(!useRetryMarch) { retryMarch='var retryMarch=function() { return; };'; } var modalAttackReplaces=[ // *** it says "new Ajax" in the source but firefox converts it to new (Ajax ['modal_attack_do','modal_attack_doOld'], ['onSuccess:','onSuccess: marchSuccess='], // ['Modal.showAlert(printLocalError(','if(rslt.error_code==3 || rslt.error_code==8) { try {retryMarch(); } catch(e) { alert("retry failed:"+e); } } else { Modal.hideModalAll(); } Modal.showAlert(printLocalError('], ['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('] ]; var attack_generatequeueReplaces=[ ['attack_generatequeue','attack_generatequeueOld'], ['class=\\"army\\">" + g_js_strings.commonstr.army + ": "','style=\\"width: 145px !important\\" class=\\"army\\">"'], ['class=\\"name','style=\\"width: 0px !important; display: none;\\" class=\\"name'], ['var u = 0;','var u = "K:"+seed.knights["city" + currentcityid]["knt" + q].combat+", "; '], ['u += parseInt','var x = parseInt'], ['"Count"]);','"Count"]); if(x>0) { var uname=unitcost["unt"+r][0]; u+=uname[0]+uname[uname.length-1]+":"+x+", "; } '], //[/123/g,'100'] ]; if(navigator.userAgent.toLowerCase().indexOf('chrome') > -1) { modalAttackReplaces.push(['new Ajax',"var marchSuccess=null; "+retryMarch+ (useRetryMarch?"":" Modal.hideModalAll(); ")+ "\nnew Ajax"]); } else { modalAttackReplaces.push(['new (Ajax',"var marchSuccess=null; "+retryMarch+ (useRetryMarch?"":" Modal.hideModalAll(); ")+ "\nnew (Ajax"]); } if(!useRetryMarch) modalAttackReplaces.push(['Modal.hideModalAll();','']); var replaceFunc=function(name,replaces) { var modalAttackFunc=window[name].toString(); var nameOld=name+'Old'; for(var a=0; a<replaces.length; a++) { var repI=replaces[a]; var found=false; if(typeof(repI[0])=="object") { found=repI[0].exec(modalAttackFunc)?true:false; } else { found=modalAttackFunc.indexOf(repI[0])>=0?true:false; } if(!found) { //alert("modalAttackReplace: cannot find: "+repI[0]+','+modalAttackFunc); } modalAttackFunc=modalAttackFunc.replace(repI[0],repI[1]); } try { window[nameOld]=eval(modalAttackFunc); //alert(window[nameOld].toString()); } catch(e) { //alert(e+', bad func:'+modalAttackFunc); } window[name]=function() { // let our stuff in addListener run first. window.setTimeout(function() { eval(nameOld+'();'); },100); } }; replaceFunc('modal_attack_do',modalAttackReplaces); replaceFunc('attack_generatequeue',attack_generatequeueReplaces); /* BAD: updateSeed.php doesn't return cityUnits var params = Object.clone(g_ajaxparams); new Ajax.Request(g_ajaxpath + "ajax/updateSeed.php" + g_ajaxsuffix, { method: "post", parameters: params, onSuccess: function (message) { alert(message.responseText); } }); */ } /* function SetupClearMessages() { modal_messages_reports_chkdelOld=modal_messages_reports_chkdel; modal_messages_reports_chkdel=function(type) { var d=document.createElement('div'); d.id='modal_msg_reports_tablediv'; document.body.appendChild(d); modal_messages_reports_chkdelOld(type); if(type=='deleteAll') { document.getElementById('ClearMessages').click(); } }; } */ function CreateMsgDiv() { var m=document.getElementById('KOCAttackMsgDiv'); if(!m) { var ml=document.getElementById('modal_msg_list'); if(!ml) { ml=document.createElement('div'); ml.id='modal_msg_list'; } m=document.createElement('div'); m.style.position='absolute'; m.style.top='0px'; m.style.left='0px'; m.style.width='700px'; m.style.zIndex='900000'; m.style.border='5px solid #000'; m.style.backgroundColor='#fff'; //m.id='modal_attack'; var close=document.createElement('a'); close.addEventListener('click',function() { m.style.display='none'; m.removeChild(ml); },false); close.innerHTML='Close'; close.style.fontSize='20px'; var center=document.createElement('center'); center.appendChild(close); m.appendChild(center); m.appendChild(ml); if(!document.getElementById('modal_msg_list_pagination')) { p=document.createElement('div'); p.id='modal_msg_list_pagination'; ml.appendChild(p); } //document.body.insertBefore(m,document.body.childNodes[0]); if(document.body){ document.body.appendChild(m); } } m.style.display='block'; return m; } function AddScript(js) { var scr=document.createElement('script'); scr.innerHTML=js; document.body.appendChild(scr); } function SetupScripts() { var options=KOCAttack.GetOptions(); var scr=document.createElement('script'); scr.innerHTML="CreateMsgDiv="+CreateMsgDiv+ ";\n"+ // SetupClearMessages+"\n; SetupClearMessages();\n"+ ";\n"+SetupQuickMarchButton+"\n; SetupQuickMarchButton("+options.retryMarch+"); \n"; document.body.appendChild(scr); } var WINLOG_MAX_ENTRIES = 1000; // TODO var WinLog = { state : null, win: null, eOut : null, lastE : null, enabled : true, reverse : true, busy : false, isOpening : false, open : function (){ var t = WinLog; function eventButClear(){ var t = WinLog; t.lastE = null; t.eOut.innerHTML =''; } function eventButReverse(){ var t = WinLog; if (t.busy) return; t.busy = true; if (t.reverse){ t.win.document.getElementById('wlRev').value= 'Top'; t.reverse = false; } else{ t.win.document.getElementById('wlRev').value= 'Bottom'; t.reverse = true; } var n = t.eOut.childNodes.length; if (n < 2) return; for (i=n-2; i>=0; i--){ t.eOut.appendChild (t.eOut.childNodes[i]); } t.busy = false; } if (!t.win || t.win.closed){ t.isOpening = true; t.win = window.open('', 'uwtrace', 'top=30,left=0,width=900,height=700,scrollbars=no,location=no,menubar=no,directories=no,status=no'); t.isOpening = false; t.state = null; } if (t.state == null){ t.win.document.body.innerHTML = '<STYLE>pre{margin:0px} hr{margin:3px; height:1px; border:0px; color:#cee; background-color:#cee}</style>\ <BODY style="margin:0px; padding:0px; border:none">\ <DIV id=winlogtop style="background-color:#d0d0d0; margin:0px; padding:0px; border:1px solid">\ <INPUT id=wlClear type=submit value="Clear"> <INPUT id=wlRev type=submit value="Bottom"></div>\ <DIV id=wlOut style="overflow-y:auto; height:100%; max-height:100%"></div></body>'; t.win.document.getElementById('wlClear').addEventListener('click', eventButClear, false); t.win.document.getElementById('wlRev').addEventListener('click', eventButReverse, false); t.eOut = t.win.document.getElementById('wlOut'); t.state = 1; } }, write : function (msg){ var t = WinLog; if (!t.enabled || t.isOpening) return; t.open(); var te = document.createElement('pre'); var now = new Date(); var m = []; var millis = now.getMilliseconds(); m.push (now.toTimeString().substring (0,8)); m.push ('.'); if (millis<100) m.push('0'); if (millis<10) m.push('0'); m.push(millis); m.push (': '); m.push (msg); te.innerHTML = m.join(''); if (t.reverse){ if (t.lastE == null){ t.eOut.appendChild(te); t.lastE = te; } else { t.eOut.insertBefore(te, t.lastE); } var hr = document.createElement('hr'); t.eOut.insertBefore(hr, te); t.lastE = hr; } else { t.eOut.appendChild(te); t.eOut.appendChild(document.createElement('hr')); } }, }; SetupScripts();
Mozilla add on,User script,Grease Monkey Script, greasemonkey userscripts, updater userscripts mafia wars userscripts mafia wars autoplayer userscripts mafia wars wall userscripts scripts userscripts travian greasemonkey greasemonkey download greasemonkey facebook greasemonkey tutorial greasemonkey youtube greasemonkey travian greasemonkey chrome greasemonkey mafia wars greasemonkey mafia wars autoplayer
Sunday, January 23, 2011
KOC Attack Modded
Subscribe to:
Post Comments (Atom)
0 comments:
Post a Comment