您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Tab to auto build wall defences
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/399252/787075/Fortify.js
/***fortify tab***/ Tabs.Fort = { tabLabel: 'Fortify', tabOrder: 2010, tabColor : 'brown', myDiv: null, timer:null, LoopCounter:0, DefTotal:0, ModelCity: null, ModelCityId: 0, serverwait: false, MaxDefTrain: 0, wall: {}, isBusy: false, QueLength: 0, limitingFactor: null, autodelay: 0, typeDelay: 5, // 5 seconds between each type intervalSecs: 30, // 30 seconds between each loop typearray: {1:[0,1,2,3,4],2:[0,1,2,3,4],3:[0,1,2,3,4],4:[0,1,2,3,4],5:[0,1,2,3,4],6:[0,1,2,3,4],7:[0,1,2,3,4],8:[0,1,2,3,4]}, // change the sort order each time, so every type gets a fair shout LastAuto: -1, Options: { Running: true, packetAmount: 50, doTraps: {1:false,2:false,3:false,4:false,5:false,6:false,7:false,8:false}, doCaltrops: {1:false,2:false,3:false,4:false,5:false,6:false,7:false,8:false}, doSpikes: {1:false,2:false,3:false,4:false,5:false,6:false,7:false,8:false}, doXbows: {1:false,2:false,3:false,4:false,5:false,6:false,7:false,8:false}, doTrebs: {1:false,2:false,3:false,4:false,5:false,6:false,7:false,8:false}, doGreek: {1:false,2:false,3:false,4:false,5:false,6:false,7:false,8:false}, Toggle: false, }, init: function (div) { var t = Tabs.Fort; t.myDiv = div; if (!Options.FortOptions) { Options.FortOptions = t.Options; } else { for (var y in t.Options) { if (!Options.FortOptions.hasOwnProperty(y)) { Options.FortOptions[y] = t.Options[y]; } } } uWExportFunction('cancelFort',Tabs.Fort.cancelFort); uWExportFunction('btDefCancelAll',Tabs.Fort.cancelAll); if (Options.FortOptions.Toggle) AddSubTabLink('AutoFort',t.toggleAutoFortState, 'FortifyToggleTab'); SetToggleButtonState('Fortify',Options.FortOptions.Running,'Fortify'); var m = '<DIV class=divHeader align=center>'+tx('WALL DEFENCE OVERVIEW')+'</div>'; m += '<div align="center">'; m += '<table width=100% height=0% class=xtab><tr><td width=30%><INPUT id=btFortToggle type=checkbox '+ (Options.FortOptions.Toggle?'CHECKED ':'') +'/> '+tx("Add toggle button")+'</td><td colspan=2 align=center><INPUT id=btAutoFortState type=submit value="'+tx("AutoBuild")+' = '+ (Options.FortOptions.Running?'ON':'OFF')+'"></td><td width=30% align=right> </td></tr></table>'; m += '<DIV id=btDefOverviewDiv style="width:'+GlobalOptions.btWinSize.x+'px;overflow-x:auto;"> </div></div><HR>'; m += '<br><DIV style="text-align:center; margin-bottom:5px;">'+uW.g_js_strings.commonstr.city+': <span id=ptdefcity></span></div>'; m += '<a id=btDefOptionLink class=divLink><div class="divHeader" align="left"><img id=btDefOptionArrow height="10" src="'+DownArrow+'"> '+tx('SET DEFENCES')+'</div></a>'; m += '<div id=btDefOption>'; m += '<TABLE align=center cellpadding=0 cellspacing=0 class=xtab width=98%><TR><TD valign=top width=49%>'; m += '<TABLE class=xtab><tr><td colspan=3> </td></tr><tr><TD align=right>'+tx('Defence Type')+': </td><TD colspan=2>'; m += '<SELECT id=btDefType>'; for (var a in uW.fortcost) { var f = parseInt(a.split("frt")[1]); m += '<option value='+f+'>'+uW.fortcost[a][0]+'</option>'; } m += '</select></td></tr><tr><td> </td><td colspan=2>(<span id=btDefMax> </span>)</td></tr>'; m += '<TR><TD align=right>'+tx('Number to build')+': </td><TD><INPUT id=btDefNumPerSlot size=5 type=text value=0\></td>'; m += '<TD><a id=btDefMaxPerSlotButton class="inlineButton btButton brown8"><span>Max</span></a> ('+uW.g_js_strings.commonstr.max; m += ': <span id=btDefMaxPerSlot>0</span>)</td></tr>'; m += '<TR><TD align=right>'+tx('Number of slots to use')+': </td>'; m += '<TD><INPUT id=btDefNumSlots size=2 type=text value=1\></td>'; m += '<TD><a id=btDefMaxSlotsButton class="inlineButton btButton brown8"><span>Max</span></a> ('+uW.g_js_strings.commonstr.max; m += ': <span id=btDefMaxSlots>0</span>)</td></tr>'; m += '<TR><TD align=right>'+tx('Speedup')+': </td><td colspan=2><SELECT id=btDefBoost>'; m += '<option value="0">-- '+uW.g_js_strings.commonstr.select+' --</center></option>'; m += '<option value="26">'+uW.itemlist.i26.name+' ('+(Seed.items.i26?Seed.items.i26:0)+')</option></select></td></tr>'; m += '<tr><td> </td><td colspan=2><INPUT id=btDefButton type=button value="'+uW.g_js_strings.modal_openWalls.builddefenses+'"\></td></tr></table>'; m += '</TD><TD valign=top width=49%><TABLE class=xtab><tr><td><b>'+uW.g_js_strings.commonstr.requirements+':-</b></td></tr>'; m += '<tr><td valign=top id="btDefRequirements"> </td></tr>'; m += '</table>'; m += '</td></tr><tr><td colspan=2><div id=btDefMessages align=center> </div></td></tr></table></div>'; m += '<a id=btDefAutoLink class=divLink><div class="divHeader" align="left"><img id=btDefAutoArrow height="10" src="'+RightArrow+'"> '+tx('AUTO BUILD')+'</div></a>'; m += '<div id=btDefAuto class=divHide>'; m += '<table class=xtab align=center>'; m += '<tr style="vertical-align:top;"><td width=30 rowspan=2><img src="'+IMGURL+'units/unit_60_30.jpg" /></td><td width=15%>'+tx('Traps')+'</td>'; m += '<td width=30 rowspan=2><img src="'+IMGURL+'units/unit_61_30.jpg" /></td><td width=15%>'+tx('Caltrops')+'</td>'; m += '<td width=30 rowspan=2><img src="'+IMGURL+'units/unit_62_30.jpg" /></td><td width=15%>'+tx('Spikes')+'</td>'; m += '<td width=30 rowspan=2><img src="'+IMGURL+'units/unit_53_30.jpg" /></td><td width=15%>'+tx('Crossbows')+'</td>'; m += '<td width=30 rowspan=2><img src="'+IMGURL+'units/unit_55_30.jpg" /></td><td width=15%>'+tx('Trebuchet')+'</td>'; m += '<td width=30 rowspan=2><img src="'+IMGURL+'units/unit_63_30.jpg" /></td><td width=15%>'+tx('Greek Fire')+'</td></tr>'; m += '<tr style="vertical-align:top;"><td><INPUT type=CHECKBOX id=chkDoTraps></td><td><INPUT type=CHECKBOX id=chkDoCaltrops></td>'; m += '<td><INPUT type=CHECKBOX id=chkDoSpikes></td><td><INPUT type=CHECKBOX id=chkDoXbows></td><td><INPUT type=CHECKBOX id=chkDoTrebs></td><td><INPUT type=CHECKBOX id=chkDoGreek></td></tr>'; m += '<tr><td colspan=9 align=left>('+tx('Will queue')+' <INPUT class=btInput id=btDefPacket type=text size=10 maxlength=7 value="'+Options.FortOptions.packetAmount+'"\> '+tx('units at a time until all available wall/field space used')+')</td>'; m += '<td colspan=3 align=right><a class=xlink id=btDefAutoCopy>'+tx('Copy settings to all cities')+'</a> </td></tr></table></div>'; m += '<a id=btDefQueueLink class=divLink><div class="divHeader" align="left"><table cellpadding=0 cellspacing=0 width=100%><tr><td class=xtab><img id=btDefQueueArrow height="10" src="'+DownArrow+'"> '+tx('DEFENCE QUEUE')+'</td><td class=xtab align=right id=btDefQueueStats> </td></tr></table></div></a>'; m += '<div id=btDefQueue style="max-height:200px;overflow-y:scroll;"></div><br>'; div.innerHTML = m; t.ModelCity = new CdispCityPicker('ptdef', ById('ptdefcity'), true, t.clickCitySelect, null); ById('btAutoFortState').addEventListener('click', function(){ t.toggleAutoFortState(this); }, false); ToggleOption('FortOptions','btFortToggle','Toggle'); ById('btDefAutoCopy').addEventListener('click', function(e){ var citynum = Cities.byID[t.ModelCityId].idx+1; t.CopyAutoFortSettings(citynum); saveOptions(); ById('btDefMessages').innerHTML = 'Auto-fortify settings copied to all cities'; }, false); ById('btDefOptionLink').addEventListener ('click', function () {ToggleMainDivDisplay("Defence",100,GlobalOptions.btWinSize.x,"btDefOption",false)}, false); ById('btDefAutoLink').addEventListener ('click', function () {ToggleMainDivDisplay("Defence",100,GlobalOptions.btWinSize.x,"btDefAuto",false)}, false); ById('btDefQueueLink').addEventListener ('click', function () {ToggleMainDivDisplay("Defence",100,GlobalOptions.btWinSize.x,"btDefQueue",false)}, false); ById('btDefType').addEventListener('change', t.PaintCityInfo, false); ById('btDefMaxPerSlotButton').addEventListener('click', function () { var slots = Math.max(parseIntNan(ById('btDefNumSlots').value),0); ById('btDefNumPerSlot').value = parseIntNan(t.MaxDefTrain / slots); t.paintRequirements(ById('btDefType').value); } ,false); ById('btDefNumPerSlot').addEventListener('change', function () { t.paintRequirements(ById('btDefType').value); }, false); ById('btDefNumSlots').addEventListener('change', function () { var slots = Math.max(parseIntNan(ById('btDefNumSlots').value),0); if (slots < 1) { slots = 1; } if (slots > t.wall.wallLevel-t.wall.Queued) { slots = t.wall.wallLevel-t.wall.Queued; } ById('btDefNumSlots').value = slots; ById('btDefMaxPerSlot').innerHTML = parseIntNan(t.MaxDefTrain / slots); } ,false); ById('btDefMaxSlotsButton').addEventListener('click', function () { ById('btDefNumSlots').value = Math.max(t.wall.wallLevel-t.wall.Queued,0); var slots = Math.max(parseIntNan(ById('btDefNumSlots').value),0); ById('btDefMaxPerSlot').innerHTML = parseIntNan(t.MaxDefTrain / slots); } ,false); ChangeIntegerOption('FortOptions','btDefPacket','packetAmount',50); ById('btDefButton').addEventListener ('click', t.setDefences, false); ById('chkDoTraps').addEventListener('change', t.clickCheckDoTraps, false); ById('chkDoCaltrops').addEventListener('change', t.clickCheckDoCaltrops, false); ById('chkDoSpikes').addEventListener('change', t.clickCheckDoSpikes, false); ById('chkDoXbows').addEventListener('change', t.clickCheckDoXbows, false); ById('chkDoTrebs').addEventListener('change', t.clickCheckDoTrebs, false); ById('chkDoGreek').addEventListener('change', t.clickCheckDoGreek, false); // start autotrain loop timer to start in 30 seconds... if (Options.FortOptions.Running) { t.timer = setTimeout(function () { t.doAutoLoop(1,0);}, (30 * 1000)); } }, toggleAutoFortState: function(obj){ var t = Tabs.Fort; obj = ById('btAutoFortState'); if (Options.FortOptions.Running == true) { Options.FortOptions.Running = false; obj.value = tx("AutoBuild = OFF"); } else { Options.FortOptions.Running = true; obj.value = tx("AutoBuild = ON"); t.timer = setTimeout(function () { t.doAutoLoop(1,0);}, 0); } saveOptions(); SetToggleButtonState('Fortify',Options.FortOptions.Running,'Fortify'); t.PaintOverview(); }, show: function (init) { var t = Tabs.Fort; var DispCityId = uW.currentcityid; if (init) { DispCityId = InitialCityId; } if (t.ModelCityId!=DispCityId) { t.ModelCity.selectBut(Cities.byID[DispCityId].idx); } t.PaintOverview(); t.UpdateDefenceOptions(); t.PaintCityInfo(); }, EverySecond : function () { var t = Tabs.Fort; if (tabManager.currentTab.name == 'Fort' && Options.btWinIsOpen){ t.LoopCounter = t.LoopCounter + 1; if (t.LoopCounter%2==0) { // refresh queue display every 2 seconds t.PaintCityInfo(); } if (t.LoopCounter >= 6) { // refresh overview display every 6 seconds t.LoopCounter = 0; t.PaintOverview(); } } }, clickCitySelect: function (city) { var t = Tabs.Fort; t.ModelCityId = city.id; t.LastQueue = 'x'; t.UpdateDefenceOptions(); t.PaintCityInfo(); }, CopyAutoFortSettings : function (citynum) { var t = Tabs.Fort; for (var i = 1; i <= Cities.numCities; i++) { if (i!=citynum) { Options.FortOptions.doTraps[i] = Options.FortOptions.doTraps[citynum]; Options.FortOptions.doCaltrops[i] = Options.FortOptions.doCaltrops[citynum]; Options.FortOptions.doSpikes[i] = Options.FortOptions.doSpikes[citynum]; Options.FortOptions.doXbows[i] = Options.FortOptions.doXbows[citynum]; Options.FortOptions.doTrebs[i] = Options.FortOptions.doTrebs[citynum]; Options.FortOptions.doGreek[i] = Options.FortOptions.doGreek[citynum]; } } }, setDefences: function () { var t = Tabs.Fort; if (t.isBusy) { t.isBusy = false; ById('btDefMessages').innerHTML = '<span style="color:#800;">'+tx('Cancelled')+'!</span>'; ById('btDefButton').value = uW.g_js_strings.modal_openWalls.builddefenses; return; } var cityId = t.ModelCityId; var unitId = ById('btDefType').value; var perSlot = parseIntNan(ById('btDefNumPerSlot').value); var numSlots = parseIntNan(ById('btDefNumSlots').value); var siege = ById('btDefBoost').value; if (perSlot < 1) { return; } if (numSlots < 1) { return; } if (perSlot * numSlots > t.MaxDefTrain) { ById('btDefMessages').innerHTML = '<span style="color:#800;">'+uW.g_js_strings.modal_attack.maxtroops+': '+t.MaxDefTrain + '</span>'; return; } if (numSlots > t.wall.wallLevel-t.wall.Queued) { ById('btDefMessages').innerHTML = '<span style="color:#800;">'+tx('Maximum number of slots exceeded')+'!</span>'; return; } var que = []; for (var i = 0; i < numSlots; i++) { que.push(['T', unitId, perSlot, siege]); } t.QueLength = que.length; t.isBusy = true; ById('btDefButton').value = uW.g_js_strings.commonstr.cancel; t.nextqueue(que); }, nextqueue : function (que){ var t = Tabs.Fort; if(!t.isBusy) { return; } var cmd = que.shift(); if (cmd[0] == 'T') { if (t.QueLength == 1) { ById('btDefMessages').innerHTML = 'Building '+cmd[2]+' '+uW.fortcost['frt'+cmd[1]][0]+' at '+Cities.byID[t.ModelCityId].name; } else { ById('btDefMessages').innerHTML = 'Building '+cmd[2]+' '+uW.fortcost['frt'+cmd[1]][0]+' at '+Cities.byID[t.ModelCityId].name + ' (Slot '+parseIntNan(t.QueLength-que.length)+' of '+t.QueLength+')'; } t.Fortify (t.ModelCityId, cmd[3], cmd[1], cmd[2], function (rslt) { if (rslt.ok) { if (parseIntNan(que.length)==0) { ById('btDefMessages').innerHTML = 'Completed!'; ById('btDefButton').value = uW.g_js_strings.modal_openWalls.builddefenses; t.isBusy = false; return; } setTimeout(function () { t.nextqueue(que) }, 2000); } else { if (rslt.msg) { ById('btDefMessages').innerHTML = '<span style="color:#800;">'+rslt.msg+'</span>'; } else { ById('btDefMessages').innerHTML = '<span style="color:#800;">Error setting defences ('+rslt.error_code+')</span>'; } ById('btDefButton').value = uW.g_js_strings.modal_openWalls.builddefenses; t.isBusy = false; return; } }); } }, clickCheckDoTraps: function () { var t = Tabs.Fort; var cityNo = Cities.byID[t.ModelCityId].idx + 1; Options.FortOptions.doTraps[cityNo] = (ById('chkDoTraps').checked); saveOptions(); if (Options.FortOptions.doTraps[cityNo]) { t.doAutoLoop(cityNo,0); } }, clickCheckDoCaltrops: function () { var t = Tabs.Fort; var cityNo = Cities.byID[t.ModelCityId].idx + 1; Options.FortOptions.doCaltrops[cityNo] = (ById('chkDoCaltrops').checked); saveOptions(); if (Options.FortOptions.doCaltrops[cityNo]) { t.doAutoLoop(cityNo,1); } }, clickCheckDoSpikes: function () { var t = Tabs.Fort; var cityNo = Cities.byID[t.ModelCityId].idx + 1; Options.FortOptions.doSpikes[cityNo] = (ById('chkDoSpikes').checked); saveOptions(); if (Options.FortOptions.doSpikes[cityNo]) { t.doAutoLoop(cityNo,2); } }, clickCheckDoXbows: function () { var t = Tabs.Fort; var cityNo = Cities.byID[t.ModelCityId].idx + 1; Options.FortOptions.doXbows[cityNo] = (ById('chkDoXbows').checked); saveOptions(); if (Options.FortOptions.doXbows[cityNo]) { t.doAutoLoop(cityNo,3); } }, clickCheckDoTrebs: function () { var t = Tabs.Fort; var cityNo = Cities.byID[t.ModelCityId].idx + 1; Options.FortOptions.doTrebs[cityNo] = (ById('chkDoTrebs').checked); saveOptions(); if (Options.FortOptions.doTrebs[cityNo]) { t.doAutoLoop(cityNo,4); } }, clickCheckDoGreek: function () { var t = Tabs.Fort; var cityNo = Cities.byID[t.ModelCityId].idx + 1; Options.FortOptions.doGreek[cityNo] = (ById('chkDoGreek').checked); saveOptions(); if (Options.FortOptions.doGreek[cityNo]) { t.doAutoLoop(cityNo,5); } }, doAutoLoop : function (idx,typ) { var t = Tabs.Fort; clearTimeout(t.timer); if (!Options.FortOptions.Running) return; var cityId = Cities.cities[idx - 1].id; t.autodelay = 0; var ascensionok = (!Options.BuildOptions || !Options.BuildOptions.AscensionReady[idx]); if (t.typearray[idx][typ]==0) { if (Options.FortOptions.doTraps[idx] && t.CheckCanBuild(60,cityId) && ascensionok) { t.doAutoDefence(60,cityId,typ); } } if (t.typearray[idx][typ]==1) { if (Options.FortOptions.doCaltrops[idx] && t.CheckCanBuild(61,cityId) && ascensionok) { t.doAutoDefence(61,cityId,typ); } } if (t.typearray[idx][typ]==2) { if (Options.FortOptions.doSpikes[idx] && t.CheckCanBuild(62,cityId) && ascensionok) { t.doAutoDefence(62,cityId,typ); } } if (t.typearray[idx][typ]==3) { if (Options.FortOptions.doXbows[idx] && t.CheckCanBuild(53,cityId) && ascensionok) { t.doAutoDefence(53,cityId,typ); } } if (t.typearray[idx][typ]==4) { if (Options.FortOptions.doTrebs[idx] && t.CheckCanBuild(55,cityId) && ascensionok) { t.doAutoDefence(55,cityId,typ); } } if (t.typearray[idx][typ]==5) { if (Options.FortOptions.doGreek[idx] && t.CheckCanBuild(63,cityId) && ascensionok) { t.doAutoDefence(63,cityId,typ); } } if (typ<5) { t.timer = setTimeout(function () { t.doAutoLoop(idx,typ+1); }, (t.autodelay * 1000)); } else { // if training happened in this city during this loop, change type order of this city for next time so every type gets a fair go.. if (t.LastAuto != -1) { for (var v=0; v<=6; v++) { t.LastAuto++; if (t.LastAuto > 5) { t.LastAuto = 0; } t.typearray[idx][v] = t.LastAuto; } t.LastAuto = -1; } if (idx == Cities.numCities) { t.timer = setTimeout(function () { t.doAutoLoop(1,0); }, (t.intervalSecs * 1000)); } else { t.timer = setTimeout(function () { t.doAutoLoop(idx+1,0); }, (t.autodelay * 1000)); } } }, doAutoDefence: function (defType,cityId,typ) { var t = Tabs.Fort; var numberToTrain = t.getMaxDefence(defType,cityId,true); if (numberToTrain > 0) { if (numberToTrain > Options.FortOptions.packetAmount) { numberToTrain = Options.FortOptions.packetAmount; } t.Fortify(cityId, 0, defType, numberToTrain); t.autodelay = t.typeDelay; t.LastAuto = typ; } }, getMaxDefence: function (defType,cityId,auto) { var t = Tabs.Fort; var numberToTrain = 0; t.limitingFactor = null; var wall = {}; getWallInfo(cityId, wall); if (defType<60 || defType==63) { var availableSpace = wall.wallSpace - wall.wallSpaceUsed - wall.wallSpaceQueued; } else { var availableSpace = wall.fieldSpace - wall.fieldSpaceUsed - wall.fieldSpaceQueued; } var MaxSlots = wall.wallLevel; if (auto && MaxSlots > 5) MaxSlots = 5; // only allow auto build to occupy 5 slots if (availableSpace > 0 && wall.slotsBusy < MaxSlots) { var availableSlots = MaxSlots - wall.slotsBusy; var unitSpace = parseInt(uW.fortstats["unt" + defType][5]); var food = parseIntNan(Seed.resources['city' + cityId].rec1[0] / 3600); var wood = parseIntNan(Seed.resources['city' + cityId].rec2[0] / 3600); var stone = parseIntNan(Seed.resources['city' + cityId].rec3[0] / 3600); var ore = parseIntNan(Seed.resources['city' + cityId].rec4[0] / 3600); // change these numbers for auto if in the future you want KEEP resource values in city. var foodRes = 0; var woodRes = 0; var stoneRes = 0; var oreRes = 0; var availFood = food - foodRes; var availWood = wood - woodRes; var availStone = stone - stoneRes; var availOre = ore - oreRes; var unitFood = parseInt(uW.fortcost['frt'+defType][1]); var unitWood = parseInt(uW.fortcost['frt'+defType][2]); var unitStone = parseInt(uW.fortcost['frt'+defType][3]); var unitOre = parseInt(uW.fortcost['frt'+defType][4]); if (defType == 63) var unitMedian = uW.fortcost['frt'+defType][11]["34002"]; var median = parseIntNan(Seed.items.i34002); // greek fire requires median oil numberToTrain = 9999999999; if ((availFood / unitFood) < numberToTrain) { t.limitingFactor = uW.resourceinfo['rec1']; numberToTrain = parseInt(availFood / unitFood); } if ((availWood / unitWood) < numberToTrain) { t.limitingFactor = uW.resourceinfo['rec2']; numberToTrain = parseInt(availWood / unitWood); } if ((availStone / unitStone) < numberToTrain) { t.limitingFactor = uW.resourceinfo['rec3']; numberToTrain = parseInt(availStone / unitStone); } if ((availOre / unitOre) < numberToTrain) { t.limitingFactor = uW.resourceinfo['rec4']; numberToTrain = parseInt(availOre / unitOre); } if (defType == 63) { if ((median / unitMedian) < numberToTrain) { t.limitingFactor = 'median'; numberToTrain = parseInt(median / unitMedian); } } if (availableSpace >= unitSpace && availableSlots > 0) { if (availFood > unitFood && availWood > unitWood & availStone > unitStone & availOre > unitOre) { if ((availableSpace / unitSpace) < numberToTrain) { numberToTrain = parseInt(availableSpace / unitSpace); } } else { numberToTrain = 0; } } else { numberToTrain = 0; } } return numberToTrain; }, CheckCanBuild : function (defType,cityId) { var t = Tabs.Fort; var Result = true; var Buildings = getCityBuildings(cityId); var fc = uW.fortcost['frt'+defType]; if (matTypeof(fc[8]) == 'object'){ for (var k in fc[8]){ var b = Buildings[k.substr(1)]; if (b.maxLevel < fc[8][k][1]){ Result = false; break; } } } if (matTypeof(fc[9]) == 'object'){ for (var k in fc[9]){ if (parseInt(Seed.tech['tch'+k.substr(1)]) < fc[9][k][1]){ Result = false; break; } } } return Result; }, PaintOverview : function () { var t = Tabs.Fort; var rownum = 0; var irows = []; var rows = []; function _row(name, row, noTotal, icon) { var t = Tabs.Fort; if (rownum++ % 2) { style = ' class="evenRow"'; } else { style = ' class="oddRow"'; } var tot = 0; var m = []; m.push('<TR align=right'); m.push(style); if (noTotal) { m.push('><TD colspan=2'); } else { m.push('><TD'); } m.push(' style="padding-left: 0px;"'); m.push('>'); if (icon) { m.push(icon); } else { m.push('<B>'+name+' </B>'); } m.push('</td>'); if (!noTotal) { for (var i = 0; i < row.length; i++) tot += row[i]; m.push('<TD><div class="totalCell xtabBorder">'); t.DefTotal[name] = tot; m.push(addCommas(tot)); m.push('</div></td>'); } for (var i = 0; i < row.length; i++) { m.push('<TD'); m.push(style); m.push('><div class=xtabBorder>'); m.push(addCommas(row[i])); m.push('</div></td>'); } m.push('</tr>'); return m.join(''); } var m = '<TABLE width=98% class=xtab cellpadding=1 cellspacing=0 align=center style="font-size:'+Options.OverviewOptions.OverviewFontSize+'px;"><TR valign=bottom><td width=20> </td><td align=right width=100><b> </b></td>'; for (var i = 1; i <= Cities.numCities; i++) { m += '<TD style="font-size:11px;" align=center width=100><span id="btDefCity_'+i+'"><B>'+Cities.cities[i-1].name.substring(0, 12)+'</b></span></td>'; } m += "<td> </td></tr>"; // spacer irows = []; irows[0] = []; // wall level irows[1] = []; // Defensive Tower Level irows[2] = []; // Wall Space irows[3] = []; // Field Space irows[4] = []; // Defence Queue irows[5] = []; // Redoubt Tower Level for (var i = 0; i < Cities.numCities; i++) { cityId = Cities.cities[i].id; var wall = {}; getWallInfo(cityId,wall); irows[0][i] = uW.g_js_strings.commonstr.level+' '+wall.wallLevel; if (wall.wallLevel==0) { irows[0][i] = '<SPAN class=boldRed><B>'+tx('None')+'!</b></span>'; } var tower = Seed.buildings['city'+cityId].pos99; if (tower) tower = parseInt(Seed.buildings['city'+cityId].pos99[1]) if (!tower) irows[1][i] = '<SPAN class=boldRed><B>'+tx('None')+'!</b></span>'; else irows[1][i] = uW.g_js_strings.commonstr.level+' '+tower; var tower = Seed.buildings['city'+cityId].pos98; if (tower) tower = parseInt(Seed.buildings['city'+cityId].pos98[1]) if (!tower) irows[5][i] = '<SPAN class=boldRed><B>'+tx('None')+'!</b></span>'; else irows[5][i] = uW.g_js_strings.commonstr.level+' '+tower; irows[2][i] = wall.wallSpaceUsed+' / '+wall.wallSpace; if (wall.wallSpaceUsed < wall.wallSpace) { irows[2][i] = '<SPAN class=boldRed><B>'+irows[2][i]+'</b></span>'; } irows[3][i] = wall.fieldSpaceUsed+' / '+wall.fieldSpace; if (wall.fieldSpaceUsed < wall.fieldSpace) { irows[3][i] = '<SPAN class=boldRed><B>'+irows[3][i]+'</b></span>'; } var totTime = 0; var now = unixTime(); var q = Seed.queue_fort['city'+cityId]; if (q != null && q.length > 0) totTime = q[q.length - 1][3] - now; if (totTime < 0) totTime = 0; if (totTime < 1 && (wall.wallSpaceUsed < wall.wallSpace - 4 || wall.fieldSpaceUsed < wall.fieldSpace - 4)) irows[4][i] = '<SPAN class=boldRed><B>' + timestr(totTime) + '</b></span>'; else irows[4][i] = timestr(totTime); } m += _row(tx('Wall Space'), irows[2], true); rows = []; var r = 0; for (var a in uW.fortcost) { var f = parseInt(a.split("frt")[1]); if (f<60 || f==63) { rows[r] = []; for (var i = 0; i < Cities.numCities; i++) { cityId = Cities.cities[i].id; rows[r][i] = parseIntNan(Seed.fortifications["city" + cityId]["fort"+f]); } m += _row(uW.fortcost[a],rows[r],false,TroopImage(f)); r++; } } m += _row(tx('Field Space'), irows[3], true); for (var a in uW.fortcost) { var f = parseInt(a.split("frt")[1]); if (f>=60 && f!=63) { rows[r] = []; for (var i = 0; i < Cities.numCities; i++) { cityId = Cities.cities[i].id; rows[r][i] = parseIntNan(Seed.fortifications["city" + cityId]["fort"+f]); } m += _row(uW.fortcost[a],rows[r],false,TroopImage(f)); r++; } } m += '<TR><TD> </td></tr>'; m += _row(tx('Walls'), irows[0], true); m += _row(tx('Def. Tower'), irows[1], true); m += _row(tx('Redoubt Tower'), irows[5], true); m += _row(tx('Defence Queue'), irows[4], true); m += '</table>'; ById('btDefOverviewDiv').innerHTML = m; }, fixQueTimes: function (q) { // fix KofC bugs .... // if first start time > now, make it now // if any end time != next start time then fix it var now = unixTime(); if (q[0][2] > now) { q[0][2] = now; } for (var i = 0; i < q.length; i++) { if (q[i + 1] != null && q[i + 1][2] != q[i][3]) { q[i][3] = q[i + 1][2]; } } }, expireTheQueue: function (q) { if (q == null) return; var now = unixTime(); while (q.length > 0 && (q[0][3] - now) < 1) q.shift(); }, UpdateDefenceOptions : function () { var t = Tabs.Fort; ById('chkDoTraps').checked = Options.FortOptions.doTraps[Cities.byID[t.ModelCityId].idx + 1]; ById('chkDoCaltrops').checked = Options.FortOptions.doCaltrops[Cities.byID[t.ModelCityId].idx + 1]; ById('chkDoSpikes').checked = Options.FortOptions.doSpikes[Cities.byID[t.ModelCityId].idx + 1]; ById('chkDoXbows').checked = Options.FortOptions.doXbows[Cities.byID[t.ModelCityId].idx + 1]; ById('chkDoTrebs').checked = Options.FortOptions.doTrebs[Cities.byID[t.ModelCityId].idx + 1]; ById('chkDoGreek').checked = Options.FortOptions.doGreek[Cities.byID[t.ModelCityId].idx + 1]; }, PaintCityInfo : function () { var t = Tabs.Fort; var cityId = t.ModelCityId; if (cityId==0) { return; } if (t.serverwait) { return; } // paint the Queue... var now = unixTime(); t.wall = {}; getWallInfo(cityId, t.wall); t.wall.Queued = 0; var totTime = 0; var q = Seed.queue_fort['city' + cityId]; t.expireTheQueue(q); var qs = q.toString(); if (q != null && q.length > 0) { totTime = q[q.length - 1][3] - now; t.wall.Queued = q.length; } if (qs == t.LastQueue) { // queue hasn't changed, just update the time of the current item if (q != null && q.length > 0) { var cur = q[0][3] - now; ById('btDefQueueRemaining').innerHTML = timestr(cur, true); } else { m = '<br><div align=center style="opacity:0.3;">'+tx('No Defence Units Under Construction')+'</div>'; ById('btDefQueue').innerHTML = m; } } else { t.LastQueue = qs; if (q != null && q.length > 0) { m = '<TABLE width=98% cellspacing=0 align=center class=xtab><tr><th class=xtabHD align=left>'+uW.g_js_strings.commonstr.type+'</th><th class=xtabHD align=right>'+uW.g_js_strings.commonstr.amount+'</th><th class=xtabHD align=right>'+tx('Total Time')+'</th><th class=xtabHD align=right>'+tx('Remaining')+'</th><th class=xtabHD align=right><a id=btDefCancelAllButton class="inlineButton btButton red14" onclick="btDefCancelAll('+cityId+')"><span>'+tx('Cancel All')+'</span></a></th></tr>'; t.fixQueTimes(q); first = true; var lastEnd = now; var r = 0; for (var i = 0; i < q.length; i++) { start = q[i][2]; end = q[i][3]; actual = end - lastEnd; if (actual < 0) { actual = 0; } rowClass = 'evenRow'; if (r % 2 == 1) rowClass = 'oddRow'; if (first) rowClass += ' highRow'; m += '<TR class="'+rowClass+'"><TD align=left>'+TroopImage(q[i][0])+uW.fortcost["frt"+q[i][0]][0]+'</td><td align=right>'+addCommas(q[i][1])+'</td><td align=right>'; if (first) { m += timestr(end - start, true) + '</td><TD align=right><SPAN id=btDefQueueRemaining>' + timestr(actual, true) + '</span></td>'; } else { m += timestr(actual, true) + '</td><td align=right> </td>'; } m += '<td align=right><A class="inlineButton btButton brown11" onclick="cancelFort(' + q[i][0] + ',' + q[i][1] + ',' + q[i][2] + ',' + q[i][3] + ',' + q[i][5] + ',' + q[i][6] + ',' + cityId + ',' + i + ')"><span>'+uW.g_js_strings.commonstr.cancel+'</span></a></td></tr>' lastEnd = end; first = false; r++; } m += '</table><div align=center id=btDefQueueMessage> </div>'; } else { m = '<br><div align=center style="opacity:0.3;">'+tx('No Defence Units Under Construction')+'</div>'; } ById('btDefQueue').innerHTML = m; ResetFrameSize('btMain',100,GlobalOptions.btWinSize.x); } m = t.wall.Queued+' '+uW.g_js_strings.commonstr.of+' '+t.wall.wallLevel; if (totTime > 0) m += ', ' + uW.timestr(totTime); ById('btDefQueueStats').innerHTML = m; // paint info into the city panel... var unitId = ById('btDefType').value; var defOwned = parseInt(Seed.fortifications['city' + cityId]['fort' + unitId]); t.MaxDefTrain = 0; if (t.CheckCanBuild(unitId,cityId)) { t.MaxDefTrain = t.getMaxDefence(unitId,cityId); } ById('btDefMax').innerHTML = uW.g_js_strings.commonstr.max + ': ' + t.MaxDefTrain + ', ' + uW.g_js_strings.commonstr.owned + ': ' + defOwned; ById('btDefMaxSlots').innerHTML = t.wall.wallLevel-t.wall.Queued; var slots = Math.max(parseIntNan(ById('btDefNumSlots').value),0); ById('btDefMaxPerSlot').innerHTML = parseIntNan(t.MaxDefTrain / slots); // paint the requirements... t.paintRequirements(unitId); }, paintRequirements : function (unitId) { var t = Tabs.Fort; var cityId = t.ModelCityId; var Buildings = getCityBuildings(cityId); var m = ''; if (uW.fortcost['frt'+unitId][8] && matTypeof(uW.fortcost['frt'+unitId][8]) === "object") { for (var b in uW.fortcost['frt'+unitId][8]) { var bid = b.split("b")[1]; var reqlevel = uW.fortcost['frt'+unitId][8][b][1]; var blvl = Buildings[bid].maxLevel; var linestyle = '<span>'; if (blvl < reqlevel) { linestyle = '<span style="color:#800;"><b>'; m += linestyle+'Level '+reqlevel+' '+uW.buildingcost['bdg'+bid][0]+'</b></span><br>'; } } } if (uW.fortcost['frt'+unitId][9] && matTypeof(uW.fortcost['frt'+unitId][9]) === "object") { for (var r in uW.fortcost['frt'+unitId][9]) { var rid = r.split("t")[1]; var reqlevel = uW.fortcost['frt'+unitId][9][r][1]; var rlvl = Seed.tech['tch'+rid]; var linestyle = '<span>'; if (rlvl < reqlevel) { linestyle = '<span style="color:#800;"><b>'; m += linestyle+'Level '+reqlevel+' '+uW.techcost['tch'+rid][0]+'</b></span><br>'; } } } m += '<table class=xtab cellpadding=0 cellspacing=0 width=100%>'; for (var r = 1; r < 5; r++) { if (uW.fortcost['frt'+unitId][r] != 0) { m += '<tr><td>'; if (r==1) { m += ResourceImage(FoodImage,uW.g_js_strings.commonstr.food); } else { if (r==2) { m += ResourceImage(WoodImage,uW.g_js_strings.commonstr.wood); } else { if (r==3) { m += ResourceImage(StoneImage,uW.g_js_strings.commonstr.stone); } else { if (r==4) { m += ResourceImage(OreImage,uW.g_js_strings.commonstr.ore); } } } } var reqlevel = uW.fortcost['frt'+unitId][r]*parseIntNan(ById('btDefNumPerSlot').value); var rlvl = parseIntNan(Seed.resources['city'+cityId]['rec'+r][0]/3600); var linestyle = '<span>'; if ((rlvl <= reqlevel) || (t.limitingFactor==uW.resourceinfo['rec'+r])) { linestyle = '<span style="color:#800;"><b>'; } m += '</td><td>'+linestyle+addCommas(reqlevel)+' / '+addCommas(rlvl)+'</b></span></td></tr>'; } } if (uW.fortcost['frt'+unitId][11] && matTypeof(uW.fortcost['frt'+unitId][11]) === "object") { for (var r in uW.fortcost['frt'+unitId][11]) { var iid = r; var reqlevel = uW.fortcost['frt'+unitId][11][r]*parseIntNan(ById('btDefNumPerSlot').value); var ilvl = parseIntNan(Seed.items['i'+iid]); var linestyle = '<span>'; if ((ilvl <= reqlevel) || (iid==34002 && t.limitingFactor=="median")) { linestyle = '<span style="color:#800;"><b>'; } m += '<tr><td>'+ResourceImage(getItemImageURL(iid),uW.itemlist['i'+iid].name)+'</td><td>'; m += linestyle+reqlevel+' / '+ilvl+'</b></span></td></tr>'; } } m += '</table>'; var perSlot = parseIntNan(ById('btDefNumPerSlot').value); if (perSlot!=0) { var time = t.getFortifyTime(cityId,unitId,perSlot); if (ById('btDefBoost').value==26) { time=parseInt(time*0.7); } m += '<br>'+tx('Estimated Time')+': '+timestr(time); } ById('btDefRequirements').innerHTML = m; }, cancelAll: function (cityId,silent) { var t = Tabs.Fort; jQuery('#btDefCancelAllButton').addClass("disabled"); var delayer = 0; var q = Seed.queue_fort['city' + cityId]; for (var i = q.length-1; i >= 0; i--) { delayer = delayer + 1; setTimeout (t.cancelFort,(1000*delayer),q[i][0],q[i][1],q[i][2],q[i][3],q[i][5],q[i][6],cityId,i,silent); // spread them out ... } delayer = delayer + 1; setTimeout (function () { jQuery('#btDefCancelAllButton').removeClass("disabled"); },(1000*delayer)); }, cancelFort: function (typefrt, numtrpfrt, frtTmp, frtETA, frtNeeded, frtid, cityId, queueId, silent) { var t = Tabs.Fort; t.serverwait = true; if (!silent) ById('btDefQueueMessage').innerHTML = 'Cancelling Queued Item...'; var params = uW.Object.clone(uW.g_ajaxparams); params.pf = 0; params.requestType = "CANCEL_FORTIFICATIONS"; params.cityId = cityId; params.typefrt = typefrt; params.numtrpfrt = numtrpfrt; params.frtETA = frtETA; params.frtTmp = frtTmp; params.frtNeeded = frtNeeded; params.frtid = frtid; new MyAjaxRequest(uW.g_ajaxpath + "ajax/cancelFortifications.php" + uW.g_ajaxsuffix, { method: "post", parameters: params, onSuccess: function (rslt) { if (rslt.ok) { var k = 0; for (var j = 0; j < Seed.queue_fort["city" + cityId].length; j++) { if (j > queueId) { Seed.queue_fort["city" + cityId][j][2] = parseInt(rslt.dateFortifications[k]["start"]); Seed.queue_fort["city" + cityId][j][3] = parseInt(rslt.dateFortifications[k]["end"]); k++; } } Seed.queue_fort["city" + cityId].splice(queueId, 1); for (var i = 1; i < 5; i++) { var totalReturn = parseInt(uW.fortcost["frt" + typefrt][i]) * parseInt(numtrpfrt) * 3600 / 2; Seed.resources["city" + cityId]["rec" + i][0] = parseInt(Seed.resources["city" + cityId]["rec" + i][0]) + totalReturn; } t.PaintCityInfo(); } else { if (rslt.msg) { if (!silent) { ById('btDefQueueMessage').innerHTML = '<span style="color:#f00">'+rslt.msg+'</span>'; }} else { if (!silent) { ById('btDefQueueMessage').innerHTML = '<span style="color:#f00">Error cancelling defence queue item</span>'; }} } t.serverwait = false; }, onFailure: function () { if (!silent) { ById('btDefQueueMessage').innerHTML = '<span style="color:#f00;">AJAX Error!</span>'; } t.serverwait = false; }, },true); }, getFortifyTime : function (cityId,unitId,num) { var b=parseInt(parseInt(uW.fortcost["frt"+unitId][7])); var f=1; f+=0.1*parseInt(Seed.tech.tch16); var a=0; var c=Seed.knights["city"+cityId]; if(c){ c=c["knt"+Seed.leaders["city"+cityId].politicsKnightId]; if(c){ a=parseInt(c.combat); newkntlv=((parseInt(c.politicsBoostExpireUnixtime)-uW.unixtime())>0)?(a*1.25):a; // removed because this is not in server calculation // f=f+(0.005*newkntlv) } } if(Seed.tech2 && Seed.tech2.tch3){ f+=parseFloat(Seed.tech2.tch3)*0.05 } b=Math.max(1,(b/f)); return b*num; }, Fortify : function (cityId, siege, unitId, num, notify) { var t = Tabs.Fort; var citynum = Cities.byID[cityId].idx+1; jQuery('#btDefCity_'+citynum).css('color', 'green'); var time = t.getFortifyTime(cityId,unitId,num); if (siege==26) { time=parseInt(time*0.7); } var params = uW.Object.clone(uW.g_ajaxparams); params.cid = cityId; params.type = unitId; params.quant = num; params.items = siege; new MyAjaxRequest(uW.g_ajaxpath + "ajax/fortify.php" + uW.g_ajaxsuffix, { method: "post", parameters: params, onSuccess: function (rslt) { if (rslt.ok) { uW.seed.queue_fort["city" + cityId].push(uWCloneInto([unitId, num, rslt.initTS, parseInt(rslt.initTS) + rslt.timeNeeded, 0, rslt.timeNeeded, rslt.fortifyId])); if (siege==26) { Seed.items.i26 = parseInt(Seed.items.i26)-1; uW.ksoItems[26].subtract(); } if (unitId==63) { Seed.items.i34002 = parseInt(Seed.items.i34002)-num; uW.ksoItems[34002].subtract(num); } actionLog(Cities.byID[cityId].name+': Building '+num+' '+uW.fortcost['frt'+unitId][0],'DEFENCE'); t.PaintCityInfo(); } else { if (rslt.msg) { actionLog(Cities.byID[cityId].name+': Failed to build '+num+' '+uW.fortcost['frt'+unitId][0]+' ('+rslt.msg+')','DEFENCE'); } else { actionLog(Cities.byID[cityId].name+': Failed to build '+num+' '+uW.fortcost['frt'+unitId][0]+' ('+rslt.error_code+')','DEFENCE'); } } jQuery('#btDefCity_'+citynum).css('color', 'rgb('+HEXtoRGB(Options.Colors.PanelText).r+','+HEXtoRGB(Options.Colors.PanelText).g+','+HEXtoRGB(Options.Colors.PanelText).b+')'); if (notify) { notify(rslt); } }, onFailure: function () { actionLog(Cities.byID[cityId].name+': Failed to build '+num+' '+uW.fortcost['frt'+unitId][0]+' (Ajax Error)','DEFENCE'); jQuery('#btDefCity_'+citynum).css('color', 'rgb('+HEXtoRGB(Options.Colors.PanelText).r+','+HEXtoRGB(Options.Colors.PanelText).g+','+HEXtoRGB(Options.Colors.PanelText).b+')'); if (notify) { notify({msg: 'AJAX error'}); } }, },true); // noretry }, }