Phain

Tiberium Alliances Real POI Bonus.user

May 5th, 2018
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.25 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Tiberium Alliances Real POI Bonus
  3. // @version 1.0.2
  4. // @namespace https://openuserjs.org/users/petui
  5. // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
  6. // @author petui (POI factor Fix AlkalyneD4)
  7. // @description Displays actual gain/loss for POIs by taking rank multiplier properly into account
  8. // @include http*://prodgame*.alliances.commandandconquer.com/*/index.aspx*
  9. // @updateURL https://openuserjs.org/meta/petui/Tiberium_Alliances_Real_POI_Bonus.meta.js
  10. // ==/UserScript==
  11. 'use strict';
  12.  
  13. (function() {
  14. var main = function() {
  15. 'use strict';
  16.  
  17. function createRealPOIBonus() {
  18. console.log('RealPOIBonus loaded');
  19.  
  20. qx.Class.define('RealPOIBonus', {
  21. type: 'singleton',
  22. extend: qx.core.Object,
  23. statics: {
  24. PoiTypeToPoiRankingTypeMap: {},
  25. PoiRankingTypeToSortColumnMap: {}
  26. },
  27. defer: function(statics) {
  28. statics.PoiTypeToPoiRankingTypeMap[ClientLib.Base.EPOIType.TiberiumBonus] = ClientLib.Data.Ranking.ERankingType.BonusTiberium;
  29. statics.PoiTypeToPoiRankingTypeMap[ClientLib.Base.EPOIType.CrystalBonus] = ClientLib.Data.Ranking.ERankingType.BonusCrystal;
  30. statics.PoiTypeToPoiRankingTypeMap[ClientLib.Base.EPOIType.PowerBonus] = ClientLib.Data.Ranking.ERankingType.BonusPower;
  31. statics.PoiTypeToPoiRankingTypeMap[ClientLib.Base.EPOIType.InfanteryBonus] = ClientLib.Data.Ranking.ERankingType.BonusInfantry;
  32. statics.PoiTypeToPoiRankingTypeMap[ClientLib.Base.EPOIType.VehicleBonus] = ClientLib.Data.Ranking.ERankingType.BonusVehicles;
  33. statics.PoiTypeToPoiRankingTypeMap[ClientLib.Base.EPOIType.AirBonus] = ClientLib.Data.Ranking.ERankingType.BonusAircraft;
  34. statics.PoiTypeToPoiRankingTypeMap[ClientLib.Base.EPOIType.DefenseBonus] = ClientLib.Data.Ranking.ERankingType.BonusDefense;
  35.  
  36. statics.PoiRankingTypeToSortColumnMap[ClientLib.Data.Ranking.ERankingType.BonusTiberium] = ClientLib.Data.Ranking.ESortColumn.TiberiumScore;
  37. statics.PoiRankingTypeToSortColumnMap[ClientLib.Data.Ranking.ERankingType.BonusCrystal] = ClientLib.Data.Ranking.ESortColumn.CrystalScore;
  38. statics.PoiRankingTypeToSortColumnMap[ClientLib.Data.Ranking.ERankingType.BonusPower] = ClientLib.Data.Ranking.ESortColumn.PowerScore;
  39. statics.PoiRankingTypeToSortColumnMap[ClientLib.Data.Ranking.ERankingType.BonusInfantry] = ClientLib.Data.Ranking.ESortColumn.InfantryScore;
  40. statics.PoiRankingTypeToSortColumnMap[ClientLib.Data.Ranking.ERankingType.BonusVehicles] = ClientLib.Data.Ranking.ESortColumn.VehicleScore;
  41. statics.PoiRankingTypeToSortColumnMap[ClientLib.Data.Ranking.ERankingType.BonusAircraft] = ClientLib.Data.Ranking.ESortColumn.AircraftScore;
  42. statics.PoiRankingTypeToSortColumnMap[ClientLib.Data.Ranking.ERankingType.BonusDefense] = ClientLib.Data.Ranking.ESortColumn.DefenseScore;
  43. },
  44. members: {
  45. rankingBonusDataCache: {},
  46. container: null,
  47. titleLabel: null,
  48. amountLabel: null,
  49. ownedPoiCount: 0,
  50.  
  51. initialize: function() {
  52. this.initializeHacks();
  53.  
  54. this.container = new qx.ui.container.Composite(new qx.ui.layout.HBox(4)).set({
  55. textColor: 'text-region-tooltip',
  56. marginRight: 10
  57. });
  58. this.container.add(this.titleLabel = new qx.ui.basic.Label());
  59. this.container.add(this.amountLabel = new qx.ui.basic.Label());
  60.  
  61. var poiStatusInfo = webfrontend.gui.region.RegionPointOfInterestStatusInfo.getInstance();
  62. poiStatusInfo.getChildren()[0].addAt(this.container, 4);
  63. poiStatusInfo.addListener('appear', this.onStatusInfoAppear, this);
  64.  
  65. phe.cnc.Util.attachNetEvent(ClientLib.Data.MainData.GetInstance().get_Alliance(), 'Change', ClientLib.Data.AllianceChange, this, this.onAllianceChange);
  66. this.onAllianceChange();
  67. },
  68.  
  69. initializeHacks: function() {
  70. if (typeof webfrontend.gui.region.RegionPointOfInterestStatusInfo.prototype.getObject !== 'function') {
  71. var source = webfrontend.gui.region.RegionPointOfInterestStatusInfo.prototype.setObject.toString();
  72. var objectMemberName = source.match(/^function \(([A-Za-z]+)\)\{this\.([A-Za-z_]+)=\1;/)[2];
  73.  
  74. /**
  75. * @returns {ClientLib.Vis.Region.RegionPointOfInterest}
  76. */
  77. webfrontend.gui.region.RegionPointOfInterestStatusInfo.prototype.getObject = function() {
  78. return this[objectMemberName];
  79. };
  80. }
  81. },
  82.  
  83. onAllianceChange: function() {
  84. var alliance = ClientLib.Data.MainData.GetInstance().get_Alliance();
  85. var poiCount = alliance.get_Exists() ? alliance.get_OwnedPOIs().length : 0;
  86.  
  87. if (poiCount !== this.ownedPoiCount) {
  88. this.ownedPoiCount = poiCount;
  89. this.rankingBonusDataCache = {};
  90. }
  91. },
  92.  
  93. /**
  94. * @param {qx.event.type.Event} event
  95. */
  96. onStatusInfoAppear: function(event) {
  97. var visObject = event.getTarget().getObject();
  98. var allianceId = ClientLib.Data.MainData.GetInstance().get_Alliance().get_Id();
  99.  
  100. if (allianceId > 0 && visObject.get_Type() !== ClientLib.Data.WorldSector.WorldObjectPointOfInterest.EPOIType.TunnelExit) {
  101. var selectedPoiScore = ClientLib.Base.PointOfInterestTypes.GetScoreByLevel(visObject.get_Level());
  102. var poiType = ClientLib.Base.PointOfInterestTypes.GetPOITypeFromWorldPOIType(visObject.get_Type());
  103. var poiRankScore = ClientLib.Data.MainData.GetInstance().get_Alliance().get_POIRankScore()[poiType - ClientLib.Base.EPOIType.RankedTypeBegin];
  104. var allianceRank = poiRankScore.r;
  105. var allianceScore = poiRankScore.s;
  106. var nextAllianceScore = poiRankScore.ns;
  107. var previousAllianceScore = poiRankScore.ps;
  108. var bonusMultiplier = ClientLib.Data.MainData.GetInstance().get_Server().get_POIGlobalBonusFactor();
  109. var currentTotalBonus = ClientLib.Base.PointOfInterestTypes.GetTotalBonusByType(poiType, allianceRank, allianceScore,bonusMultiplier);
  110.  
  111. var gainOrLoss = null;
  112.  
  113. if (visObject.get_OwnerAllianceId() === allianceId) {
  114. this.titleLabel.setValue('Real loss:');
  115.  
  116. if (previousAllianceScore <= 0) {
  117. // No rank multiplier; no loss by rank
  118. gainOrLoss = currentTotalBonus - ClientLib.Base.PointOfInterestTypes.GetTotalBonusByType(poiType, allianceRank, allianceScore - selectedPoiScore,bonusMultiplier);
  119. }
  120. else if (allianceScore - selectedPoiScore < previousAllianceScore) {
  121. // Falling behind previous alliance; need to use rankings
  122. }
  123. else {
  124. // No loss by rank; if we end up with same score as previous alliance, our rank stays the same and they get same rank
  125. gainOrLoss = currentTotalBonus - ClientLib.Base.PointOfInterestTypes.GetTotalBonusByType(poiType, allianceRank, allianceScore - selectedPoiScore,bonusMultiplier);
  126. }
  127. }
  128. else {
  129. this.titleLabel.setValue('Real gain:');
  130.  
  131. if (!allianceScore) {
  132. // Zero bonus; need to use rankings
  133. }
  134. else if (nextAllianceScore <= 0 || allianceRank <= 1) {
  135. // Already rank 1; no gain by rank
  136. gainOrLoss = ClientLib.Base.PointOfInterestTypes.GetTotalBonusByType(poiType, allianceRank, allianceScore + selectedPoiScore,bonusMultiplier) - currentTotalBonus;
  137. }
  138. else if (visObject.get_OwnerAllianceId() !== webfrontend.gui.widgets.AllianceLabel.ESpecialNoAllianceName) {
  139. // Current owner of POI will lose score while we gain; need to use rankings
  140. }
  141. else if (allianceScore + selectedPoiScore > nextAllianceScore) {
  142. // Overtaking next alliance; need to use rankings
  143. }
  144. else if (allianceScore + selectedPoiScore < nextAllianceScore) {
  145. // No gain by rank
  146. gainOrLoss = ClientLib.Base.PointOfInterestTypes.GetTotalBonusByType(poiType, allianceRank, allianceScore + selectedPoiScore,bonusMultiplier) - currentTotalBonus;
  147. }
  148. else {
  149. // Same score as next alliance; same rank and same bonus as them
  150. gainOrLoss = ClientLib.Base.PointOfInterestTypes.GetTotalBonusByType(poiType, allianceRank - 1, allianceScore + selectedPoiScore,bonusMultiplier) - currentTotalBonus;
  151. }
  152. }
  153.  
  154. if (gainOrLoss === null) {
  155. this.amountLabel.setValue('Loading...');
  156. this.fetchAndCalculateBonusWithRankingData(poiType, allianceRank, allianceScore, selectedPoiScore, allianceId, visObject.get_OwnerAllianceId());
  157. }
  158. else {
  159. this.amountLabel.setValue(this.formatGainOrLoss(gainOrLoss, poiType));
  160. }
  161.  
  162. this.container.setVisibility('visible');
  163. }
  164. else {
  165. this.container.setVisibility('excluded');
  166. }
  167. },
  168.  
  169. /**
  170. * @param {ClientLib.Base.EPOIType} poiType
  171. * @param {Number} currentRank
  172. * @param {Number} currentScore
  173. * @param {Number} poiScore
  174. * @param {Number} allianceId
  175. * @param {Number} poiOwnerId
  176. */
  177. fetchAndCalculateBonusWithRankingData: function(poiType, currentRank, currentScore, poiScore, allianceId, poiOwnerId) {
  178. var context = {
  179. poiType: poiType,
  180. currentRank: currentRank,
  181. currentScore: currentScore,
  182. poiScore: poiScore,
  183. allianceId: allianceId,
  184. poiOwnerId: poiOwnerId
  185. };
  186.  
  187. if (poiType in this.rankingBonusDataCache && this.rankingBonusDataCache[poiType].expire >= Date.now()) {
  188. this.calculateBonus(context, this.rankingBonusDataCache[poiType].results);
  189. }
  190. else {
  191. var lastMultiplierRank = Object.keys(ClientLib.Res.ResMain.GetInstance().GetGamedata().poibmbr).length;
  192. var rankingPoiType = RealPOIBonus.PoiTypeToPoiRankingTypeMap[poiType];
  193. var sortColumn = RealPOIBonus.PoiRankingTypeToSortColumnMap[rankingPoiType];
  194.  
  195. ClientLib.Net.CommunicationManager.GetInstance().SendSimpleCommand('RankingGetData', {
  196. firstIndex: 0,
  197. lastIndex: lastMultiplierRank,
  198. view: ClientLib.Data.Ranking.EViewType.Alliance,
  199. rankingType: rankingPoiType,
  200. sortColumn: sortColumn,
  201. ascending: true
  202. }, phe.cnc.Util.createEventDelegate(ClientLib.Net.CommandResult, this, this.onRankingGetData), context);
  203. }
  204. },
  205.  
  206. /**
  207. * @param {Object} context
  208. * @param {Object} results
  209. */
  210. onRankingGetData: function(context, results) {
  211. if (results === null) {
  212. return;
  213. }
  214.  
  215. var allianceBonuses = results.a;
  216.  
  217. // Remove own alliance from list and add missing scores
  218. for (var i = 0; i < allianceBonuses.length; i++) {
  219. if (allianceBonuses[i].a === context.allianceId) {
  220. allianceBonuses.splice(i--, 1);
  221. }
  222. else if (allianceBonuses[i].pois === undefined) {
  223. allianceBonuses[i].pois = 0;
  224. }
  225. }
  226.  
  227. this.rankingBonusDataCache[context.poiType] = {
  228. expire: Date.now() + 600000,
  229. results: allianceBonuses
  230. };
  231.  
  232. this.calculateBonus(context, allianceBonuses);
  233. },
  234.  
  235. /**
  236. * @param {Object} context
  237. * @param {Array} allianceBonuses
  238. */
  239. calculateBonus: function(context, allianceBonuses) {
  240. var isGain = context.poiOwnerId !== context.allianceId;
  241. var i;
  242.  
  243. if (isGain && context.poiOwnerId !== webfrontend.gui.widgets.AllianceLabel.ESpecialNoAllianceName) {
  244. // Subtract POI score from current owner
  245. for (i = 0; i < allianceBonuses.length; i++) {
  246. if (allianceBonuses[i].a === context.poiOwnerId) {
  247. // Array can be safely modified after cloning
  248. allianceBonuses = allianceBonuses.map(this.shallowClone);
  249. allianceBonuses[i].pois -= context.poiScore;
  250.  
  251. allianceBonuses.sort(function(a, b) {
  252. return b.pois - a.pois;
  253. });
  254. break;
  255. }
  256. }
  257. }
  258.  
  259. var newAllianceScore = context.currentScore + (isGain ? context.poiScore : -context.poiScore);
  260.  
  261. for (i = 0; i < allianceBonuses.length; i++) {
  262. if (allianceBonuses[i].pois <= newAllianceScore) {
  263. break;
  264. }
  265. }
  266. var bonusMultiplier = ClientLib.Data.MainData.GetInstance().get_Server().get_POIGlobalBonusFactor();
  267. var currentTotalBonus = ClientLib.Base.PointOfInterestTypes.GetTotalBonusByType(context.poiType, context.currentRank, context.currentScore,bonusMultiplier);
  268. var newTotalBonus = ClientLib.Base.PointOfInterestTypes.GetTotalBonusByType(context.poiType, i + 1, newAllianceScore,bonusMultiplier);
  269. var gainOrLoss = isGain
  270. ? newTotalBonus - currentTotalBonus
  271. : currentTotalBonus - newTotalBonus;
  272.  
  273. this.amountLabel.setValue(this.formatGainOrLoss(gainOrLoss, context.poiType));
  274. },
  275.  
  276. /**
  277. * @param {Number} gainOrLoss
  278. * @param {ClientLib.Base.EPOIType} poiType
  279. * @returns {String}
  280. */
  281. formatGainOrLoss: function(gainOrLoss, poiType) {
  282. switch (poiType) {
  283. case ClientLib.Base.EPOIType.TiberiumBonus:
  284. case ClientLib.Base.EPOIType.CrystalBonus:
  285. case ClientLib.Base.EPOIType.PowerBonus:
  286. return phe.cnc.gui.util.Numbers.formatNumbers(gainOrLoss) + '/h';
  287. case ClientLib.Base.EPOIType.InfanteryBonus:
  288. case ClientLib.Base.EPOIType.VehicleBonus:
  289. case ClientLib.Base.EPOIType.AirBonus:
  290. case ClientLib.Base.EPOIType.DefenseBonus:
  291. return phe.cnc.gui.util.Numbers.formatNumbers(gainOrLoss) + '%';
  292. };
  293. },
  294.  
  295. /**
  296. * @param {Object} object
  297. * @returns {Object}
  298. */
  299. shallowClone: function(object) {
  300. var clone = new object.constructor;
  301.  
  302. for (var key in object) {
  303. if (object.hasOwnProperty(key)) {
  304. clone[key] = object[key];
  305. }
  306. }
  307.  
  308. return clone;
  309. }
  310. }
  311. });
  312. }
  313.  
  314. function waitForGame() {
  315. try {
  316. if (typeof qx !== 'undefined' && qx.core.Init.getApplication() && qx.core.Init.getApplication().initDone) {
  317. createRealPOIBonus();
  318. RealPOIBonus.getInstance().initialize();
  319. }
  320. else {
  321. setTimeout(waitForGame, 1000);
  322. }
  323. }
  324. catch (e) {
  325. console.log('RealPOIBonus: ', e.toString());
  326. }
  327. }
  328.  
  329. setTimeout(waitForGame, 1000);
  330. };
  331.  
  332. var script = document.createElement('script');
  333. script.innerHTML = '(' + main.toString() + ')();';
  334. script.type = 'text/javascript';
  335. document.getElementsByTagName('head')[0].appendChild(script);
  336. })();
Advertisement
Add Comment
Please, Sign In to add comment