您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Script for Ikariam V 0.5.x, Overview tables for Ress, buildings and mititary, desktop versions in the style of Ikariam Empire Board
当前为
// ==UserScript== // @name Empire Overview // @author germano // @description Script for Ikariam V 0.5.x, Overview tables for Ress, buildings and mititary, desktop versions in the style of Ikariam Empire Board // @namespace Test // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // @grant GM_registerMenuCommand // @grant GM_deleteValue // @grant GM_xmlhttpRequest // @grant GM_openInTab // @include http://s*.ikariam.gameforge.*/index.php* // @exclude http://board.*.ikariam.gameforge.com* // @exclude http://*.ikariam.gameforge.*/board // // @require http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js // @require http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js // // @version 1.1661 // // ==/UserScript== /*********************************************************************************************************************** * Includes ********************************************************************************************************************* */ ;(function($){ var jQuery = $; if(window.navigator.vendor.match(/Google/)) { var isChrome = true; } if(!isChrome) { this.$ = this.jQuery = jQuery.noConflict(true); } $.extend({ exclusive : function(arr) { return $.grep(arr, function(v, k) { return $.inArray(v, arr) === k; }); }, mergeValues : function(a, b, c) { var length = arguments.length; if(length == 1 || typeof arguments[0] !== "object" || typeof arguments[1] !== "object") { return arguments[0]; } var args = jQuery.makeArray(arguments); var i = 1; var target = args[0]; for(; i < length; i++) { var copy = args[i]; for(var name in copy) { if(!target.hasOwnProperty(name)) { target[name] = copy[name]; continue; } if(typeof target[name] == "object" && typeof copy[name] == "object") { target[name] = jQuery.mergeValues(target[name], copy[name]) } else if(copy.hasOwnProperty(name) && copy[name] != undefined) { target[name] = copy[name] } } } return target }, decodeUrlParam: function(string) { var str = string.split('?').pop().split('&'); var obj = {}; for(var i = 0; i < str.length; i++) { var param = str[i].split('='); if(param.length !== 2) { continue; } obj[param[0]] = decodeURIComponent(param[1].replace(/\+/g, " ")) } return obj } }); var events = (function() { var _events = {}; var retEvents = function(id) { var callbacks, topic = id && _events[ id ]; if(!topic) { callbacks = $.Callbacks(""); topic = { pub : callbacks.fire, sub : callbacks.add, unsub: callbacks.remove }; if(id) { _events[ id ] = topic; } } return topic; }; retEvents.scheduleAction = function(callback, time) { return clearTimeout.bind(undefined, setTimeout(callback, time || 0)); }; retEvents.scheduleActionAtTime = function(callback, time) { return retEvents.scheduleAction(callback, (time - $.now() > 0 ? time - $.now() : 0)) }; retEvents.scheduleActionAtInterval = function(callback, time) { return clearInterval.bind(undefined, setInterval(callback, time)); }; return retEvents })(); /*********************************************************************************************************************** * Globals **********************************************************************************************************************/ var debug = false; var log = false; var timing = false; if(!unsafeWindow) unsafeWindow = window; /*********************************************************************************************************************** * Inject button into page before the page renders the YUI menu or it will not be animated (less work) **********************************************************************************************************************/ $('.menu_slots > .expandable:last').after('<li class="expandable slot99 empire_Menu" onclick=""><div class="empire_Menu image" style="background-image: url(skin/minimized/weltinfo.png); background-position: 0px 0px; background-size:33px auto"></div></div><div class="name"><span class="namebox">Empire Overview</span></div></li>'); /*********************************************************************************************************************** * Utility Functions **********************************************************************************************************************/ var Utils = { wrapInClosure : function(obj) { return (function(x) { return function() { return x } })(obj) }, existsIn : function(input, test) { try { var ret = input.indexOf(test) !== -1 } catch(e) { return false } return ret; }, estimateTravelTime: function(city1, city2) { if(!city1 || !city2) return 0; if(city1[0] == city2[0] && city1[1] == city2[1]) { var time = 1200 / 60 * 0.5; } else { time = 1200 / 60 * (Math.sqrt(Math.pow((city2[0] - city1[0]), 2) + Math.pow((city2[1] - city1[1]), 2))); } return Math.floor(time * 60 * 1000); }, addStyleSheet : function(style) { var getHead = document.getElementsByTagName("HEAD")[0]; var cssNode = window.document.createElement('style'); var elementStyle = getHead.appendChild(cssNode); elementStyle.innerHTML = style; return elementStyle; }, escapeRegExp : function(str) { return str.replace(/[\[\]\/\{\}\(\)\-\?\$\*\+\.\\\^\|]/g, "\\$&"); }, format : function(inputString, replacements) { var str = '' + inputString; var keys = Object.keys(replacements); var i = keys.length; while(i--) { str = str.replace(new RegExp(this.escapeRegExp('{' + keys[i] + '}'), 'g'), replacements[keys[i]]) } return str }, cacheFunction : function(toExecute, expiry) { expiry = expiry || 1000; var cachedTime = $.now; var cachedResult = undefined; return function() { if(cachedTime < $.now() - expiry || cachedResult === undefined) { cachedResult = toExecute(); cachedTime = $.now() } return cachedResult } }, getClone : function($node){ if ($node.hasClass('ui-sortable-helper') || $node.parent().find('.ui-sortable-helper').length){ return $node;} return $($node.get(0).cloneNode(true)) }, setClone : function($node, $clone){ if ($node.hasClass('ui-sortable-helper') || $node.parent().find('.ui-sortable-helper').length){ return $node; } $node.get(0).parentNode.replaceChild($clone.get(0), $node.get(0)); return $node }, replaceNode : function(node, html) { var t = node.cloneNode(false); t.innerHTML = html; node.parentNode.replaceChild(t, node); return t }, FormatTimeLengthToStr : function(timeString, precision, spacer) { var lang = database.settings.languageChange.value; timeString = timeString || 0; precision = precision || 2; spacer = spacer || " "; if(!isFinite(timeString)) { return ' \u221E '; } if(timeString < 0) timeString *= -1; var factors = []; var locStr = []; var server = ikariam.Nationality(); factors.day = 86400; factors.hour = 3600; factors.minute = 60; factors.second = 1; locStr.day = Constant.LanguageData[lang].day; locStr.hour = database.getGlobalData.getLocalisedString('h'); locStr.minute = database.getGlobalData.getLocalisedString('m'); locStr.second = database.getGlobalData.getLocalisedString('s'); if (server == 'ir' || server == 'ae') { locStr.hour = database.getGlobalData.getLocalisedString('س'); locStr.minute = database.getGlobalData.getLocalisedString('د'); locStr.second = database.getGlobalData.getLocalisedString('ث'); } timeString = Math.ceil(timeString / 1000); var retString = ""; for(var fact in factors) { var timeInSecs = Math.floor(timeString / factors[fact]); if(isNaN(timeInSecs)) { return retString; } if(precision > 0 && (timeInSecs > 0 || retString != "")) { timeString = timeString - timeInSecs * factors[fact]; if(retString != "") { retString += spacer; } retString += timeInSecs + locStr[fact]; precision--; } } return retString; }, FormatFullTimeToDateString: function (timeString, precise) { var lang = database.settings.languageChange.value; precise = precise || true; timeString = timeString || 0; var sInDay = 86400000; var day = ''; var compDate = new Date(timeString); if(precise) { switch(Math.floor(compDate.getTime() / sInDay) - Math.floor($.now() / sInDay)) { case 0 : day = Constant.LanguageData[lang].today; break; case 1 : day = Constant.LanguageData[lang].tomorrow; break; case -1 : day = Constant.LanguageData[lang].yesterday; break; default : day = (!isChrome ? compDate.toLocaleFormat('%a %d %b') : compDate.toString().split(' ').splice(0, 3).join(' ')) //Dienstag } } if(day != '') { day += ', ' } return day + compDate.toLocaleTimeString(); }, FormatTimeToDateString: function (timeString) { timeString = timeString || 0; var compDate = new Date(timeString); return compDate.toLocaleTimeString(); }, FormatRemainingTime : function(time, brackets) { brackets = brackets || false; var arrInTime = Utils.FormatTimeLengthToStr(time, 3, ' '); return (arrInTime == '') ? '' : (brackets ? '(' : '') + arrInTime + (brackets ? ')' : ''); }, FormatNumToStr : function(inputNum, outputSign, precision) { var lang = database.settings.languageChange.value; precision = precision ? "10e" + (precision - 1) : 1; var ret, val, sign, i, j; var tho = Constant.LanguageData[lang].thousandSeperator; var dec = Constant.LanguageData[lang].decimalPoint; if(!isFinite(inputNum)) { return '\u221E' } sign = inputNum > 0 ? 1 : inputNum === 0 ? 0 : -1; if(sign) { val = (( Math.floor(Math.abs(inputNum * precision)) / precision ) + '').split('.'); ret = val[1] != undefined ? [dec, val[1]] : []; val = val[0].split(''); i = val.length; j = 1; while(i--) { ret.unshift(val.pop()); if(i && j % 3 == 0) { ret.unshift(tho) } j++ } if(outputSign) { ret.unshift(sign == 1 ? '+' : '-'); } return ret.join(''); } else return inputNum; } }; /*********************************************************************************************************************** * CLASSES **********************************************************************************************************************/ function Movement(id, originCityId, targetCityId, arrivalTime, mission, loadingTime, resources, military, ships) { if(typeof id === "object") { this._id = id._id || null; this._originCityId = id._originCityId || null; this._targetCityId = id._targetCityId || null; this._arrivalTime = id._arrivalTime || null; this._mission = id._mission || null; this._loadingTime = id._loadingTime || null; this._resources = id._resources || {wood: 0, wine: 0, marble: 0, glass: 0, sulfur: 0, gold: 0}; this._military = id._military || new MilitaryUnits(); this._ships = id._ships || null; this._updatedCity = id._updatedCity || false; this._complete = id._complete || false; this._updateTimer = id._updateTimer || null; } else { this._id = id || null; this._originCityId = originCityId || null; this._targetCityId = targetCityId || null; this._arrivalTime = arrivalTime || null; this._mission = mission || null; this._loadingTime = loadingTime || null; this._resources = resources || {wood: 0, wine: 0, marble: 0, glass: 0, sulfur: 0, gold: 0}; this._military = military || new MilitaryUnits(); this._ships = ships || null; this._updatedCity = false; this._complete = false; this._updateTimer = null; } } Movement.prototype = { startUpdateTimer : function() { this.clearUpdateTimer(); if(this.isCompleted) { this.updateTransportComplete() } else { this._updateTimer = events.scheduleActionAtTime(this.updateTransportComplete.bind(this), this._arrivalTime + 1000) } }, clearUpdateTimer : function() { var ret = !this._updateTimer || this._updateTimer(); this._updateTimer = null; return ret }, get getId() { return this._id }, get getOriginCityId() { return this._originCityId }, get getTargetCityId() { return this._targetCityId }, get getArrivalTime() { return this._arrivalTime }, get getMission() { return this._mission }, get getLoadingTime() { return this._loadingTime - $.now() }, get getResources() { return this._resources }, getResource : function(resourceName) { return this._resources[resourceName] }, get getMilitary() { return this._military }, get getShips() { return this._ships }, get isCompleted() { return this._arrivalTime < $.now() }, get isLoading() { return this._loadingTime > $.now() }, get getRemainingTime() { return this._arrivalTime - $.now() }, updateTransportComplete: function() { if(this.isCompleted && !this._updatedCity) { var city = database.getCityFromId(this._targetCityId); var changes = []; if(city) { for(var resource in Constant.Resources) { if(this.getResource(Constant.Resources[resource])) { changes.push(Constant.Resources[resource]) } city.getResource(Constant.Resources[resource]).increment(this.getResource(Constant.Resources[resource])); } this._updatedCity = true; city = database.getCityFromId(this.originCityId); if(city) { city.updateActionPoints(city.getAvailableActions + 1) } if(changes.length) { events(Constant.Events.MOVEMENTS_UPDATED).pub([this.getTargetCityId]); events(Constant.Events.RESOURCES_UPDATED).pub(this.getTargetCityId, changes); } events.scheduleAction(function() { database.getGlobalData.removeFleetMovement(this._id) }.bind(this)); return true } } else if(this._updatedCity) { events.scheduleAction(function() { database.getGlobalData.removeFleetMovement(this._id) }.bind(this)) } return false; } }; function Resource(city, name) { this._current = 0; this._production = 0; this._consumption = 0; this._currentChangedDate = $.now(); this.city = Utils.wrapInClosure(city); this._name = name; return this } Resource.prototype = { get name() { return this._name }, update : function(current, production, consumption) { var changed = (current % this._current > 10) || (production != this._production) || (consumption != this._consumption); this._current = current; this._production = production; this._consumption = consumption; this._currentChangedDate = $.now(); return changed; }, project : function() { var limit = Math.floor($.now() / 1000); var start = Math.floor(this._currentChangedDate / 1000); while(limit > start) { this._current += this._production; if(Math.floor(start / 3600) != Math.floor((start + 1) / 3600)) if(this._current > this._consumption) { this._current -= this._consumption } else { this.city().projectPopData(start * 1000); this._consumption = 0; } start++ } this._currentChangedDate = limit * 1000; this.city().projectPopData(limit * 1000) }, increment: function(amount) { if(amount !== 0) { this._current += amount; return true; } return false; }, get getEmptyTime() { var net = this.getProduction * 3600 - this.getConsumption; return (net < 0) ? this.getCurrent / net * -1 : Infinity; }, get getFullTime() { var net = this.getProduction * 3600 - this.getConsumption; return (net > 0) ? (this.city().maxResourceCapacities.capacity - this.getCurrent) / net : 0; }, get getCurrent() { return Math.floor(this._current); }, get getProduction() { return this._production || 0 }, get getConsumption() { return this._consumption || 0 } }; function Military(city) { this.city = Utils.wrapInClosure(city); this._units = new MilitaryUnits(); this._advisorLastUpdate = 0; this.armyTraining = []; this._trainingTimer = null; } Military.prototype = { init : function() { this._trainingTimer = null; this._startTrainingTimer() }, _getTrainingTotals: function (){ var ret = {}; $.each(this.armyTraining, function(index, training) { $.each(Constant.UnitData, function(unitId, info) { ret[unitId] = ret[unitId]?ret[unitId]+(training.units[unitId]||0):training.units[unitId]||0 }) }); return ret }, get getTrainingTotals() { if(!this._trainingTotals) { this._trainingTotals = Utils.cacheFunction(this._getTrainingTotals.bind(this), 1000) } return this._trainingTotals() }, _getIncomingTotals :function (){ var ret = {}; $.each(this.city().getIncomingMilitary, function(index, element) { for(var unitName in Constant.UnitData) { ret[unitName] = ret[unitName] ? ret[unitName] + (element.getMilitary.totals[unitName]||0) : element.getMilitary.totals[unitName]||0 } }); return ret }, get getIncomingTotals() { if(!this._incomingTotals) { this._incomingTotals = Utils.cacheFunction(this._getIncomingTotals.bind(this), 1000) } return this._incomingTotals() }, getTrainingForUnit : function(unit) { var ret = []; $.each(this.armyTraining, function(index, training) { $.each(training.units, function(unitId, count) { if(unitId === unit) { ret.push({count: count, time: training.completionTime}) } }) }); return ret }, setTraining : function(trainingQueue) { if(!trainingQueue.length) return false; this._stopTrainingTimer(); var type = trainingQueue[0].type; var changes = this._clearTrainingForType(type); $.each(trainingQueue, function(index, training) { this.armyTraining.push(training); $.each(training.units, function(unitId, count) { changes.push(unitId) }) }.bind(this)); this.armyTraining.sort(function(a, b) { return a.completionTime - b.completionTime }); this._startTrainingTimer(); return $.exclusive(changes) }, _clearTrainingForType: function(type) { var oldTraining = this.armyTraining.filter(function(item) { return item.type === type }); this.armyTraining = this.armyTraining.filter(function(item) { return item.type !== type }); var changes = []; $.each(oldTraining, function(index, training) { $.each(training.units, function(unitId, count) { changes.push(unitId) }) }); return changes }, _completeTraining : function() { if(this.armyTraining.length) { if(this.armyTraining[0].completionTime < $.now() + 5000) { var changes = []; var training = this.armyTraining.shift(); $.each(training.units, function(id, count) { this.getUnits.addUnit(id, count); changes.push(id) }.bind(this)); if(changes.length)events(Constant.Events.MILITARY_UPDATED).pub(this.city().getId, changes) } } this._startTrainingTimer() }, _startTrainingTimer : function() { this._stopTrainingTimer(); if(this.armyTraining.length) { this._trainingTimer = events.scheduleActionAtTime(this._completeTraining.bind(this), this.armyTraining[0].completionTime) } }, _stopTrainingTimer : function() { if(this._trainingTimer) { this._trainingTimer() } this._trainingTimer = null }, updateUnits : function(counts) { var changes = []; $.each(counts, function(unitId, count) { if(this._units.setUnit(unitId, count)) { changes.push(unitId) } }.bind(this)); return changes; }, get getUnits() { return this._units } }; function MilitaryUnits(obj) { this._units = obj !== undefined ? obj._units: {}; } MilitaryUnits.prototype = { getUnit : function(unitId) { return this._units[unitId] || 0 }, setUnit : function(unitId, count) { var changed = this._units[unitId] != count; this._units[unitId] = count; return changed }, get totals() { return this._units }, addUnit : function(unitId, count) { return this.setUnit(unitId, this.getUnit(unitId) + count) }, removeUnit: function(unitId, count) { count = Math.max(0, this.getUnit[unitId] - count); return this.setUnit(unitId, count) } }; function Building(city, pos) { this._position = pos; this._level = 0; this._name = null; this.city = Utils.wrapInClosure(city); this._updateTimer = null } Building.prototype = { startUpgradeTimer : function() { if(this._updateTimer) { this._updateTimer(); delete this._updateTimer } if(this._completionTime) { if(this._completionTime - $.now() < 5000) { this.completeUpgrade() } else { this._updateTimer = events.scheduleActionAtTime(this.completeUpgrade.bind(this), this._completionTime - 4000) } } var statusPoll = function(a, b){ return events.scheduleActionAtInterval(function(){ if(a != this.isUpgradable || b != this.isUpgrading){ var changes = {position: this._position, name: this.getName, upgraded: this.isUpgrading != b} events(Constant.Events.BUILDINGS_UPDATED).pub([changes]); a = this.isUpgradable; b = this.isUpgrading; } }.bind(this),3000) }(this.isUpgradable,this.isUpgrading) }, update : function(data) { var changes; var name = data.building.split(' ')[0]; var level = parseInt(data.level) || 0; database.getGlobalData.addLocalisedString(name, data.name); var completion = ('undefined' !== typeof data['completed']) ? parseInt(data['completed']) : 0; var changed = (name !== this._name || level !== this._level || !!completion != this.isUpgrading); if(changed) { changes = {position: this._position, name: this.getName, upgraded: this.isUpgrading != !completion}; } if(completion) { this._completionTime = completion * 1000; this.startUpgradeTimer() } else if(this._completionTime) { delete this._completionTime } this._name = name; this._level = level; if(changed) { return changes; } return false; }, get getUrlParams() { return { view : this.getName, cityId : this.city().getId, position: this.getPosition }; }, get getUpgradeCost() { var carpenter, architect, vineyard, fireworker, optician; var level = this._level + this.isUpgrading; if(this.isEmpty) { return { wood : Infinity, glass : 0, marble: 0, sulfur: 0, wine : 0, time : 0 } } var time = Constant.BuildingData[this._name].time; var bon = 1; var bonTime = 1 + Constant.GovernmentData[database.getGlobalData.getGovernmentType].buildingTime; bon -= database.getGlobalData.getResearchTopicLevel(Constant.Research.Economy.PULLEY) ? .02 : 0; bon -= database.getGlobalData.getResearchTopicLevel(Constant.Research.Economy.GEOMETRY) ? .04 : 0; bon -= database.getGlobalData.getResearchTopicLevel(Constant.Research.Economy.SPIRIT_LEVEL) ? .08 : 0; return{ wood : Math.floor((Constant.BuildingData[this._name].wood[level] || 0) * (bon - (carpenter = this.city().getBuildingFromName(Constant.Buildings.CARPENTER), carpenter ? carpenter.getLevel / 100 : 0))), wine : Math.floor((Constant.BuildingData[this._name].wine[level] || 0) * (bon - (vineyard = this.city().getBuildingFromName(Constant.Buildings.VINEYARD), vineyard ? vineyard.getLevel / 100 : 0))), marble: Math.floor((Constant.BuildingData[this._name].marble[level] || 0) * (bon - (architect = this.city().getBuildingFromName(Constant.Buildings.ARCHITECT), architect ? architect.getLevel / 100 : 0))), glass : Math.floor((Constant.BuildingData[this._name].glass[level] || 0) * (bon - (optician = this.city().getBuildingFromName(Constant.Buildings.OPTICIAN), optician ? optician.getLevel / 100 : 0))), sulfur: Math.floor((Constant.BuildingData[this._name].sulfur[level] || 0) * (bon - (fireworker = this.city().getBuildingFromName(Constant.Buildings.FIREWORK_TEST_AREA), fireworker ? fireworker.getLevel / 100 : 0))), time : Math.round(time.a / time.b * Math.pow(time.c, level + 1) - time.d) * 1000 * bonTime } }, get getName() { return this._name }, get getType() { return Constant.BuildingData[this.getName].type }, get getLevel() { return this._level }, get isEmpty() { return this._name == 'buildingGround' || this._name == null }, get isUpgrading() { return (this._completionTime > $.now()) }, subtractUpgradeResourcesFromCity: function() { var cost = this.getUpgradeCost; $.each(Constant.Resources, function(key, resourceName) { this.city().getResource(resourceName).increment(cost[resourceName] * -1) }.bind(this)); this._completionTime = $.now() + cost.time; }, get isUpgradable() { if(this.isEmpty || this.isMaxLevel) { return false } var cost = this.getUpgradeCost; var upgradable = true; $.each(Constant.Resources, function(key, value) { upgradable = upgradable && (!cost[value] || cost[value] <= this.city().getResource(value).getCurrent); }.bind(this)); return upgradable; }, get getCompletionTime() { return this._completionTime }, get getCompletionDate() { }, get isMaxLevel() { return Constant.BuildingData[this.getName].maxLevel === (this.getLevel) }, get getPosition() { return this._position }, completeUpgrade : function() { this._level++; delete this._completionTime; delete this._updateTimer; events(Constant.Events.BUILDINGS_UPDATED).pub(this.city().getId, [ {position: this._position, name: this.getName, upgraded: true} ]) } }; function CityResearch(city) { this._researchersLastUpdate = 0; this._researchers = 0; this._researchCostLastUpdate = 0; this._researchCost = 0; this.city = Utils.wrapInClosure(city); } CityResearch.prototype = { updateResearchers: function(researchers) { var changed = this._researchers !== researchers; this._researchers = researchers; this._researchersLastUpdate = $.now(); this._researchCost = this.getResearchCost; return changed; }, updateCost : function(cost) { var changed = this._researchCost !== cost; this._researchCost = cost; this._researchCostLastUpdate = $.now(); this._researchers = this.getResearchers; return changed; }, get getResearchers() { if(this._researchersLastUpdate < this._researchCostLastUpdate) { return Math.floor(this._researchCost / this._researchCostModifier); } else { return this._researchers } }, get getResearch() { return this.researchData.total }, get researchData(){ if (!this._researchData){ this._researchData = Utils.cacheFunction(this.researchDataCached.bind(this),1000) } return this._researchData() }, researchDataCached :function(){ var resBon = 0 + Constant.GovernmentData[database.getGlobalData.getGovernmentType].researchBonus + (database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.PAPER) * 0.02) + (database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.INK) * 0.04) + (database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.MECHANICAL_PEN) * 0.08) + (database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.SCIENTIFIC_FUTURE) * 0.02); var premBon = database.getGlobalData.hasPremiumFeature(Constant.Premium.RESEARCH_POINTS_BONUS_EXTREME_LENGTH) ? (0 + Constant.PremiumData[Constant.Premium.RESEARCH_POINTS_BONUS_EXTREME_LENGTH].bonus) : database.getGlobalData.hasPremiumFeature(Constant.Premium.RESEARCH_POINTS_BONUS) ? (0 + Constant.PremiumData[Constant.Premium.RESEARCH_POINTS_BONUS].bonus) : 0; var goods = Constant.GovernmentData[database.getGlobalData.getGovernmentType].researchPerCulturalGood * this.city()._culturalGoods; var researchers = this.getResearchers; var corruptionSpend = researchers * this.city().getCorruption; var nonCorruptedResearchers = researchers * (1 - this.city().getCorruption); var premiumResBonus = nonCorruptedResearchers * premBon; var researchBonus = nonCorruptedResearchers * resBon; var premiumGoodsBonus = goods * premBon; var serverTyp = $('li.logout a[href="?view=normalServerStatus"]').text() ? 1 : 3; return { scientists: researchers, researchBonus: researchBonus, premiumScientistBonus: premiumResBonus, premiumResearchBonus: (researchBonus* premBon), culturalGoods: goods, premiumCulturalGoodsBonus: premiumGoodsBonus, corruption: corruptionSpend, total: (nonCorruptedResearchers + researchBonus + premiumResBonus + goods + premiumGoodsBonus + (researchBonus* premBon))* serverTyp } }, get _researchCostModifier() { return 6 + Constant.GovernmentData[database.getGlobalData.getGovernmentType].researcherCost - (database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.LETTER_CHUTE) * 3) }, get getResearchCost() { return this.getResearchers * this._researchCostModifier; } }; function Changes(city, type, changes) { this.city = city || null; this.type = type || null; this.changes = changes || []; } function Population(city) { this._population = 0; this._citizens = 0; this._resourceWorkers = 0; this._tradeWorkers = 0; this._priests = 0; this._culturalGoods = 0; this._popChanged = $.now(); this._citizensChanged = $.now(); this._culturalGoodsChanged = $.now(); this._priestsChanged = $.now(); this.city = Utils.wrapInClosure(city) } Population.prototype = { updatePopulationData: function(population, citizens, priests, culturalGoods) { var changes = []; if(population && population != this._population) { changes.push({population: true}); this.population = population; } if(citizens && citizens != this._priests) { changes.push({citizens: true}); this.citizens = citizens; } if(priests && priests != this._priests) { changes.push({priests: true}); this.priests = priests; } }, updateWorkerData : function(resourceName, workers) { }, updatePriests : function(newCount) { }, updateCulturalGoods : function(newCount) { }, get population() { return this._population }, set population(newVal) { this._population = newVal; this._popChanged = $.now() }, get citizens() { return this._citizens }, set citizens(newVal) { this._citizens = newVal; this._citizensChanged = $.now() }, get priests() { return this._priests }, set priests(newVal) { this._priests = newVal; this._priestsChanged = $.now() } }; function City(id) { this._id = id || 0; this._name = ''; this._resources = { gold : new Resource(this, Constant.Resources.GOLD), wood : new Resource(this, Constant.Resources.WOOD), wine : new Resource(this, Constant.Resources.WINE), marble: new Resource(this, Constant.Resources.MARBLE), glass : new Resource(this, Constant.Resources.GLASS), sulfur: new Resource(this, Constant.Resources.SULFUR) }; this._capacities = { capacity : 0, safe : 0, buildings: { dump : {storage: 0, safe: 0}, warehouse: {storage: 0, safe: 0}, townHall : {storage: 2500, safe: 100} }, invalid : true }; this._tradeGoodID = 0; this.knownTime = $.now(); this._