TW Friends

Friend Management for The West Events

目前为 2015-04-11 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name TW Friends
  3. // @name:el TW Friends
  4. // @version 0.16
  5. // @description Friend Management for The West Events
  6. // @description:el Διαχείριση Φίλων για τις Εκδηλώσεις του The West
  7. // @author hiroaki
  8. // @include http://*.the-west.*/game.php*
  9. // @include https://*.the-west.*/game.php*
  10. // @grant none
  11. // @namespace https://greasyfork.org/users/3197
  12. // ==/UserScript==
  13.  
  14. function hiroFriendsScript(fn) {
  15. var script = document.createElement('script');
  16. script.setAttribute("type", "application/javascript");
  17. script.textContent = '(' + fn + ')();';
  18. document.body.appendChild(script);
  19. document.body.removeChild(script);
  20. }
  21. hiroFriendsScript (function() {
  22. var VERSION = 0.16;
  23. var installURL = "https://greasyfork.org/scripts/2992-tw-friends";
  24. var refreshMs = 2 * 60 * 1000; // 2 minutes
  25. HiroFriends = {
  26. version: VERSION,
  27. storageItem: "HiroFriends.version",
  28. cdnBase: '',
  29. eventName : '',
  30. eventInfo : {},
  31. eventEndStamp : 0,
  32. friends : [],
  33. interval: false,
  34. timeLeft : 0,
  35. total : 0,
  36. avail: 0,
  37. log: { lastLog: 0, friendLog: {}, count_friends: 0, count_job: 0, count_duel: 0, count_npc: 0, count_fort: 0, count_mpi: 0, count_build: 0, count_other: 0, count_reset: 0, count_bribe: 0, times_reset: 0, times_bribe: 0, received: 0, used: 0 },
  38. spanCounter: $("<span />", { id: "hiro_friends_counter", style: "position: absolute; right: 5px; color: #f8c57c; font-size: 13pt; height: 25px; line-height: 25px; bottom: 0px" }),
  39. spanTimeLeft: $("<span />", { id: "hiro_event_timeleft", style: "position: absolute; left: 5px; color: #d3d3d3; font-size: 11px; height: 25px; line-height: 25px" })
  40. };
  41. HiroFriends.init = function(eventName) {
  42. if (undefined === Game.sesData[eventName] || undefined === Game.sesData[eventName].friendsbar) return false;
  43. HiroFriends.eventName = eventName;
  44. HiroFriends.eventInfo = Game.sesData[eventName].friendsbar;
  45. if (undefined === Game.sesData[HiroFriends.eventName].meta.end) return false;
  46. HiroFriends.eventEndStamp = (buildTimestamp(Game.sesData[HiroFriends.eventName].meta.end) - Game.serverTimeDifference) / 1000;
  47. HiroFriends.timeLeft = HiroFriends.eventEndStamp - Game.getServerTime();
  48. if (HiroFriends.timeLeft < 0) return false;
  49. HiroFriends.cdnBase = (undefined === Game.cdnURL) ? "https://westzzs.innogamescdn.com" : Game.cdnURL;
  50. HiroFriends.getLog();
  51. var eventImage = HiroFriends.cdnBase + "/images/interface/friendsbar/events/" + HiroFriends.eventName + ".png"; // event based
  52. 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;" })
  53. 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;" });
  54. var divRefresh = $("<div />", { style: "width: 24px; height: 24px; position: absolute; left: 8px; top: 3px; z-index: 3; padding: 4px 0px 0px 4px;" });
  55. var spanRefresh = $("<span >", { 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;" });
  56. var spanSend = $("<span />", { style: "width: 26px; height: 26px; left: auto; position: absolute; right: 7px; top: 2px; z-index: 3;" });
  57. var imageSend = $("<img />", { src: eventImage, title: HiroFriends.eventInfo.label, style: "width: 26px; height: 26px; cursor: pointer" });
  58. divContainer.append(divRefresh.append(spanRefresh), spanSend.append(imageSend), divCounter.append(HiroFriends.spanTimeLeft, HiroFriends.spanCounter)).appendTo("#user-interface");;
  59. spanRefresh.hover(function() { $(this).css("background-position", ""); }, function() { $(this).css("background-position", "0px -20px"); });
  60. spanRefresh.click(function() { HiroFriends.spanCounter.slideUp(500, function() { HiroFriends.fetch(); }).slideDown(1500); });
  61. imageSend.click(function() { HiroFriends.open(); });
  62. HiroFriends.updateTimer();
  63. if(typeof(Storage) !== "undefined") {
  64. var previousVersion = (localStorage.getItem(HiroFriends.storageItem) === null) ? 0 : parseFloat(localStorage.getItem(HiroFriends.storageItem));
  65. localStorage.setItem(HiroFriends.storageItem, HiroFriends.version);
  66. // 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();
  67. }
  68. $("<style>.hf_idx { width: 40px; 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");
  69. return true;
  70. }
  71. HiroFriends.fetch = function() {
  72. if (HiroFriends.interval !== false) clearInterval (HiroFriends.interval);
  73. var event_times = {};
  74. var friends = [], total = 0, avail = 0;
  75. var server_time = Game.getServerTime(), activation_time, friend_time;
  76. if (HiroFriends.timeLeft < 0) {
  77. $("#hiro_friends_container").slideUp(5000);
  78. throw "Event is over";
  79. }
  80. return $.post( "/game.php?window=friendsbar&mode=search", { search_type: "friends" } , function (data) {
  81. $.each(data.eventActivations, function (key, val) {
  82. if (val.event_name == HiroFriends.eventName) event_times[val.friend_id] = val.activation_time;
  83. });
  84. $.each(data.players, function (key, val) {
  85. if (val.name !== Character.name) {
  86. activation_time = (event_times[val.player_id] !== undefined) ? event_times[val.player_id]: 0;
  87. friend_time = activation_time + HiroFriends.eventInfo.cooldown - server_time;
  88. friends.push ({ id: val.player_id, name: val.name, time: friend_time });
  89. ++ total;
  90. if (friend_time <= 0) ++ avail;
  91. }
  92. });
  93. if (total) friends.sort(HiroFriends.timeCompare);
  94. HiroFriends.friends = friends;
  95. HiroFriends.avail = avail;
  96. HiroFriends.total = total;
  97. HiroFriends.interval = setInterval(function() { HiroFriends.fetch(); }, refreshMs);
  98. HiroFriends.update();
  99. });
  100. }
  101. HiroFriends.getLog = function() {
  102. var hasNext = true;
  103. var limit = 100;
  104. var page = 1;
  105. var count = 0;
  106. var details;
  107. var maxDate = HiroFriends.log.lastLog;
  108. while (hasNext) {
  109. $.ajax({ type: "POST", url: "/game.php?window=ses&mode=log", data: { ses_id: HiroFriends.eventName, page: page, limit: limit }, async: false, success: function(data) {
  110. hasNext = data.hasNext;
  111. limit = data.limit;
  112. page = data.page + 1;
  113. $.each(data.entries, function (key, val) {
  114. count = parseInt(val.value);
  115. if (val.date <= HiroFriends.log.lastLog) {
  116. hasNext = false;
  117. return false;
  118. }
  119. if (val.date > maxDate) maxDate = val.date;
  120. switch (val.type) {
  121. case "friendDrop":
  122. details = JSON.parse(val.details);
  123. if (undefined === HiroFriends.log.friendLog[details.player_id]) HiroFriends.log.friendLog[details.player_id] = count;
  124. else HiroFriends.log.friendLog[details.player_id] += count;
  125. HiroFriends.log.count_friends += count;
  126. HiroFriends.log.received += count;
  127. break;
  128. case "jobDrop": HiroFriends.log.count_job += count; HiroFriends.log.received += count; break;
  129. case "buildDrop": HiroFriends.log.count_build += count; HiroFriends.log.received += count; break;
  130. case "duelDrop": HiroFriends.log.count_duel += count; HiroFriends.log.received += count; break;
  131. case "duelNPCDrop": HiroFriends.log.count_npc += count; HiroFriends.log.received += count; break;
  132. case "battleDrop": HiroFriends.log.count_fort += count; HiroFriends.log.received += count; break;
  133. case "adventureDrop": HiroFriends.log.count_mpi += count; HiroFriends.log.received += count; break;
  134. case "wofPay":
  135. HiroFriends.log.used += count;
  136. if (val.details == "timerreset") {
  137. HiroFriends.log.count_reset += count;
  138. ++ HiroFriends.log.times_reset;
  139. }
  140. else if (val.details == "sneakyshot") {
  141. HiroFriends.log.count_bribe += count;
  142. ++ HiroFriends.log.times_bribe;
  143. }
  144. break;
  145. default:
  146. HiroFriends.log.count_other += count;
  147. HiroFriends.log.received += count;
  148. }
  149. });
  150. }});
  151. }
  152. HiroFriends.log.lastLog = maxDate;
  153. }
  154. HiroFriends.open = function() {
  155. if (!WestUi.FriendsBar.hidden) WestUi.FriendsBar.toggle();
  156. HiroFriends.getLog();
  157. return HiroFriends.fetch().done(function() {
  158. var maindiv = $('<div class="hiro_friends_maindiv"></div>');
  159. var 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", '<img src="'+HiroFriends.cdnBase+'/images/icons/user.png" alt="" />').appendToCell("head", "hf_action", HiroFriends.eventInfo.label).appendToCell("head","hf_log",'<img src="'+HiroFriends.cdnBase+'/images/icons/watch.png" alt="" />').appendToCell("head", "hf_delete", '&nbsp;');
  160. var idx = 1;
  161. $.each(HiroFriends.friends, function (key, val) {
  162. var rcv = 0, actionCell;
  163. rcv = (undefined === HiroFriends.log.friendLog[val.id]) ? 0 : HiroFriends.log.friendLog[val.id];
  164. if (val.time > HiroFriends.timeLeft) actionCell = '(Next Year)';
  165. else if (val.time > 0) actionCell = '('+val.time.formatDurationBuffWay()+')';
  166. else {
  167. actionCell = $('<a href="javascript:void();">'+HiroFriends.eventInfo.label+'</a>').click({ id: val.id, ev: HiroFriends.eventName }, function (e) {
  168. $(this).parent().parent().remove();
  169. Ajax.remoteCall("friendsbar", "event", { player_id: val.id, event: HiroFriends.eventName }, function (response) {
  170. if (response.error) return MessageError(response.msg).show();
  171. MessageSuccess(response.msg).show();
  172. if (HiroFriends.avail) -- HiroFriends.avail;
  173. HiroFriends.update();
  174. if (WestUi.FriendsBar.friendsBarUi !== null)
  175. WestUi.FriendsBar.friendsBarUi.friendsBar.eventActivations[val.id][HiroFriends.eventName] = response.activationTime;
  176. });
  177. });
  178. }
  179. hiroTable.appendRow(null, 'hiroFriendRow_'+val.id)
  180. .appendToCell(-1, "hf_idx", idx)
  181. .appendToCell(-1, "hf_player", '<a href="javascript:void(PlayerProfileWindow.open('+val.id+'));">' + val.name + '</a>')
  182. .appendToCell(-1, "hf_action", actionCell)
  183. .appendToCell(-1, "hf_log", rcv)
  184. .appendToCell(-1, "hf_delete", '<a href="javascript:void(FriendslistWindow.deleteFromFriendList('+val.id+'));"><img style="width:16px; height: 16px;" title="Remove Friend" src="'+HiroFriends.cdnBase+'/images/icons/delete.png" alt="delete" /></a>');
  185. ++ idx;
  186. });
  187. hiroTable.appendToCell('foot', 'hf_player', '<a target="_blank" href="'+installURL+'">TW Friends</a> version <b>' + HiroFriends.version.toFixed(2) + '</b>');
  188. var statsTable = $('<table style="margin: auto;"><tr style="vertical-align: top;"><td>Received:</td><td style="color: #006600; font-weight: bold; text-align: right; padding-right: 8pt;">'+HiroFriends.log.received+'</td><td>Friends: <b>'+HiroFriends.log.count_friends+'</b>, Jobs: <b>'+HiroFriends.log.count_job+'</b>, Fort Battles: <b>'+HiroFriends.log.count_fort+'</b>, Adventures: <b>'+HiroFriends.log.count_mpi+'</b>,<br />Duels: <b>'+HiroFriends.log.count_duel+'</b>, NPC Duels: <b>'+HiroFriends.log.count_npc+'</b>, Construction: <b>'+HiroFriends.log.count_build+'</b>, Other: <b>'+HiroFriends.log.count_other+'</b></td></tr><tr><td>Used:</td><td style="color: #660000; font-weight: bold; text-align: right; padding-right: 8pt;">'+HiroFriends.log.used+'</td><td>Reset Timer: <b>'+HiroFriends.log.count_reset+'</b> (#'+HiroFriends.log.times_reset+'), Bribe: <b>'+HiroFriends.log.count_bribe+'</b> (#'+HiroFriends.log.times_bribe+')</td></tr></table>');
  189. statsTable.appendTo(maindiv);
  190. var hiroWindow = wman.open("HiroFriends_"+HiroFriends.eventName, null, "noreload").setMiniTitle(HiroFriends.eventInfo.label).setTitle(HiroFriends.eventInfo.label);
  191. hiroWindow.appendToContentPane(maindiv);
  192. });
  193. }
  194. HiroFriends.timeCompare = function(a, b) {
  195. if (a.time < b.time) return -1;
  196. if (a.time > b.time) return 1;
  197. return 0;
  198. }
  199. HiroFriends.updateTimer = function() {
  200. HiroFriends.timeLeft = HiroFriends.eventEndStamp - Game.getServerTime();
  201. if (HiroFriends.timeLeft <= 0) {
  202. HiroFriends.spanTimeLeft.html('Finito');
  203. HiroFriends.fetch();
  204. return;
  205. }
  206. HiroFriends.spanTimeLeft.html(HiroFriends.timeLeft.formatDurationBuffWay());
  207. var seconds = 0;
  208. if (HiroFriends.timeLeft < 70) seconds = 1;
  209. else if (HiroFriends.timeLeft < 3660) seconds = 10;
  210. else if (HiroFriends.timeLeft < 86520) seconds = 60;
  211. else seconds = 120;
  212. setTimeout (function() { HiroFriends.updateTimer(); }, seconds * 1000);
  213. }
  214. HiroFriends.update = function() {
  215. HiroFriends.spanCounter.html(HiroFriends.avail+' <span style="color: #d3d3d3; font-size: 11px;">/ '+HiroFriends.total+'</span>');
  216. }
  217. HiroFriends.scriptInit = function(tries, maxTries) {
  218. if (tries >= maxTries) return false;
  219. if (Game && Game.loaded && undefined !== west.events && undefined != west.events.Manager) {
  220. var westEvents = west.events.Manager.getRunningEvents();
  221. var eventName;
  222. if ("object" == typeof westEvents) $.each (westEvents, function (key, val) {
  223. if (undefined !== val['id']) {
  224. eventName = val['id'];
  225. if ('SES Easter event' == eventName) eventName = 'Easter';
  226. else if ('SES: ' == eventName.substr(0,5)) eventName = eventName.substr(5);
  227. if ('Hearts' == eventName || 'Easter' == eventName || 'Independence' == eventName || 'DayOfDead' == eventName) {
  228. if (HiroFriends.init(eventName)) HiroFriends.fetch();
  229. return false;
  230. }
  231. }
  232. });
  233. return true;
  234. }
  235. ++ tries;
  236. setTimeout(function() { HiroFriends.scriptInit(tries, maxTries); }, tries * 1000);
  237. }
  238. HiroFriends.scriptInit(0, 100);
  239. });