TW Friends IT

Friend Management for The West Events

  1. // ==UserScript==
  2. // @name TW Friends IT
  3. // @name:it TW Friends Italiano
  4. // @version 0.28
  5. // @license LGPLv3
  6. // @description Friend Management for The West Events
  7. // @description:it Gestione Amici nei eventi The West
  8. // @author hiroaki
  9. // @translation Jackson (it_IT)
  10. // @include http*://*.the-west.*/game.php*
  11. // @include http*://*.tw.innogames.*/game.php*
  12. // @grant none
  13. // @namespace https://gf.qytechs.cn/users/3197
  14. // @icon https://cdn.rawgit.com/TWFriends/scripts/master/friends.png
  15. // ==/UserScript==
  16.  
  17. function hiroFriendsScript(fn) {
  18. var script = document.createElement('script');
  19. script.setAttribute("type", "application/javascript");
  20. script.textContent = '(' + fn + ')();';
  21. document.body.appendChild(script);
  22. document.body.removeChild(script);
  23. }
  24. hiroFriendsScript(function() {
  25. var VERSION = 0.28;
  26. var installURL = "https://gf.qytechs.cn/it/scripts/31148-tw-friends-it";
  27. var codeURL = "https://gf.qytechs.cn/scripts/31148-tw-friends-it/code/TW%20Friends%20IT.user.js";
  28. var versionURL = "https://gist.githubusercontent.com/TWFriends/974718d615afe3d2c2a2/raw/version?"+Date.now();
  29. var scriptName = "TW Friends Italiano";
  30. var scriptAuthor = "hiroaki";
  31. var scriptTranslate = "Jackson";
  32. var refreshMs = 10 * 60 * 1e3; // 10 minutes
  33. var enableLog = true;
  34. var enableInv = true;
  35. var enableVersionCheck = false;
  36. HiroFriends = {
  37. api: TheWestApi.register('HiroFriends', scriptName, '2.04', Game.version.toString(), scriptAuthor, scriptTranslate, installURL),
  38. version: VERSION,
  39. latestVersion: undefined,
  40. storageItem: "HiroFriends.version",
  41. cdnBase: '',
  42. eventCurrencyImage : '',
  43. eventName : '',
  44. eventInfo : {},
  45. eventEndStamp : 0,
  46. friends : {},
  47. interval: false,
  48. locale: 'it_IT',
  49. pendingInvitations: 0,
  50. messages: {
  51. it_IT: {
  52. description: '<h1>Gestione Amici nei eventi The West</h1><p style="margin: 8pt;">Eventi supportati:</p><ul style="list-style: disc outside; margin-left: 16pt; padding-left: 16pt;"><li>Il Giorno di SanValentino</li><li>Pasqua</li><li>Giorno dell&#039;Indipendenza</li><li>Oktoberfest</li><li>Il giorno della morte</li></ul><p style="margin: 8pt;"><a target="_blank" href="https://gf.qytechs.cn/it/users/136590-ruslan-jackson">Feedback</a>: Translation error. </p><p style="margin: 8pt;"><b>Credits</b>: Jackson</p>',
  53. version: 'versione',
  54. upgrade: 'Nuova versione disponibile. Vuoi aggiornare adesso?',
  55. refresh: 'Aggiorna',
  56. timeLeft: 'Tempo rimasto alla fine dell&#039;evento',
  57. serverTime: 'orario server',
  58. availFriends: 'Totale amici che puoi inviare adesso',
  59. totalFriends: 'Totale amici',
  60. pendingInvitation: 'Invito in attesa',
  61. pendingInvitations: 'inviti in attesa',
  62. noFriends: 'Non ci sono amici',
  63. name: 'Nome',
  64. received: 'Ricevuto',
  65. frequency: 'Frequenza',
  66. removeFriend: 'Cancella amico',
  67. removeConfirm: 'Sei sicuro di voler rimouvere l&#039;amico dalla lista?',
  68. removeSuccess: 'L&#039;amico rimosso con successo.',
  69. removeFailed: 'Impossibile rimuovere l&#039;amico',
  70. exporter: 'Esporta',
  71. everything: 'Tutto',
  72. stats: 'Statistiche',
  73. since: 'dal',
  74. collected: 'Collezionate',
  75. friends: 'Amici',
  76. jobs: 'Lavori',
  77. fortBattles: 'Bataglie ai forti',
  78. adventures: 'Avventure',
  79. duels: 'Duelli',
  80. npcDuels: 'NPC Duelli',
  81. construction: 'Costruzioni',
  82. quests: 'Missioni',
  83. itemUse: 'Oggetti usati',
  84. other: 'Altro',
  85. used: 'Usato',
  86. timerReset: 'Reseta orario',
  87. bribe: 'Bribe',
  88. gameAction: 'Azione evento del gioco',
  89. inventory: 'Inventario',
  90. nextYear: 'Anno prossimo',
  91. theEnd: 'Fine',
  92. },
  93. },
  94. timeLeft : 0,
  95. total : 0,
  96. avail: 0,
  97. log: { firstLog: Date.now()/1e3, lastLog: 0, newLastLog: 0, friendLog: {}, entries: [], count_friends: 0, count_job: 0, count_duel: 0, count_npc: 0, count_fort: 0, count_mpi: 0, count_quest: 0, count_build: 0, count_item: 0, count_other: 0, count_reset: 0, count_bribe: 0, count_action: 0, times_reset: 0, times_bribe: 0, received: 0, used: 0 },
  98. spanCounter: $("<span />", { id: "hiro_friends_counter", style: "position: absolute; right: 5px; color: #f8c57c; font-size: 13pt; height: 25px; line-height: 25px; bottom: 0px" }),
  99. spanInvitations: null,
  100. spanTimeLeft: null,
  101. divFriendsAvail: null,
  102. imgFriendsAvail: null,
  103. /* Inno buildDateObject() function currently buggy */
  104. buildDateObject: function(timeStr, isServerTime) {
  105. var regEx, match, d = new Date(0), today = new Date();
  106. regEx = /^(?:(3[01]|[012]?[0-9]|\*)\.(?:(1[012]|0?[1-9]|\*)\.((?:19|20)?\d\d|\*)))?(?: ?(2[0-3]|[01]?\d|\*)\:([0-5]?\d|\*)(?:\:([0-5]?\d|\*))?)?$/;
  107. if(match = timeStr.match(regEx)) {
  108. d.setFullYear(match[3] !== undefined ? (match[3] == '*' ? today.getFullYear() : parseInt(match[3], 10)) : today.getFullYear());
  109. d.setMonth(match[2] !== undefined ? (match[2] == '*' ? today.getMonth() : parseInt(match[2], 10) - 1) : today.getMonth());
  110. d.setDate(match[1] !== undefined ? (match[1] == '*' ? today.getDate() : parseInt(match[1], 10)) : today.getDate());
  111. d.setHours(match[4] !== undefined ? (match[4] == '*' ? today.getHours() : match[4]) : 0);
  112. d.setMinutes(match[5] !== undefined ? (match[5] == '*' ? today.getMinutes() : match[5]) : 0);
  113. d.setSeconds(match[6] !== undefined ? (match[6] == '*' ? today.getSeconds() : match[6]) : 0);
  114. d.setMilliseconds(0);
  115. }
  116. if(isServerTime) d = new Date(d - Game.serverTimeDifference);
  117. return d;
  118. },
  119. buildTimeStamp: function (timeStr, isServerTime) {
  120. return this.buildDateObject(timeStr, isServerTime).getTime();
  121. },
  122. items: {
  123. Hearts: {
  124. 2557000 : 1250, /* Small Heart Bag - 1250 hearts */
  125. 2558000 : 2500, /* Large Heart Bag - 2500 hearts */
  126. 2561000 : 100, /* Love Apple - 100 hearts */
  127. 2562000 : 500, /* Sugar hearts - 500 hearts */
  128. 2563000 : 650, /* 650 hearts */
  129. 2564000 : 1500, /* 1500 hearts */
  130. 2565000 : 3250, /* 3250 hearts */
  131. 2566000 : 9000, /* 9000 hearts */
  132. 2567000 : 16000, /* 16000 hearts */
  133. },
  134. Easter: {
  135. 2698000 : 2500, /* Efficient Easter egg container - 2500 eggs */
  136. 2590000 : 650, /* 650 Eggs */
  137. 2591000 : 1500, /* 1500 Eggs */
  138. 2592000 : 3250, /* 3250 Eggs */
  139. 2593000 : 9000, /* 9000 Eggs */
  140. 2594000 : 16000, /* 16000 Eggs */
  141. },
  142. Independence: {
  143. 2619000 : 650,
  144. 2620000 : 1500,
  145. 2621000 : 3250,
  146. 2622000 : 9000,
  147. 2623000 : 16000,
  148. },
  149. Octoberfest: {
  150. 371000 : 650,
  151. 973000 : 1500,
  152. 974000 : 3250,
  153. 975000 : 9000,
  154. 976000 : 16000,
  155. },
  156. DayOfDead: {
  157. 2665000 : 1250, /* Flower pot - 1250 Cempasúchil flowers */
  158. 2666000 : 2500, /* Big Flower pot - 2500 Cempasúchil flowers */
  159. 2675000 : 25, /* Cempasúchil Case - 25 Cempasúchil flowers */
  160. 2676000 : 650,
  161. 2677000 : 1500,
  162. 2678000 : 3250,
  163. 2679000 : 9000,
  164. 2680000 : 16000,
  165. }
  166. },
  167. eventItems: {
  168. divInventory: null,
  169. imgInventory: null,
  170. imgTitle: '',
  171. Inventory: [],
  172. Available: [],
  173. total: 0,
  174. coolDownComplete: false,
  175. check: function () {
  176. HiroFriends.eventItems.Inventory = [];
  177. HiroFriends.eventItems.Available = [];
  178. HiroFriends.eventItems.total = 0;
  179. HiroFriends.eventItems.coolDownComplete = false;
  180. if(undefined === HiroFriends.items[HiroFriends.eventName]) return false;
  181. var now = new ServerDate().getTime()/1e3, coolDown, invItem;
  182. $.each(HiroFriends.items[HiroFriends.eventName], function(itemId, amount) {
  183. invItem = Bag.getItemByItemId(itemId);
  184. if(invItem) {
  185. HiroFriends.eventItems.Inventory.push(invItem);
  186. coolDown = Bag.itemCooldown[itemId];
  187. if(!coolDown) {
  188. HiroFriends.eventItems.Available.push(invItem);
  189. HiroFriends.eventItems.total += invItem.count*amount;
  190. }
  191. else if(coolDown <= now) {
  192. HiroFriends.eventItems.coolDownComplete = true;
  193. HiroFriends.eventItems.Available.push(invItem);
  194. HiroFriends.eventItems.total += amount;
  195. }
  196. }
  197. });
  198. HiroFriends.eventItems.imgInventory.attr('src', HiroFriends.eventItems.coolDownComplete ? HiroFriends.cdnBase+'/images/icons/clock.png' : HiroFriends.eventCurrencyImage);
  199. HiroFriends.eventItems.imgInventory.attr('title', HiroFriends.eventItems.total ? HiroFriends.eventItems.total+' <img src="' + HiroFriends.eventCurrencyImage + '" alt="">' : '');
  200. return true;
  201. },
  202. display: function() {
  203. HiroFriends.eventItems.check();
  204. if(HiroFriends.eventItems.Inventory.length > 0) {
  205. if(!Bag.loaded) {
  206. EventHandler.listen('inventory_loaded', function () {
  207. Wear.open();
  208. Inventory.showSearchResult(HiroFriends.eventItems.Inventory);
  209. return EventHandler.ONE_TIME_EVENT;
  210. });
  211. Bag.loadItems();
  212. }
  213. else {
  214. Wear.open();
  215. Inventory.showSearchResult(HiroFriends.eventItems.Inventory);
  216. }
  217. }
  218. HiroFriends.eventItems.divInventory.hide();
  219. },
  220. },
  221. display: function(sort) {
  222. var friend_time, server_time = Game.getServerTime();
  223. var maindiv = $('<div class="hiro_friends_maindiv" />');
  224. var friends = [];
  225. for(var key in this.friends) if(this.friends.hasOwnProperty(key)) friends.push({ id: key, name: this.friends[key].name, activation_time: this.friends[key].activation_time, recv: this.friends[key].recv });
  226. if(!friends.length) $('<h1 style="text-align: center; color: #990000; margin-bottom: 80px;">'+this.localeMsg('noFriends')+'</h1>').appendTo(maindiv);
  227. else {
  228. var hiroTable;
  229. switch(sort) {
  230. case "name" : friends.sort(this.sortByName); break;
  231. case "name_desc": friends.sort(this.sortByName).reverse(); break;
  232. case "recv" : friends.sort(this.sortByRecv); break;
  233. case "recv_asc" : friends.sort(this.sortByRecv).reverse(); break;
  234. case "time_asc" : friends.sort(this.sortByTime).reverse(); break;
  235. case "time" :
  236. default : sort = "time"; friends.sort(this.sortByTime);
  237. }
  238. var thName = $('<a style="cursor: pointer;"><img src="'+this.cdnBase+'/images/icons/user.png" alt="" />&nbsp;'+this.localeMsg('name')+'</a>').click(function(){ HiroFriends.display(sort == 'name' ? 'name_desc' : 'name'); return false; });
  239. var thAction = $('<a style="cursor: pointer;"><img src="'+this.cdnBase+'/images/icons/clock.png" alt="" />&nbsp;'+this.eventInfo.label+'</a>').click(function(){ HiroFriends.display(sort == 'time' ? 'time_asc' : 'time'); return false; });
  240. var thRecv = enableLog ? $('<a style="cursor: pointer;" title="'+this.localeMsg('since')+' '+new Date(this.log.firstLog*1e3).toDateTimeString()+'"><img src="'+this.cdnBase+'/images/icons/watch.png" alt="" />&nbsp;'+this.localeMsg('received')+'</a>').click(function(){ HiroFriends.display(sort == 'recv' ? 'recv_asc' : 'recv'); return false; }) : '';
  241. hiroTable = new west.gui.Table().appendTo(maindiv).addColumn("hf_idx").addColumn("hf_player").addColumn("hf_action").addColumn("hf_log").addColumn("hf_delete").appendToCell("head", "hf_idx", '&nbsp;').appendToCell("head", "hf_player", thName).appendToCell("head", "hf_action", thAction).appendToCell("head","hf_log",thRecv).appendToCell("head", "hf_delete", '&nbsp;');
  242. var idx = 1;
  243. var now = Date.now()/1e3;
  244. $.each(friends, function(key, val) {
  245. var actionCell, recvCell;
  246. friend_time = val.activation_time + HiroFriends.eventInfo.cooldown - server_time;
  247. if(friend_time > HiroFriends.timeLeft) actionCell = '('+HiroFriends.localeMsg('nextYear')+')';
  248. else if(friend_time > 0) actionCell = '('+friend_time.formatDurationBuffWay()+')';
  249. else {
  250. actionCell = $('<a style="cursor: pointer;">'+HiroFriends.eventInfo.label+'</a>').click({ id: val.id, ev: HiroFriends.eventName }, function(e) {
  251. $(this).parent().parent().remove();
  252. Ajax.remoteCall("friendsbar", "event", { player_id: val.id, event: HiroFriends.eventName }, function(response) {
  253. if(response.error) return MessageError(response.msg).show();
  254. MessageSuccess(response.msg).show();
  255. HiroFriends.friends[val.id].activation_time = Date.now()/1e3;
  256. if(HiroFriends.avail) -- HiroFriends.avail;
  257. HiroFriends.updateCounter();
  258. if(WestUi.FriendsBar.friendsBarUi !== null)
  259. WestUi.FriendsBar.friendsBarUi.friendsBar.eventActivations[val.id][HiroFriends.eventName] = response.activationTime;
  260. });
  261. return false;
  262. });
  263. }
  264. recvCell = '';
  265. if(enableLog) {
  266. if(val.recv) {
  267. var recv_list = '';
  268. HiroFriends.log.friendLog[val.id].dates.sort(function(a, b){ return new Date(a)-new Date(b); });
  269. if(HiroFriends.log.friendLog[val.id].total && HiroFriends.log.friendLog[val.id].dates.length > 1) {
  270. recv_list += '<p style=&quot;text-align: center; margin-bottom: 8px;&quot;>'+HiroFriends.localeMsg('frequency')+': <b>'+((now - HiroFriends.log.friendLog[val.id].dates[0]) / (HiroFriends.log.friendLog[val.id].dates.length-1)).formatDuration()+'</b></p>';
  271. }
  272. recv_list += '<ol style=&quot;list-style-type: decimal; padding: 0 0 0 20px;&quot;>';
  273. $.each(HiroFriends.log.friendLog[val.id].dates, function(dkey, dval) {
  274. recv_list += '<li style=&quot;display: list-item; white-space: nowrap;&quot;>' + new Date(dval * 1e3).toDateTimeStringNice() + '</li>';
  275. });
  276. recv_list += '<ol>';
  277. recvCell = '<span title="'+recv_list+'" style="cursor: help;">'+val.recv+'</span>';
  278. }
  279. else recvCell = val.recv;
  280. }
  281. hiroTable.appendRow(null, 'hiroFriendRow_'+val.id)
  282. .appendToCell(-1, "hf_idx", idx)
  283. .appendToCell(-1, "hf_player", '<a href="javascript:void(PlayerProfileWindow.open('+val.id+'));">' + val.name + '</a>')
  284. .appendToCell(-1, "hf_action", actionCell)
  285. .appendToCell(-1, "hf_log", recvCell)
  286. .appendToCell(-1, "hf_delete", '<a href="javascript:void(HiroFriends.removeFriend('+val.id+'));"><img style="width:16px; height: 16px;" title="'+HiroFriends.localeMsg('removeFriend')+'" src="'+HiroFriends.cdnBase+'/images/icons/delete.png" alt="delete" /></a>');
  287. ++ idx;
  288. });
  289. hiroTable.appendToCell('foot', 'hf_idx', '<a target="_blank" href="'+installURL+'"><img src="'+this.cdnBase+'/images/icons/link.png" alt=""></a>');
  290. hiroTable.appendToCell('foot', 'hf_player', '<a target="_blank" href="'+installURL+'">'+scriptName+'</a> '+this.localeMsg('version')+' ' + this.version.toFixed(2));
  291. if('https://it1.the-west.it' == Game.gameURL || 'https://it13.the-west.it' == Game.gameURL || 'https://it5.the-west.gr' == Game.gameURL) hiroTable.appendToCell('foot', 'hf_action', 'tradotto da <a href="javascript:void(PlayerProfileWindow.open(542314));">'+scriptTranslate+'</a>');
  292. else if('https://zz1.beta.the-west.net' == Game.gameURL) hiroTable.appendToCell('foot', 'hf_action', 'by <a href="javascript:void(PlayerProfileWindow.open(542314));">'+scriptTranslate+'</a>');
  293. else hiroTable.appendToCell('foot', 'hf_action', 'trad. '+scriptTranslate);
  294. if(this.pendingInvitations) hiroTable.appendToCell('foot', 'hf_delete', '<a href="javascript:void(FriendslistWindow.open(\'openrequests\'));"><img style="width:16px; height: 16px;" title="'+this.pendingInvitationsMsg()+'" src="'+this.cdnBase+'/images/icons/friends.png" alt="add" /></a>');
  295. if(enableLog) hiroTable.appendToCell('foot', 'hf_log', $('<a style="cursor: pointer;">'+HiroFriends.localeMsg('exporter')+'</a>').click(function() {
  296. HiroFriends.log.entries.sort(function(a,b) { return a.date - b.date; });
  297. var tsv_friends = "id\t"+HiroFriends.localeMsg('name')+"\t"+HiroFriends.localeMsg('received')+"\r\n";
  298. $.each(HiroFriends.log.friendLog, function(key,val) { tsv_friends += key+"\t"+val.name+"\t"+val.total+"\r\n"; });
  299. new west.gui.Dialog(HiroFriends.localeMsg('exporter'),'<b>'+HiroFriends.localeMsg('friends')+'</b> (<a download="TW Friends - '+HiroFriends.eventName+' - '+ Game.worldName+' - '+Character.name+' - '+HiroFriends.localeMsg('friends')+' - '+Date.now()+'.tsv" href="data:text/tab-separated-values,'+encodeURI(tsv_friends)+'">TSV</a>):<br /><textarea cols="60" rows="8" style="width: 100%; height: 100px;">' + JSON.stringify(HiroFriends.log.friendLog) + '</textarea><br /><b>'+HiroFriends.localeMsg('everything')+'</b>:<br /><textarea cols="60" rows="8" style="width: 100%; height: 100px;">' + JSON.stringify(HiroFriends.log.entries) + '</textarea>').setModal(true,true,{bg:HiroFriends.cdnBase+'/images/curtain_bg.png',opacity:0.7}).addButton("ok").show();
  300. return false;
  301. }) );
  302. }
  303. if(enableLog || this.eventItems.total) {
  304. var statsTable = '<table style="margin: auto; width: 96%;">';
  305. if(enableLog) statsTable += '<tr><th colspan="3" style="border-bottom: 1px dotted;">'+this.localeMsg('stats')+' ('+this.localeMsg('since')+' '+new Date(this.log.firstLog*1e3).toDateTimeString()+')</th></tr><tr style="vertical-align: top;"><td style="white-space: nowrap;">'+this.localeMsg('collected')+':</td><td style="color: #006600; font-weight: bold; text-align: right; padding-right: 8pt;">'+this.log.received+'</td><td> <span style="white-space: nowrap;">'+this.localeMsg('friends')+': <b>'+this.log.count_friends+'</b>,</span> <span style="white-space: nowrap;">'+this.localeMsg('jobs')+': <b>'+this.log.count_job+'</b>,</span> <span style="white-space: nowrap;">'+this.localeMsg('fortBattles')+': <b>'+this.log.count_fort+'</b>,</span> <span style="white-space: nowrap;">'+this.localeMsg('adventures')+': <b>'+this.log.count_mpi+'</b>,</span> <span style="white-space: nowrap;">'+this.localeMsg('duels')+': <b>'+this.log.count_duel+'</b>,</span> <span style="white-space: nowrap;">'+this.localeMsg('npcDuels')+': <b>'+this.log.count_npc+'</b>,</span> <span style="white-space: nowrap;">'+this.localeMsg('construction')+': <b>'+this.log.count_build+'</b>,</span> <span style="white-space: nowrap;">'+this.localeMsg('quests')+': <b>'+this.log.count_quest+'</b>,</span> <span style="white-space: nowrap;">'+this.localeMsg('itemUse')+': <b>'+this.log.count_item+'</b>,</span> <span style="white-space: nowrap;">'+this.localeMsg('other')+': <b>'+this.log.count_other+'</b></span></td></tr>'+(this.log.used?'<tr style="vertical-align: top;"><td style="white-space: nowrap;">'+this.localeMsg('used')+':</td><td style="color: #660000; font-weight: bold; text-align: right; padding-right: 8pt;">'+this.log.used+'</td><td>'+(this.log.count_reset?'<span style="white-space: nowrap;">'+this.localeMsg('timerReset')+': <b>'+this.log.count_reset+'</b> (#'+this.log.times_reset+'),</span> ' : '')+(this.log.count_action?'<span style="white-space: nowrap;">'+this.localeMsg('gameAction')+': <b>'+this.log.count_action+'</b>,</span> ' : '')+(this.log.count_bribe?'<span style="white-space: nowrap;">'+this.localeMsg('bribe')+': <b>'+this.log.count_bribe+'</b> (#'+this.log.times_bribe+')</span>' : '')+'</td></tr>' : '');
  306. if(this.eventItems.total) statsTable += '<tr><td style="white-space: nowrap;">'+this.localeMsg('inventory')+':</td><td style="text-align: right; padding-right: 8pt;"><a href="javascript:void(HiroFriends.eventItems.display());">'+this.eventItems.total+'</a></td><td>&nbsp;</td></tr>';
  307. statsTable += '</table>';
  308. $(statsTable).appendTo(maindiv);
  309. }
  310. var hiroPane = new west.gui.Scrollpane();
  311. hiroPane.appendContent(maindiv);
  312. var hiroWindow = wman.open("HiroFriends_"+this.eventName, null, "noreload").setMiniTitle(this.eventInfo.label).setTitle(this.eventInfo.label).appendToContentPane(hiroPane.getMainDiv());
  313. },
  314. eventManager: function(eventName) {
  315. if(undefined === Game.sesData[eventName] || undefined === Game.sesData[eventName].friendsbar) return false;
  316. this.eventName = eventName;
  317. this.eventInfo = Game.sesData[eventName].friendsbar;
  318. if(undefined === Game.sesData[this.eventName].meta.end) return false;
  319. this.eventEndStamp = (this.buildTimeStamp(Game.sesData[this.eventName].meta.end) - Game.serverTimeDifference) / 1e3;
  320. this.timeLeft = this.eventEndStamp - Game.getServerTime();
  321. if(this.timeLeft < 0) return false;
  322. this.cdnBase = (undefined === Game.cdnURL) ? "https://westzzs.innogamescdn.com" : Game.cdnURL;
  323. $.when(this.getLog()).done(function() {
  324. HiroFriends.design();
  325. });
  326. },
  327. design: function() {
  328. HiroFriends.spanTimeLeft = $("<span />", { id: "hiro_event_timeleft", style: "position: absolute; left: 5px; color: #d3d3d3; font-size: 11px; height: 25px; line-height: 25px; cursor: pointer", title: HiroFriends.localeMsg('timeLeft')+'<br />('+new Date(HiroFriends.buildTimeStamp(Game.sesData[HiroFriends.eventName].meta.end)).toDateTimeStringNice()+' '+HiroFriends.localeMsg('serverTime')+')' });
  329. var eventImage = HiroFriends.cdnBase + "/images/interface/friendsbar/events/" + HiroFriends.eventName + ".png"; // event based
  330. if(HiroFriends.eventName == 'Octoberfest') eventImage = HiroFriends.cdnBase + "/images/window/events/octoberfest/pretzels_icon.png";
  331. var divContainer = $("<div />", { id: "hiro_friends_container", style: "position: absolute; top: 32px; right: 50%; margin-right: 120px; z-index: 16; width: 180px; height: 36px; text-align: left; text-shadow: 1px 1px 1px #000; background: url('"+HiroFriends.cdnBase+"/images/interface/custom_unit_counter_sprite.png?2') no-repeat scroll 50% 0px transparent;" })
  332. var divCounter = $("<div />", { id: "hiro_friends", style: "background: url('"+HiroFriends.cdnBase+"/images/interface/custom_unit_counter_sprite.png?2') no-repeat scroll 0 -36px rgba(0, 0, 0, 0); height: 25px; left: 32px; line-height: 25px; padding: 0 5px; position: absolute; top: 3px; width: 105px; z-index: 1; text-shadow: 1px 1px 1px #000;" });
  333. var divRefresh = $("<div />", { style: "width: 24px; height: 24px; position: absolute; left: 8px; top: 3px; z-index: 3; padding: 4px 0px 0px 4px;" });
  334. var spanRefresh = $('<span />', { title: HiroFriends.localeMsg('refresh'), style: "display: inline-block; width: 20px; height: 20px; cursor: pointer; background: url('"+HiroFriends.cdnBase+"/images/tw2gui/window/window2_buttons.png?5') repeat scroll 0px -20px transparent;" });
  335. var spanSend = $("<span />", { style: "width: 26px; height: 26px; left: auto; position: absolute; right: 7px; top: 2px; z-index: 3;" });
  336. var imageSend = $("<img />", { src: eventImage, title: HiroFriends.eventInfo.label, style: "width: 26px; height: 26px; cursor: pointer" });
  337. if(HiroFriends.pendingInvitations) {
  338. HiroFriends.spanCounter.css("right", "20px");
  339. HiroFriends.spanInvitations = $("<span />", { id: "hiro_friends_invitations", title: HiroFriends.pendingInvitationsMsg(), style: "position: absolute; right: 0px; width: 19px; height: 25px; background-image: url('"+HiroFriends.cdnBase+"/images/interface/more.jpg'); background-repeat: no-repeat;" });
  340. HiroFriends.spanInvitations.hover(function() { $(this).css("background-position", "0px -25px"); }, function() { $(this).css("background-position", ""); });
  341. HiroFriends.spanInvitations.click(function() { $(this).hide(); HiroFriends.spanCounter.css("right", "5px"); FriendslistWindow.open('openrequests'); return false; });
  342. divCounter.append(HiroFriends.spanInvitations);
  343. }
  344. divContainer.append(divRefresh.append(spanRefresh), spanSend.append(imageSend), divCounter.append(HiroFriends.spanTimeLeft, HiroFriends.spanCounter)).appendTo("#user-interface");
  345. spanRefresh.hover(function() { $(this).css("background-position", ""); }, function() { $(this).css("background-position", "0px -20px"); });
  346. spanRefresh.click(function() { HiroFriends.spanCounter.slideUp(500, function() { HiroFriends.fetch(); }).slideDown(1500); return false; });
  347. imageSend.click(function() { HiroFriends.open(); return false; });
  348. HiroFriends.eventCurrencyImage = "/images/icons/"+HiroFriends.eventName+".png";
  349. if(enableInv) {
  350. HiroFriends.eventItems.divInventory = $("<div />", { id: "hiro_friends_inventory_container", style: "position: absolute; top: 0px; right: 0px; z-index: 18; width: 20px; height: 18px;" }).hide().appendTo("#ui_bottombar .ui_bottombar_wrapper .button:first .dock-image");
  351. HiroFriends.eventItems.imgInventory = $('<img src="'+HiroFriends.eventCurrencyImage+'" alt="" title="">').click(function(e){ e.preventDefault(); HiroFriends.eventItems.display(); return false; }).appendTo(HiroFriends.eventItems.divInventory);
  352. }
  353. HiroFriends.divFriendsAvail = $("<div />", { id: "hiro_friends_bottombar_friends", style: "position: absolute; top: 0px; right: 0px; z-index: 18; width: 20px; height: 18px;" }).hide().appendTo("#ui_bottombar .ui_bottombar_wrapper .button:nth-child(3) .dock-image");
  354. HiroFriends.imgFriendsAvail = $('<img src="'+HiroFriends.eventCurrencyImage+'" alt="" title="'+scriptName+'">').click(function(e){ e.preventDefault(); HiroFriends.open(); return false; }).appendTo(HiroFriends.divFriendsAvail);
  355. HiroFriends.updateTimer();
  356. if(typeof(Storage) !== "undefined") {
  357. var previousVersion = (localStorage.getItem(HiroFriends.storageItem) === null) ? 0 : parseFloat(localStorage.getItem(HiroFriends.storageItem));
  358. localStorage.setItem(HiroFriends.storageItem, HiroFriends.version);
  359. // if(previousVersion && HiroFriends.version > previousVersion) var msg=new west.gui.Dialog("TW Friends", "Script upgraded to version "+HiroFriends.version, west.gui.Dialog.SYS_WARNING).addButton("OK").show();
  360. }
  361. $("<style>.hf_idx { width: 32px; text-align: right; padding-right: 8px; } .hf_player { width: 250px; } .hf_action { width: 200px; } .hf_log { width: 100px; text-align: right; padding-right: 8px; } .hf_delete { width: 40px; text-align: center; } div.tbody .hf_idx, div.tbody .hf_delete { background-image: url('"+HiroFriends.cdnBase+"/images/tw2gui/table/cell_shadow_y.png'); }</style>").appendTo("head");
  362. HiroFriends.fetch();
  363. },
  364. fetch: function() {
  365. if(this.interval !== false) clearInterval(this.interval);
  366. var event_times = {};
  367. var friends = {}, total = 0, avail = 0, recv = 0;
  368. var server_time = Game.getServerTime(), activation_time, friend_time;
  369. if(this.timeLeft < 0) {
  370. $("#hiro_friends_container").slideUp(5000);
  371. if(enableInv) HiroFriends.eventItems.divInventory.hide(5000);
  372. throw "Event is over";
  373. }
  374. if(enableInv) {
  375. if(HiroFriends.eventItems.check() && HiroFriends.eventItems.Available.length > 0)
  376. HiroFriends.eventItems.divInventory.show(5000);
  377. else HiroFriends.eventItems.divInventory.hide();
  378. }
  379. return $.post("/game.php?window=friendsbar&mode=search", { search_type: "friends" } , function(data) {
  380. $.each(data.eventActivations, function(key, val) {
  381. if(val.event_name == HiroFriends.eventName) event_times[val.friend_id] = val.activation_time;
  382. });
  383. $.each(data.players, function(key, val) {
  384. if(val.name !== Character.name) {
  385. activation_time = (event_times[val.player_id] !== undefined) ? event_times[val.player_id]: 0;
  386. if(undefined === HiroFriends.log.friendLog[val.player_id]) {
  387. recv = 0;
  388. HiroFriends.log.friendLog[val.player_id] = { name: val.name, total: 0, dates: [] };
  389. }
  390. else recv = HiroFriends.log.friendLog[val.player_id].total;
  391. friends[val.player_id] = { name: val.name, activation_time: activation_time, recv: recv };
  392. ++ total;
  393. if(activation_time + HiroFriends.eventInfo.cooldown - server_time <= 0) ++ avail;
  394. }
  395. });
  396. HiroFriends.friends = friends;
  397. HiroFriends.avail = avail;
  398. HiroFriends.total = total;
  399. HiroFriends.updateCounter();
  400. if(HiroFriends.avail) {
  401. HiroFriends.imgFriendsAvail.attr('title', 'TW Friends: '+HiroFriends.avail+'/'+HiroFriends.total);
  402. HiroFriends.divFriendsAvail.show(5000);
  403. }
  404. else HiroFriends.divFriendsAvail.hide();
  405. HiroFriends.interval = setInterval(function() { HiroFriends.fetch(); }, refreshMs);
  406. });
  407. },
  408. getLogPage: function(page, limit, deferred) {
  409. return $.ajax({ type: "POST", url: "/game.php?window=ses&mode=log", data: { ses_id: HiroFriends.eventName, page: page, limit: limit }, success: function(data) {
  410. var details;
  411. var hasNext = data.hasNext;
  412. var count = 0;
  413. var limit = data.limit;
  414. page = data.page + 1;
  415. $.each(data.entries, function(key, val) {
  416. count = parseInt(val.value);
  417. if(val.date < HiroFriends.log.firstLog) HiroFriends.log.firstLog = val.date;
  418. if(val.date <= HiroFriends.log.lastLog) {
  419. hasNext = false;
  420. return false;
  421. }
  422. HiroFriends.log.entries.push(val);
  423. if(val.date > HiroFriends.log.newLastLog) {
  424. HiroFriends.log.newLastLog = val.date;
  425. }
  426. switch(val.type) {
  427. case "friendDrop":
  428. if(null !== val.details) {
  429. details = JSON.parse(val.details);
  430. if(undefined !== HiroFriends.friends[details.player_id]) HiroFriends.friends[details.player_id].recv += count;
  431. if(undefined === HiroFriends.log.friendLog[details.player_id]) HiroFriends.log.friendLog[details.player_id] = { name: details.name, total: count, dates: [] };
  432. else HiroFriends.log.friendLog[details.player_id].total += count;
  433. HiroFriends.log.friendLog[details.player_id].dates.push(val.date);
  434. }
  435. HiroFriends.log.count_friends += count;
  436. HiroFriends.log.received += count;
  437. break;
  438. case "jobDrop": HiroFriends.log.count_job += count; HiroFriends.log.received += count; break;
  439. case "buildDrop": HiroFriends.log.count_build += count; HiroFriends.log.received += count; break;
  440. case "duelDrop": HiroFriends.log.count_duel += count; HiroFriends.log.received += count; break;
  441. case "duelNPCDrop": HiroFriends.log.count_npc += count; HiroFriends.log.received += count; break;
  442. case "battleDrop": HiroFriends.log.count_fort += count; HiroFriends.log.received += count; break;
  443. case "adventureDrop": HiroFriends.log.count_mpi += count; HiroFriends.log.received += count; break;
  444. case "questDrop": HiroFriends.log.count_quest += count; HiroFriends.log.received += count; break;
  445. case "itemUse": HiroFriends.log.count_item += count; HiroFriends.log.received += count; break;
  446. case "wofPay":
  447. HiroFriends.log.used += count;
  448. if(null !== val.details) {
  449. if(val.details == "timerreset") {
  450. HiroFriends.log.count_reset += count;
  451. ++ HiroFriends.log.times_reset;
  452. }
  453. else if(val.details == "sneakyshot") {
  454. HiroFriends.log.count_bribe += count;
  455. ++ HiroFriends.log.times_bribe;
  456. }
  457. }
  458. break;
  459. default:
  460. HiroFriends.log.count_other += count;
  461. HiroFriends.log.received += count;
  462. }
  463. });
  464. if (hasNext) return HiroFriends.getLogPage(page, limit, deferred);
  465. else {
  466. /* Done */
  467. HiroFriends.log.lastLog = HiroFriends.log.newLastLog;
  468. Chat.Request.Nop();
  469. deferred.resolve();
  470. }
  471. } });
  472. },
  473. getLog: function() {
  474. if(enableLog) {
  475. var deferred = new $.Deferred();
  476. var limit = 100;
  477. HiroFriends.log.newLastLog = HiroFriends.log.lastLog;
  478. this.getLogPage(1, limit, deferred);
  479. return deferred.promise();
  480. }
  481. },
  482. getPendingInvitations: function() {
  483. return $.post("/game.php?window=character&mode=get_open_requests", function(data) {
  484. var openReq = 0;
  485. $.each(data.open_friends, function(key, val) { if(val.inviter_id != Character.playerId) ++ openReq; });
  486. HiroFriends.pendingInvitations = openReq;
  487. });
  488. },
  489. localeMsg: function(msg) {
  490. if(undefined !== this.messages[this.locale][msg]) return this.messages[this.locale][msg];
  491. if(undefined !== this.messages['en_US'][msg]) return this.messages['en_US'][msg];
  492. return '';
  493. },
  494. open: function() {
  495. if(!WestUi.FriendsBar.hidden) WestUi.FriendsBar.toggle();
  496. $.when(this.getLog()).done(function() {
  497. HiroFriends.fetch().done(function() {
  498. HiroFriends.divFriendsAvail.hide();
  499. HiroFriends.getPendingInvitations().done(function() {
  500. HiroFriends.display('time');
  501. });
  502. });
  503. });
  504. },
  505. pendingInvitationsMsg: function() { return this.pendingInvitations == 1 ? this.localeMsg('pendingInvitation') : this.pendingInvitations+' '+this.localeMsg('pendingInvitations'); },
  506. removeFriend: function(charId) {
  507. new west.gui.Dialog(HiroFriends.localeMsg('removeFriend'), HiroFriends.localeMsg('removeConfirm')).setIcon(west.gui.Dialog.SYS_QUESTION).addButton("yes", function() {
  508. Ajax.remoteCall('character', 'cancel_friendship', { friend_id: charId }, function(json) {
  509. if(json["result"]) {
  510. new UserMessage(HiroFriends.localeMsg('removeSuccess'), UserMessage.TYPE_SUCCESS).show();
  511. $("div.hiroFriendRow_" + charId).remove();
  512. $("div.friendData_" + charId, FriendslistWindow.DOM).remove();
  513. delete(HiroFriends.friends[charId]);
  514. if(HiroFriends.avail) -- HiroFriends.avail;
  515. if(HiroFriends.total) -- HiroFriends.total;
  516. HiroFriends.updateCounter();
  517. Chat.Friendslist.removeFriend(charId);
  518. }
  519. else new UserMessage(HiroFriends.localeMsg('removeFailed'), UserMessage.TYPE_ERROR).show();
  520. })
  521. }).addButton("no").show();
  522. },
  523. sortByName: function(a, b) { return a.name.toLowerCase().localeCompare(b.name.toLowerCase()); },
  524. sortByRecv: function(a, b) { return b.recv - a.recv; },
  525. sortByTime: function(a, b) { return a.activation_time - b.activation_time; },
  526. updateCounter: function() {
  527. this.spanCounter.html('<span title="'+this.localeMsg('availFriends')+'">'+this.avail+'</span> <span style="color: #d3d3d3; font-size: 11px;" title="'+this.localeMsg('totalFriends')+'">/ '+this.total+'</span>');
  528. },
  529. updateTimer: function() {
  530. this.timeLeft = this.eventEndStamp - Game.getServerTime();
  531. if(this.timeLeft <= 0) {
  532. this.spanTimeLeft.html(this.localeMsg('theEnd'));
  533. this.fetch();
  534. return;
  535. }
  536. this.spanTimeLeft.html(this.timeLeft.formatDurationBuffWay());
  537. var seconds = 0;
  538. if(this.timeLeft < 70) seconds = 1;
  539. else if(this.timeLeft < 3660) seconds = 10;
  540. else if(this.timeLeft < 86520) seconds = 60;
  541. else seconds = 120;
  542. setTimeout(function() { HiroFriends.updateTimer(); }, seconds * 1e3);
  543. },
  544. scriptInit: function(tries, maxTries) {
  545. var ev, eventName;
  546. if(tries >= maxTries) return false;
  547. if(Game && Game.loaded && Character.playerId) {
  548. this.locale = (undefined === Game.locale || undefined == this.messages[Game.locale]) ? "en_US" : Game.locale;
  549. this.api.setGui(this.localeMsg('description'));
  550. if (enableVersionCheck) {
  551. try {
  552. $.getScript(versionURL).done(function() {
  553. if(HiroFriends.latestVersion && HiroFriends.latestVersion > VERSION) {
  554. var upgradeDialog = new west.gui.Dialog(scriptName, HiroFriends.localeMsg('upgrade'), west.gui.Dialog.SYS_WARNING).addButton('ok', function() {
  555. try { upgradeDialog.hide(); location.href = codeURL; } catch(e) {}
  556. }).addButton('cancel').show();
  557. }
  558. });
  559. }
  560. catch(e) { }
  561. }
  562. for(eventName in Game.sesData) {
  563. if(!Game.sesData.hasOwnProperty(eventName)) continue;
  564. var ev = Game.sesData[eventName];
  565. if(!ev.friendsbar) continue;
  566. if('Hearts' == eventName || 'Easter' == eventName || 'Independence' == eventName || 'DayOfDead' == eventName || 'Octoberfest' == eventName) {
  567. this.getPendingInvitations().done(function() {
  568. HiroFriends.eventManager(eventName);
  569. });
  570. return false;
  571. }
  572. }
  573. return true;
  574. }
  575. ++ tries;
  576. setTimeout(function() { HiroFriends.scriptInit(tries, maxTries); }, tries * 1e3);
  577. },
  578. }
  579. try { HiroFriends.scriptInit(0, 100); } catch(e) { }
  580. });
  581.  

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址