Greasy Fork is available in English.

TW Friends

Gestion des Amis pour les Evénements de The West

Version au 2015-04-16 14:26:07 UTC. Voir la dernière version.

// ==UserScript==
// @name            TW Friends
// @name:el         TW Friends
// @name:es         TW Friends
// @name:fr         TW Friends
// @version         0.19
// @description     Friend Management for The West Events
// @description:el  Διαχείριση Φίλων για τις Εκδηλώσεις του The West
// @description:es  Gestión de Amigos para Eventos de The West
// @description:fr  Gestion des Amis pour les Evénements de The West
// @author          hiroaki
// @include         http://*.the-west.*/game.php*
// @include         https://*.the-west.*/game.php*
// @grant           none
// @namespace       https://greasyfork.org/users/3197
// ==/UserScript==

function hiroFriendsScript(fn) {
	var script = document.createElement('script');
	script.setAttribute("type", "application/javascript");
	script.textContent = '(' + fn + ')();';
	document.body.appendChild(script);
	document.body.removeChild(script);
}
hiroFriendsScript (function() {
	var VERSION = 0.19;
	var installURL = "https://greasyfork.org/scripts/2992-tw-friends";
	var scriptName = "TW Friends";
	var scriptAuthor = "hiroaki";
	var refreshMs = 2 * 60 * 1000;	// 2 minutes
	HiroFriends = {
		api: TheWestApi.register('HiroFriends', scriptName, '2.04', Game.version.toString(), scriptAuthor, installURL),
		version: VERSION,
		storageItem: "HiroFriends.version",
		cdnBase: '',
		eventName : '',
		eventInfo : {},
		eventEndStamp : 0,
		friends : [],
		interval: false,
		locale: 'en_US',
		messages: {
			el_GR: {
				description: '<h1>Διαχείριση Φίλων για τις Εκδηλώσεις του The West</h1><p style="margin: 8pt;">Μην κλικάρετε πολύ γρήγορα, για να αποφύγετε ένα σερί κακής τύχης :)</p><p style="margin: 8pt;">Υποστηριζόμενες Εκδηλώσεις:</p><ul style="list-style: disc outside; margin-left: 16pt; padding-left: 16pt;"><li>Άγιος Βαλεντίνος</li><li>Πάσχα</li><li>Ημέρα Ανεξαρτησίας</li><li>Ημέρα των Νεκρών</li></ul><p style="margin: 8pt;"><a target="_blank" href="http://forum.the-west.gr/showthread.php?t=8029">Συζήτηση στο Φόρουμ</a> | <a target="_blank" href="https://greasyfork.org/scripts/2992-tw-friends/feedback">Feedback</a>: Αναφορά Bugs, Ιδέες, Μεταφράσεις.</p><p style="margin: 8pt;"><b>Ευχαριστίες</b>: pepe100</p>',
				version: 'έκδοση',
				refresh: 'Ανανέωση',
				timeLeft: 'Χρόνος που υπολείπεται μέχρι το τέλος της εκδήλωσης',
				serverTime: 'ώρα διακομιστή',
				availFriends: 'Αριθμός Φιλων στους οποίους μπορείς να στείλεις τώρα',
				totalFriends: 'Αριθμός Φίλων',
				noFriends: 'Δεν έχεις φίλους',
				name: 'Όνομα',
				received: 'Έλαβες',
				removeFriend: 'Αφαίρεση φίλου',
				removeConfirm: 'Θέλεις πραγματικά να διαγράψεις αυτόν τον παίχτη από τη λίστα;',
				removeSuccess: 'Ο φίλος αφαιρέθηκε από τη λίστα.',
				removeFailed: 'Ο φίλος δεν μπόρεσε να αφαιρεθεί',
				exporter: 'Εξαγωγή',
				everything: 'Όλα',
				collected: 'Έχεις συλλέξει',
				friends: 'Φίλοι',
				jobs: 'Εργασίες',
				fortBattles: 'Μάχες Οχυρών',
				adventures: 'Περιπέτειες',
				duels: 'Μονομαχίες',
				npcDuels: 'Μονομαχίες με NPC',
				construction: 'Χτίσιμο',
				itemUse: 'Χρήση Αντικειμένων',
				other: 'Άλλα',
				used: 'Έχεις χρησιμοποιήσει',
				timerReset: 'Μηδενισμός χρονομέτρου',
				bribe: 'Δωροδοκίες',
				nextYear: 'Του χρόνου',
				theEnd: 'Τετέλεσται',
			},
			en_US: {
				description: '<h1>Friend Management for The West Events</h1><p style="margin: 8pt;">Don&#039;t click too fast, to avoid a streak of bad luck upon you :)</p><p style="margin: 8pt;">Supported Events:</p><ul style="list-style: disc outside; margin-left: 16pt; padding-left: 16pt;"><li>Valentine&#039;s Day</li><li>Easter</li><li>Independence Day</li><li>Day of the Dead</li></ul><p style="margin: 8pt;"><a target="_blank" href="https://greasyfork.org/scripts/2992-tw-friends/feedback">Feedback</a>: Bug Reports, Ideas, Translations (in English).</p><p style="margin: 8pt;"><b>Credits</b>: pepe100</p>',
				version: 'version',
				refresh: 'Refresh',
				timeLeft: 'Time Left until the event ends',
				serverTime: 'server time',
				availFriends: 'Number of Friends you can send now',
				totalFriends: 'Number of Friends',
				noFriends: 'No Friends',
				name: 'Name',
				received: 'Received',
				removeFriend: 'Remove friend',
				removeConfirm: 'Do you really want to delete this player from the list?',
				removeSuccess: 'Friend removed from your list.',
				removeFailed: 'Friend could not be removed',
				exporter: 'Export',
				everything: 'Everything',
				collected: 'Collected',
				friends: 'Friends',
				jobs: 'Jobs',
				fortBattles: 'Fort Battles',
				adventures: 'Adventures',
				duels: 'Duels',
				npcDuels: 'NPC Duels',
				construction: 'Construction',
				itemUse: 'Item Use',
				other: 'Other',
				used: 'Used',
				timerReset: 'Reset Timers',
				bribe: 'Bribe',
				nextYear: 'Next Year',
				theEnd: 'The End',
			},
			es_ES: {
				description: '<h1>Gestión de Amigos para Eventos de The West</h1><p style="margin: 8pt;">No haga clic demasiado rápido, para evitar una racha de mala suerte :)</p><p style="margin: 8pt;">Eventos soportados:</p><ul style="list-style: disc outside; margin-left: 16pt; padding-left: 16pt;"><li>Día de San Valentín</li><li>Pascua</li><li>Día de la Independencia</li><li>Día de los Muertos</li></ul><p style="margin: 8pt;"><a target="_blank" href="https://greasyfork.org/scripts/2992-tw-friends/feedback">Comentarios</a>: Bug Reports, Ideas, Translations (in English).</p><p style="margin: 8pt;"><b>Créditos</b>: pepe100</p>',
				version: 'versión',
				refresh: 'Actualizar',
				timeLeft: 'Tiempo que queda hasta el final del evento',
				serverTime: 'hora del servidor',
				availFriends: 'Número de Amigos que se puede enviar ahora',
				totalFriends: 'Número de Amigos',
				noFriends: 'Sin Amigos',
				name: 'Nombre',
				received: 'Recibidos',
				removeFriend: 'Remover amigo',
				removeConfirm: '¿Estas seguro que quieres eliminar a este jugador de tu lista?',
				removeSuccess: 'Amigo removido de tu lista',
				removeFailed: 'El amigo no ha podido ser eliminado',
				exporter: 'Exportar',
				everything: 'Todo',
				collected: 'Conseguidos',
				friends: 'Amigos',
				jobs: 'Trabajos',
				fortBattles: 'Batallas de fuertes',
				adventures: 'Aventuras',
				duels: 'Duelos',
				npcDuels: 'Duelos NPC',
				construction: 'Ampliación',
				itemUse: 'Objetos usados',
				other: 'Otros',
				used: 'Usados',
				timerReset: 'Reiniciar temporizadores',
				bribe: 'Soborno',
				nextYear: 'El próximo año',
				theEnd: 'Final',
			},
			fr_FR: {
				description: '<h1>Gestion des Amis pour les Evénements de The West</h1><p style="margin: 8pt;">Ne cliquez pas trop vite, pour éviter une série de malchance sur vous :)</p><p style="margin: 8pt;">Evénements:</p><ul style="list-style: disc outside; margin-left: 16pt; padding-left: 16pt;"><li> Saint Valentin</li><li>Pâques</li><li>Jour De L&#039;Indépendance</li><li>Jour des Morts</li></ul><p style="margin: 8pt;"><a target="_blank" href="https://greasyfork.org/scripts/2992-tw-friends/feedback">Commentaires</a>: Bug Reports, Ideas, Translations (in English).</p><p style="margin: 8pt;"><b>Credits</b>: pepe100</p>',
				version: 'version',
				refresh: 'Rafraîchir',
				timeLeft: "Temps restant jusqu'à la fin de l'événement",
				serverTime: 'horaire du serveur',
				availFriends: 'Nombre des amis que tu peux envoyer maintenant',
				totalFriends: 'Nombre des Amis',
				noFriends: "Pas d' Amis",
				name: 'Nom',
				received: 'Tu as reçu',
				removeFriend: "Supprimer l'ami(e)",
				removeConfirm: 'Veux-tu vraiment supprimer ce joueur de la liste?',
				removeSuccess: 'Ami supprimé de la liste',
				removeFailed: "L'ami n'a pas pu être supprimé",
				exporter: 'Exportation',
				everything: 'Tout',
				collected: 'Collectés',
				friends: 'Amis',
				jobs: 'Travaux',
				fortBattles: 'Batailles',
				adventures: 'Aventures',
				duels: 'Duels',
				npcDuels: 'Duels PNJ',
				construction: 'Agrandissement',
				itemUse: 'Objets utilisés',
				other: 'Autres',
				used: 'Utilisés',
				timerReset: 'Se battre en duel',
				bribe: 'Soudoyer',
				nextYear: "L'année prochaine",
				theEnd: 'La Fin',
			},
		},
		timeLeft : 0,
		total : 0,
		avail: 0,
		log: { lastLog: 0, friendLog: {}, entries: [], count_friends: 0, count_job: 0, count_duel: 0, count_npc: 0, count_fort: 0, count_mpi: 0, count_build: 0, count_item: 0, count_other: 0, count_reset: 0, count_bribe: 0, times_reset: 0, times_bribe: 0, received: 0, used: 0 },
		spanCounter: $("<span />", { id: "hiro_friends_counter", style: "position: absolute; right: 5px; color: #f8c57c; font-size: 13pt; height: 25px; line-height: 25px; bottom: 0px" }),
		spanTimeLeft: null
	};
	HiroFriends.init = function(eventName) {
		if (undefined === Game.sesData[eventName] || undefined === Game.sesData[eventName].friendsbar) return false;
		HiroFriends.eventName = eventName;
		HiroFriends.eventInfo = Game.sesData[eventName].friendsbar;
		if (undefined === Game.sesData[HiroFriends.eventName].meta.end) return false;
		HiroFriends.eventEndStamp = (buildTimestamp(Game.sesData[HiroFriends.eventName].meta.end) - Game.serverTimeDifference) / 1000;
		HiroFriends.timeLeft = HiroFriends.eventEndStamp - Game.getServerTime();
		if (HiroFriends.timeLeft < 0) return false;
		HiroFriends.cdnBase = (undefined === Game.cdnURL) ? "https://westzzs.innogamescdn.com" : Game.cdnURL;
		HiroFriends.getLog();
		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(buildTimestamp(Game.sesData[HiroFriends.eventName].meta.end)).toDateTimeStringNice()+' '+HiroFriends.localeMsg('serverTime')+')' });
		var eventImage = HiroFriends.cdnBase + "/images/interface/friendsbar/events/" + HiroFriends.eventName + ".png";	// event based
		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;" })
		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;" });
		var divRefresh = $("<div />", { style: "width: 24px; height: 24px; position: absolute; left: 8px; top: 3px; z-index: 3; padding: 4px 0px 0px 4px;" });
		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;" });
		var spanSend = $("<span />", { style: "width: 26px; height: 26px; left: auto; position: absolute; right: 7px; top: 2px; z-index: 3;" });
		var imageSend = $("<img />", { src: eventImage, title: HiroFriends.eventInfo.label, style: "width: 26px; height: 26px; cursor: pointer" });
		divContainer.append(divRefresh.append(spanRefresh), spanSend.append(imageSend), divCounter.append(HiroFriends.spanTimeLeft, HiroFriends.spanCounter)).appendTo("#user-interface");;
		spanRefresh.hover(function() { $(this).css("background-position", ""); }, function() { $(this).css("background-position", "0px -20px"); });
		spanRefresh.click(function() { HiroFriends.spanCounter.slideUp(500, function() { HiroFriends.fetch(); }).slideDown(1500); });
		imageSend.click(function() { HiroFriends.open(); });
		HiroFriends.updateTimer();
		if(typeof(Storage) !== "undefined") {
			var previousVersion = (localStorage.getItem(HiroFriends.storageItem) === null) ? 0 : parseFloat(localStorage.getItem(HiroFriends.storageItem));
			localStorage.setItem(HiroFriends.storageItem, HiroFriends.version);
			// 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();
		}
		$("<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");
		return true;
	};
	HiroFriends.localeMsg = function(msg) {
		if (HiroFriends.messages[HiroFriends.locale][msg]) return HiroFriends.messages[HiroFriends.locale][msg];
		if (HiroFriends.messages.en_US.msg) return HiroFriends.messages.en_US.msg;
		return '';
	}
	HiroFriends.fetch = function() {
		if (HiroFriends.interval !== false) clearInterval (HiroFriends.interval);
		var event_times = {};
		var friends = [], total = 0, avail = 0, recv = 0;
		var server_time = Game.getServerTime(), activation_time, friend_time;
		if (HiroFriends.timeLeft < 0) {
			$("#hiro_friends_container").slideUp(5000);
			throw "Event is over";
		}
		return $.post( "/game.php?window=friendsbar&mode=search", { search_type: "friends" } , function (data) {
			$.each(data.eventActivations, function (key, val) {
				if (val.event_name == HiroFriends.eventName) event_times[val.friend_id] = val.activation_time;
			});
			$.each(data.players, function (key, val) {
				if (val.name !== Character.name) {
					activation_time = (event_times[val.player_id] !== undefined) ? event_times[val.player_id]: 0;
					recv = (undefined === HiroFriends.log.friendLog[val.player_id]) ? 0 : HiroFriends.log.friendLog[val.player_id].total;
					friends.push ({ id: val.player_id, name: val.name, activation_time: activation_time, recv: recv });
					++ total;
					if (activation_time + HiroFriends.eventInfo.cooldown - server_time <= 0) ++ avail;
				}
			});
			HiroFriends.friends = friends;
			HiroFriends.avail = avail;
			HiroFriends.total = total;
			HiroFriends.interval = setInterval(function() { HiroFriends.fetch(); }, refreshMs);
			HiroFriends.update();
		});
	}
	HiroFriends.getLog = function() {
		var hasNext = true;
		var limit = 100;
		var page = 1;
		var count = 0;
		var details;
		var maxDate = HiroFriends.log.lastLog;
		while (hasNext) {
			$.ajax({ type: "POST", url: "/game.php?window=ses&mode=log", data: { ses_id: HiroFriends.eventName, page: page, limit: limit }, async: false, success: function(data) {
				hasNext = data.hasNext;
				limit = data.limit;
				page = data.page + 1;
				$.each(data.entries, function (key, val) {
					count = parseInt(val.value);
					if (val.date <= HiroFriends.log.lastLog) {
						hasNext = false;
						return false;
					}
					HiroFriends.log.entries.push(val);
					if (val.date > maxDate) maxDate = val.date;
					switch (val.type) {
						case "friendDrop":
							details = JSON.parse(val.details);
							if (undefined !== HiroFriends.friends[details.player_id]) HiroFriends.friends[details.player_id].recv += count;
							if (undefined === HiroFriends.log.friendLog[details.player_id]) HiroFriends.log.friendLog[details.player_id] = { name: details.name, total: count, dates: [] };
							else HiroFriends.log.friendLog[details.player_id].total += count;
							HiroFriends.log.friendLog[details.player_id].dates.push(val.date);
							HiroFriends.log.count_friends += count;
							HiroFriends.log.received += count;
							break;
						case "jobDrop":		HiroFriends.log.count_job += count; HiroFriends.log.received += count; break;
						case "buildDrop":	HiroFriends.log.count_build += count; HiroFriends.log.received += count; break;
						case "duelDrop":	HiroFriends.log.count_duel += count; HiroFriends.log.received += count; break;
						case "duelNPCDrop":	HiroFriends.log.count_npc += count; HiroFriends.log.received += count; break;
						case "battleDrop":	HiroFriends.log.count_fort += count; HiroFriends.log.received += count; break;
						case "adventureDrop":	HiroFriends.log.count_mpi += count; HiroFriends.log.received += count; break;
						case "itemUse":		HiroFriends.log.count_item += count; HiroFriends.log.received += count; break;
						case "wofPay":
							HiroFriends.log.used += count;
							if (val.details == "timerreset") {
								HiroFriends.log.count_reset += count;
								++ HiroFriends.log.times_reset;
							}
							else if (val.details == "sneakyshot") {
								HiroFriends.log.count_bribe += count;
								++ HiroFriends.log.times_bribe;
							}
							break;
						default:
							HiroFriends.log.count_other += count;
							HiroFriends.log.received += count;
					}
				});
			}});
		}
		HiroFriends.log.lastLog = maxDate;
		Chat.Request.Nop();
	}
	HiroFriends.display = function(sort) {
		var friend_time, server_time = Game.getServerTime();
		var maindiv = $('<div class="hiro_friends_maindiv" />');
		if (!HiroFriends.friends.length) $('<h1 style="text-align: center; color: #990000; margin-bottom: 80px;">'+HiroFriends.localeMsg('noFriends')+'</h1>').appendTo(maindiv);
		else {
			var hiroTable;
			switch (sort) {
				case "name" 	:	HiroFriends.friends.sort(HiroFriends.nameCompare); break;
				case "name_desc":	HiroFriends.friends.sort(HiroFriends.nameCompare).reverse(); break;
				case "recv" 	:	HiroFriends.friends.sort(HiroFriends.recvCompare); break;
				case "recv_asc"	:	HiroFriends.friends.sort(HiroFriends.recvCompare).reverse(); break;
				case "time_asc"	:	HiroFriends.friends.sort(HiroFriends.timeCompare).reverse(); break;
				case "time"	:
				default		:	sort = "time"; HiroFriends.friends.sort(HiroFriends.timeCompare);
			}
			var thName = $('<a href="javascript:void(0);"><img src="'+HiroFriends.cdnBase+'/images/icons/user.png" alt="" />&nbsp;'+HiroFriends.localeMsg('name')+'</a>').click(function (){ HiroFriends.display(sort == 'name' ? 'name_desc' : 'name'); });
			var thAction = $('<a href="javascript:void(0);"><img src="'+HiroFriends.cdnBase+'/images/icons/clock.png" alt="" />&nbsp;'+HiroFriends.eventInfo.label+'</a>').click(function (){ HiroFriends.display(sort == 'time' ? 'time_asc' : 'time'); });
			var thRecv = $('<a href="javascript:void(0);"><img src="'+HiroFriends.cdnBase+'/images/icons/watch.png" alt="" />&nbsp;'+HiroFriends.localeMsg('received')+'</a>').click(function (){ HiroFriends.display(sort == 'recv' ? 'recv_asc' : 'recv'); });
			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;');
			var idx = 1;
			$.each(HiroFriends.friends, function (key, val) {
				var actionCell, recvCell;
				friend_time = val.activation_time + HiroFriends.eventInfo.cooldown - server_time;
				if (friend_time > HiroFriends.timeLeft) actionCell = '('+HiroFriends.localeMsg('nextYear')+')';
				else if (friend_time > 0) actionCell = '('+friend_time.formatDurationBuffWay()+')';
				else {
					actionCell = $('<a href="javascript:void(0);">'+HiroFriends.eventInfo.label+'</a>').click({ id: val.id, ev: HiroFriends.eventName }, function (e) {
						$(this).parent().parent().remove();
						Ajax.remoteCall("friendsbar", "event", { player_id: val.id, event: HiroFriends.eventName }, function (response) {
							if (response.error) return MessageError(response.msg).show();
							MessageSuccess(response.msg).show();
							val.activation_time = Date.now()/1e3;
							if (HiroFriends.avail) -- HiroFriends.avail;
							HiroFriends.update();
							if (WestUi.FriendsBar.friendsBarUi !== null)
								WestUi.FriendsBar.friendsBarUi.friendsBar.eventActivations[val.id][HiroFriends.eventName] = response.activationTime;
						});
					});
				}
				if (val.recv) {
					var recv_list = '<ol style=&quot;list-style-type: decimal; padding: 0 0 0 20px;&quot;>';
					HiroFriends.log.friendLog[val.id].dates.sort(function(a, b){
						return new Date(a)-new Date(b);
					});
					$.each(HiroFriends.log.friendLog[val.id].dates, function (dkey, dval) {
						recv_list += '<li style=&quot;display: list-item; white-space: nowrap;&quot;>' + new Date(dval * 1000).toDateTimeStringNice() + '</li>';
					});
					recv_list += '<ol>';
					recvCell = '<span title="'+recv_list+'" style="cursor: help;">'+val.recv+'</span>';
				}
				else recvCell = val.recv;
				hiroTable.appendRow(null, 'hiroFriendRow_'+val.id)
					.appendToCell(-1, "hf_idx", idx)
					.appendToCell(-1, "hf_player", '<a href="javascript:void(PlayerProfileWindow.open('+val.id+'));">' + val.name + '</a>')
					.appendToCell(-1, "hf_action", actionCell)
					.appendToCell(-1, "hf_log", recvCell)
					.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>');
				++ idx;
			});
			hiroTable.appendToCell('foot', 'hf_idx', '<a target="_blank" href="'+installURL+'"><img src="'+HiroFriends.cdnBase+'/images/icons/link.png" alt=""></a>');
			hiroTable.appendToCell('foot', 'hf_player', '<a target="_blank" href="'+installURL+'">TW Friends</a> '+HiroFriends.localeMsg('version')+' ' + HiroFriends.version.toFixed(2));
			if ('http://gr1.the-west.gr' == Game.gameURL || 'http://gr4.the-west.gr' == Game.gameURL || 'http://gr5.the-west.gr' == Game.gameURL) hiroTable.appendToCell('foot', 'hf_action', 'by <a href="javascript:void(PlayerProfileWindow.open(92184));">'+scriptAuthor+'</a>');
			else if ('https://zz1.beta.the-west.net' == Game.gameURL) hiroTable.appendToCell('foot', 'hf_action', 'by <a href="javascript:void(PlayerProfileWindow.open(16866));">'+scriptAuthor+'</a>');
			hiroTable.appendToCell('foot', 'hf_log', $('<a href="javascript:void(0);">'+HiroFriends.localeMsg('exporter')+'</a>').click(function() {
				HiroFriends.log.entries.sort(function(a,b) { return a.date - b.date; });
				new west.gui.Dialog(HiroFriends.localeMsg('exporter'),'<b>'+HiroFriends.localeMsg('friends')+'</b>:<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();
			}) );
		}
		var statsTable = $('<table style="margin: auto; width: 90%;"><tr style="vertical-align: top;"><td style="white-space: nowrap;">'+HiroFriends.localeMsg('collected')+':</td><td style="color: #006600; font-weight: bold; text-align: right; padding-right: 8pt;">'+HiroFriends.log.received+'</td><td> <span style="white-space: nowrap;">'+HiroFriends.localeMsg('friends')+': <b>'+HiroFriends.log.count_friends+'</b>,</span> <span style="white-space: nowrap;">'+HiroFriends.localeMsg('jobs')+': <b>'+HiroFriends.log.count_job+'</b>,</span> <span style="white-space: nowrap;">'+HiroFriends.localeMsg('fortBattles')+': <b>'+HiroFriends.log.count_fort+'</b>,</span> <span style="white-space: nowrap;">'+HiroFriends.localeMsg('adventures')+': <b>'+HiroFriends.log.count_mpi+'</b>,</span> <span style="white-space: nowrap;">'+HiroFriends.localeMsg('duels')+': <b>'+HiroFriends.log.count_duel+'</b>,</span> <span style="white-space: nowrap;">'+HiroFriends.localeMsg('npcDuels')+': <b>'+HiroFriends.log.count_npc+'</b>,</span> <span style="white-space: nowrap;">'+HiroFriends.localeMsg('construction')+': <b>'+HiroFriends.log.count_build+'</b>,</span> <span style="white-space: nowrap;">'+HiroFriends.localeMsg('itemUse')+': <b>'+HiroFriends.log.count_item+'</b>,</span> <span style="white-space: nowrap;">'+HiroFriends.localeMsg('other')+': <b>'+HiroFriends.log.count_other+'</b></span></td></tr>'+(HiroFriends.log.used?'<tr style="vertical-align: top;"><td style="white-space: nowrap;">'+HiroFriends.localeMsg('used')+':</td><td style="color: #660000; font-weight: bold; text-align: right; padding-right: 8pt;">'+HiroFriends.log.used+'</td><td><span style="white-space: nowrap;">'+HiroFriends.localeMsg('timerReset')+': <b>'+HiroFriends.log.count_reset+'</b> (#'+HiroFriends.log.times_reset+'),</span> <span style="white-space: nowrap;">'+HiroFriends.localeMsg('bribe')+': <b>'+HiroFriends.log.count_bribe+'</b> (#'+HiroFriends.log.times_bribe+')</span></td></tr>' : '') + '</table>').appendTo(maindiv);
		var hiroPane = new west.gui.Scrollpane();
		hiroPane.appendContent(maindiv);
		var hiroWindow = wman.open("HiroFriends_"+HiroFriends.eventName, null, "noreload").setMiniTitle(HiroFriends.eventInfo.label).setTitle(HiroFriends.eventInfo.label).appendToContentPane(hiroPane.getMainDiv());
	}
	HiroFriends.open = function() {
		if (!WestUi.FriendsBar.hidden) WestUi.FriendsBar.toggle();
		HiroFriends.getLog();
		return HiroFriends.fetch().done(function() { HiroFriends.display('time'); });
	}
	HiroFriends.nameCompare = function(a, b) { return a.name.toLowerCase().localeCompare(b.name.toLowerCase()); }
	HiroFriends.recvCompare = function(a, b) { return b.recv - a.recv; }
	HiroFriends.timeCompare = function(a, b) { return a.activation_time - b.activation_time; }
	HiroFriends.updateTimer = function() {
		HiroFriends.timeLeft = HiroFriends.eventEndStamp - Game.getServerTime();
		if (HiroFriends.timeLeft <= 0) {
			HiroFriends.spanTimeLeft.html(HiroFriends.localeMsg('theEnd'));
			HiroFriends.fetch();
			return;
		}
		HiroFriends.spanTimeLeft.html(HiroFriends.timeLeft.formatDurationBuffWay());
		var seconds = 0;
		if (HiroFriends.timeLeft < 70) seconds = 1;
		else if (HiroFriends.timeLeft < 3660) seconds = 10;
		else if (HiroFriends.timeLeft < 86520) seconds = 60;
		else seconds = 120;
		setTimeout (function() { HiroFriends.updateTimer(); }, seconds * 1000);
	}
	HiroFriends.update = function() {
		HiroFriends.spanCounter.html('<span title="'+HiroFriends.localeMsg('availFriends')+'">'+HiroFriends.avail+'</span> <span style="color: #d3d3d3; font-size: 11px;" title="'+HiroFriends.localeMsg('totalFriends')+'">/ '+HiroFriends.total+'</span>');
	}
	HiroFriends.removeFriend = function(charId) {
		new west.gui.Dialog(HiroFriends.localeMsg('removeFriend'), HiroFriends.localeMsg('removeConfirm')).setIcon(west.gui.Dialog.SYS_QUESTION).addButton("yes",
			function() {
				Ajax.remoteCall('character', 'cancel_friendship', { friend_id: charId }, function(json) {
					if (json["result"]) {
						new UserMessage(HiroFriends.localeMsg('removeSuccess'), UserMessage.TYPE_SUCCESS).show();
						$("div.hiroFriendRow_" + charId).remove();
						$("div.friendData_" + charId, FriendslistWindow.DOM).remove();
						if (HiroFriends.avail) -- HiroFriends.avail;
						if (HiroFriends.total) -- HiroFriends.total;
						HiroFriends.update();
						Chat.Friendslist.removeFriend(charId);
					}
					else new UserMessage(HiroFriends.localeMsg('removeFailed'), UserMessage.TYPE_ERROR).show();
			});
		}).addButton("no").show();
	}
	HiroFriends.scriptInit = function(tries, maxTries) {
		var ev, eventName;
		if (tries >= maxTries) return false;
		if (Game && Game.loaded) {
			HiroFriends.locale = (undefined === Game.locale || undefined == HiroFriends.messages[Game.locale]) ? "en_US" : Game.locale;
			HiroFriends.api.setGui(HiroFriends.localeMsg('description'));
			for (eventName in Game.sesData) {
				if (!Game.sesData.hasOwnProperty(eventName)) continue;
				var ev = Game.sesData[eventName];
				if (!ev.friendsbar) continue;
				if ('Hearts' == eventName || 'Easter' == eventName || 'Independence' == eventName || 'DayOfDead' == eventName) {
					if (HiroFriends.init(eventName)) HiroFriends.fetch();
					return false;
				}
			}
			return true;
		}
		++ tries;
		setTimeout(function() { HiroFriends.scriptInit(tries, maxTries); }, tries * 1000);
	}
	HiroFriends.scriptInit(0, 100);
});