TW Friends

Friend Management for The West Events

当前为 2017-09-15 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name               TW Friends
// @name:el            TW Friends
// @name:es            TW Friends
// @name:fr            TW Friends
// @name:it            TW Friends
// @name:pl            TW Friends
// @name:pt-PT         TW Friends
// @name:tr            TW Friends
// @version            0.30
// @license            LGPLv3
// @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
// @description:it     Gestione amici per gli eventi The West
// @description:pl     Menadżer zarządzania Przyjaciółmi podczas eventów The West
// @description:pt-PT  Gestão de amigos para eventos no The West
// @description:tr     The West Etkinlikleri İçin Arkadaş Yöneticisi
// @author             hiroaki
// @translation        pepe100 (es_ES)
// @translation        Jackssson (it_IT)
// @translation        jccwest (pt_PT)
// @translation        Bartosz86 (pl_PL)
// @translation        Oğuzhan Ünal (tr_TR)
// @include            http*://*.the-west.*/game.php*
// @include            http*://*.tw.innogames.*/game.php*
// @grant              none
// @namespace          https://greasyfork.org/users/3197
// @icon               https://cdn.rawgit.com/TWFriends/scripts/master/friends.png
// ==/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.30;
	var URL_INSTALL = "https://greasyfork.org/scripts/2992-tw-friends";
	var URL_CODE = "https://greasyfork.org/scripts/2992-tw-friends/code/TW%20Friends.user.js";
	var URL_VERSION = "https://raw.githack.com/TWFriends/scripts/master/version.js";
	var scriptName = "TW Friends";
	var scriptAuthor = "hiroaki";
	var scriptCredits = '<span style="display: inline-block; vertical-align: middle;">Bartosz86 ??, Jackssson ??, jccwest ??, pepe100 ??, Oğuzhan Ünal ??,<br />noolas, Pnevma</span>';
	var refreshMs = 2 * 60 * 1e3;	// 2 minutes
	var refreshWof = 20 * 60 * 1e3;	// 20 minutes
	var enableLog = true;
	var enableInv = true;
	var enableVersionCheck = true;
	HiroFriends = {
		api: TheWestApi.register('HiroFriends', scriptName, '2.04', Game.version.toString(), scriptAuthor, URL_INSTALL),
		version: VERSION,
		latestVersion: undefined,
		storageItem: "HiroFriends.version",
		cdnBase: '',
		eventCurrencyImage : '',
		eventName : '',
		eventInfo : {},
		eventEndStamp : 0,
		friends : {},
		interval: false,
		locale: 'en_US',
		pendingInvitations: 0,
		wallet: 0,
		wofId: undefined,
		wofStatus: {},
		wofTimeout: undefined,
		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><li>Ημέρα των Νεκρών</li></ul><p style="margin: 8pt;"><a target="_blank" href="https://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>: '+scriptCredits+'</p>',
				version: 'έκδοση',
				version_checkFailed: 'Ο αυτόματος έλεγχος για ενημερώσεις απέτυχε',
				version_checkManual: 'Μη αυτόματος έλεγχος',
				version_ok: 'Έχεις ήδη την τελευταία έκδοση',
				version_upgrade: 'Μια νέα έκδοση είναι διαθέσιμη. Θες να την εγκαταστήσεις;',
				refresh: 'Ανανέωση',
				timeLeft: 'Χρόνος που υπολείπεται μέχρι το τέλος της εκδήλωσης',
				serverTime: 'ώρα διακομιστή',
				availFriends: 'Αριθμός Φιλων στους οποίους μπορείς να στείλεις τώρα',
				totalFriends: 'Αριθμός Φίλων',
				pendingInvitation: 'Μία εκκρεμής πρόσκληση',
				pendingInvitations: 'εκκρεμείς πρoσκλήσεις',
				noFriends: 'Δεν έχεις φίλους',
				name: 'Όνομα',
				received: 'Έλαβες',
				frequency: 'Συχνότητα',
				removeFriend: 'Αφαίρεση φίλου',
				removeConfirm: 'Θέλεις πραγματικά να διαγράψεις αυτόν τον παίχτη από τη λίστα;',
				removeSuccess: 'Ο φίλος αφαιρέθηκε από τη λίστα.',
				removeFailed: 'Ο φίλος δεν μπόρεσε να αφαιρεθεί',
				exporter: 'Εξαγωγή',
				everything: 'Όλα',
				stats: 'Στατιστικά',
				since: 'από',
				collected: 'Έχεις συλλέξει',
				friends: 'Φίλοι',
				jobs: 'Εργασίες',
				fortBattles: 'Μάχες Οχυρών',
				adventures: 'Περιπέτειες',
				duels: 'Μονομαχίες',
				npcDuels: 'Μονομαχίες με NPC',
				construction: 'Χτίσιμο',
				quests: 'Αποστολές',
				itemUse: 'Χρήση Αντικειμένων',
				other: 'Άλλα',
				used: 'Έχεις χρησιμοποιήσει',
				timerReset: 'Μηδενισμός χρονομέτρου',
				bribe: 'Δωροδοκίες',
				inventory: 'Αποθέματα',
				wofCat: [ 'Συνηθισμένα', 'Ασυνήθιστα', 'Σπάνια', 'Πολύ Σπάνια' ],
				wofState: {
					Octoberfest: [ 'Περιμένεις να σερβιριστεί το επόμενο πιάτο', 'Δεν διαθέτεις αρκετά πρέτσελ', 'Διαθέτεις αρκετά πρέτσελ για να φας', 'Διαθέτεις αρκετά πρέτσελ για να φας και να δωροδοκήσεις!' ]
				},
				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>Oktoberfest</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>: '+scriptCredits+'</p>',
				version: 'version',
				version_checkFailed: 'Unable to check for updates',
				version_checkManual: 'Check manually',
				version_ok: 'You already have the latest version',
				version_upgrade: 'A new version is available. Do you want to upgrade now?',
				refresh: 'Refresh',
				timeLeft: 'Time Left until the event ends',
				serverTime: 'server time',
				availFriends: 'Number of Friends you can send now',
				totalFriends: 'Number of Friends',
				pendingInvitation: 'One pending invitation',
				pendingInvitations: 'pending invitations',
				noFriends: 'No Friends',
				name: 'Name',
				received: 'Received',
				frequency: 'Frequency',
				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',
				stats: 'Stats',
				since: 'since',
				collected: 'Collected',
				friends: 'Friends',
				jobs: 'Jobs',
				fortBattles: 'Fort Battles',
				adventures: 'Adventures',
				duels: 'Duels',
				npcDuels: 'NPC Duels',
				construction: 'Construction',
				quests: 'Quests',
				itemUse: 'Item Use',
				other: 'Other',
				used: 'Used',
				timerReset: 'Reset Timers',
				bribe: 'Bribe',
				gameAction: 'Event game action',
				inventory: 'Inventory',
				wofCat: [ 'Common', 'Uncommon', 'Rare', 'Very Rare' ],
				wofState: {
					Octoberfest: [ 'Waiting for the next dish to be served', 'Not enough pretzels to pay for a serving', 'Enough pretzels to pay for a serving', 'Enough pretzels to pay for a serving and bribe the waiting staff' ]
				},
				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>Oktoberfest</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>: '+scriptCredits+'</p>',
				version: 'versión',
				version_checkFailed: 'No se puede comprobar actualizaciones',
				version_checkManual: 'Compruebe manualmente',
				version_ok: 'Ya tienes la última versión',
				version_upgrade: 'Una nueva versión está disponible. ¿Quieres instalarla ahora?',
				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',
				pendingInvitation: 'Una invitación pendiente',
				pendingInvitations: 'invitaciones pendientes',
				noFriends: 'Sin Amigos',
				name: 'Nombre',
				received: 'Recibidos',
				frequency: 'Frecuencia',
				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',
				stats: 'Estadísticas',
				since: 'desde',
				collected: 'Conseguidos',
				friends: 'Amigos',
				jobs: 'Trabajos',
				fortBattles: 'Batallas de fuertes',
				adventures: 'Aventuras',
				duels: 'Duelos',
				npcDuels: 'Duelos NPC',
				construction: 'Ampliación',
				quests: 'Busquedas',
				itemUse: 'Objetos usados',
				other: 'Otros',
				used: 'Usados',
				timerReset: 'Reiniciar temporizadores',
				bribe: 'Soborno',
				inventory: 'Inventario',
				wofCat: [ 'Común', 'No común', 'Raro', 'Muy raro' ],
				wofState: {
					Octoberfest: [ 'Esperando para ser servido', 'No tienes suficientes pretzels', 'Tienes suficientes pretzels para pagar', 'Tienes suficientes pretzels para pagar y sobornar' ]
				},
				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>Oktoberfest</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>: '+scriptCredits+'</p>',
				version: 'version',
				version_checkFailed: 'Impossible de vérifier les mises à jour',
				version_checkManual: 'Vérifier manuellement',
				version_ok: 'Tu as déjà la dernière version',
				version_upgrade: 'Une nouvelle version est disponible. Installer maintenant?',
				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',
				pendingInvitation: 'Une invitation en attente',
				pendingInvitations: 'invitations en attentes',
				noFriends: "Pas d'Amis",
				name: 'Nom',
				received: 'Tu as reçu',
				frequency: 'Fréquence',
				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',
				stats: 'Statistiques',
				since: 'à partir de',
				collected: 'Collectés',
				friends: 'Amis',
				jobs: 'Travaux',
				fortBattles: 'Batailles',
				adventures: 'Aventures',
				duels: 'Duels',
				npcDuels: 'Duels PNJ',
				construction: 'Agrandissement',
				quests: 'Quêtes',
				itemUse: 'Objets utilisés',
				other: 'Autres',
				used: 'Utilisés',
				timerReset: 'Se battre en duel',
				bribe: 'Soudoyer',
				inventory: 'Inventaire',
				wofCat: [ 'Commun', 'Non commun', 'Rare', 'Très rare' ],
				wofState: {
					Octoberfest: [ "En attendant d'être servi", "Tu n'as pas assez de Bretzels", 'Tu as assez de Bretzels pour payer', 'Tu as assez de Bretzels pour payer et soudoyer' ]
				},
				nextYear: "L'année prochaine",
				theEnd: 'La Fin',
			},
			it_IT: {
				description: '<h1>Gestione amici per gli eventi The West</h1><p style="margin: 8pt;">Non clickare tropo veloce, per non essere bloccato :)</p><p style="margin: 8pt;">Eventi supportati:</p><ul style="list-style: disc outside; margin-left: 16pt; padding-left: 16pt;"><li>Giorno San Valentino</li><li>Pasqua</li><li>Giorno dell&#039;Independenza</li><li>Oktoberfest</li><li>Il giorno dei morti</li></ul><p style="margin: 8pt;"><a target="_blank" href="https://greasyfork.org/scripts/2992-tw-friends/feedback">Feedback</a>: Bug Report, Ideee, Traduzioni (in English).</p><p style="margin: 8pt;"><b>Credits</b>: '+scriptCredits+'</p>',
				version: 'versione',
				version_checkFailed: 'Impossibile verificare gli aggiornamenti',
				version_checkManual: 'Controllare manualmente',
				version_ok: "Hai già l'ultima versione",
				version_upgrade: 'Nuova versione disponibile. Vuoi aggiornare adesso?',
				refresh: 'Aggiorna',
				timeLeft: 'Tempo rimanente fino alla fine dell&#039;evento',
				serverTime: 'server time',
				availFriends: 'Totale amici che puoi inviare adesso',
				totalFriends: 'Amici totale',
				pendingInvitation: 'Invito in attesa',
				pendingInvitations: 'inviti in attesa',
				noFriends: 'Non ci sono amici',
				name: 'Nome',
				received: 'Ricevuti',
				frequency: 'Freqvenza',
				removeFriend: 'Rimuovi amico',
				removeConfirm: 'Sei sicuro di voler cancellare l&#039;amico dalla lista?',
				removeSuccess: 'Amico rimosso dalla tua lista.',
				removeFailed: 'Impossibile rimuovere l&#039;amico',
				exporter: 'Esporta',
				everything: 'Tutto',
				stats: 'Statistiche',
				since: 'dal',
				collected: 'Collezionate',
				friends: 'Amici',
				jobs: 'Lavori',
				fortBattles: 'Battaglie forti',
				adventures: 'Avventure',
				duels: 'Duelli',
				npcDuels: 'Duelli con NPC',
				construction: 'Costruzione',
				quests: 'Missioni',
				itemUse: 'Oggetti usati',
				other: 'Altro',
				used: 'Usato',
				timerReset: 'Reseta Timer',
				bribe: 'Corruzione',
				gameAction: 'Event game action',
				inventory: 'Inventario',
				wofCat: [ 'Molto comune', 'Comune', 'Raro', 'Molto raro' ],
				wofState: {
					Octoberfest: [ 'In attesa di essere servita', 'Non hai abbastanza pretzel', 'Hai abbastanza pretzel per pagare', 'Hai abbastanza pretzel per pagare e corrompere' ]
				},
				nextYear: 'Anno prossimo',
				theEnd: 'Fine',
			},
			pl_PL: {
				description: '<h1>Menadżer zarządzania Przyjaciółmi podczas eventów The West</h1><p style="margin: 8pt;">Nie klikaj zbyt szybko, bo to będzie bardzo niemiłe dla Ciebie :)</p><p style="margin: 8pt;">Obsługiwane Eventy:</p><ul style="list-style: disc outside; margin-left: 16pt; padding-left: 16pt;"><li>Walentynki</li><li>Wielkanoc</li><li>Dzień Niepodległości</li><li>Oktoberfest</li><li>Dia de los Muertos</li></ul><p style="margin: 8pt;"><a target="_blank" href="https://forum.the-west.pl/showthread.php?t=60424">Forum</a> | <a target="_blank" href="https://greasyfork.org/scripts/2992-tw-friends/feedback">Opinie</a>: Zgłaszanie błędów, pomysłów, propozycji zmian (w języku angielskim).</p><p style="margin: 8pt;"><b>Uznanie dla</b>: '+scriptCredits+'</p>',
				version: 'wersja',
				version_checkFailed: 'Nie można sprawdzić aktualizacji',
				version_checkManual: 'Sprawdź ręcznie',
				version_ok: 'Masz już najnowszą wersję',
				version_upgrade: 'Dostępna jest nowa wersja. Czy chcesz dokonać aktualizacji?',
				refresh: 'Odśwież',
				timeLeft: 'Czas pozostały do zakończenia eventu',
				serverTime: 'czasu serwera',
				availFriends: 'Liczba przyjaciół do których można wysłać prezent',
				totalFriends: 'Łączna liczba przyjaciół',
				pendingInvitation: 'jedno oczekujące zaproszenie',
				pendingInvitations: 'oczekujących zaproszeń',
				noFriends: 'Brak przyjaciół',
				name: 'Nazwa gracza',
				received: 'Otrzymano',
				frequency: 'Częstotliwość',
				removeFriend: 'Usuń przyjaciela',
				removeConfirm: 'Czy na pewno chcesz usunąć tego gracza z listy przyjaciół?',
				removeSuccess: 'Przyjaciel usunięty z Twojej listy.',
				removeFailed: 'Nie można usunąć przyjaciela',
				exporter: 'Eksport',
				everything: 'Wszystko',
				stats: 'Statystyka',
				since: 'od',
				collected: 'Uzbierano',
				friends: 'Znajomi',
				jobs: 'Prace',
				fortBattles: 'Bitwy fortowe',
				adventures: 'Przygody',
				duels: 'Pojedynki',
				npcDuels: 'Pojedynki z NPC',
				construction: 'Rozbudowa',
				quests: 'Zadania',
				itemUse: 'Użycie przedmiotów',
				other: 'Inne',
				used: 'Użyto',
				timerReset: 'Zresetuj liczniki',
				bribe: 'Przekup',
				gameAction: 'Akcje podczas eventu',
				inventory: 'Ekwipunek',
				wofCat: [ 'Bardzo powszechny', 'Powszechny', 'Rzadki', 'Bardzo rzadki' ],
				nextYear: 'W przyszłym roku',
				theEnd: 'Koniec',
			},
			pt_PT: {
				description: '<h1>Gestão de amigos para eventos no The West</h1><p style="margin: 8pt;">não clique rápido demais, para evitar uma maré de azar :)</p><p style="margin: 8pt;">Eventos suportados:</p><ul style="list-style: disc outside; margin-left: 16pt; padding-left: 16pt;"><li>Dia dos namorados</li><li>Páscoa</li><li>Dia da independência</li><li>Oktoberfest</li><li>Dia de los Muertos</li></ul><p style="margin: 8pt;"><a target="_blank" href="https://greasyfork.org/scripts/2992-tw-friends/feedback">Comentários</a>: Bug Reports, Ideas, Translations (in English).</p><p style="margin: 8pt;"><b>Créditos</b>: '+scriptCredits+'</p>',
				version: 'versão',
				version_checkFailed: 'Não é possível verificar atualizações',
				version_checkManual: 'Verifique manualmente',
				version_ok: 'Você já possui a versão mais recente',
				version_upgrade: 'A nova versão está disponível. Atualize agora?',
				refresh: 'Actualizar',
				timeLeft: 'Tempo restante até ao final do evento',
				serverTime: 'hora do servidor',
				availFriends: 'Número de amigos a quem pode enviar agora',
				totalFriends: 'Número de Amigos',
				pendingInvitation: 'Um convite pendente',
				pendingInvitations: 'convites pendentes',
				noFriends: 'Sem Amigos',
				name: 'Nome',
				received: 'Recebidos',
				frequency: 'Freqüência',
				removeFriend: 'Remover amigo',
				removeConfirm: 'Queres mesmo remover amigo da lista ?',
				removeSuccess: 'Amigo removido da lista',
				removeFailed: 'Amigo não pode ser removido',
				exporter: 'Exportar',
				everything: 'Tudo',
				stats: 'Estatísticas',
				since: 'desde',
				collected: 'Recolhidos',
				friends: 'Amigos',
				jobs: 'Trabalhos',
				fortBattles: 'Batalhas de Forte',
				adventures: 'Aventuras MPI',
				duels: 'Duelos',
				npcDuels: 'Duelos NPC',
				construction: 'Construção',
				quests: 'Aventuras',
				itemUse: 'Itens usados',
				other: 'Outros',
				used: 'Usados',
				timerReset: 'Reiniciar temporizadores',
				bribe: 'Suborno',
				inventory: 'Inventário',
				wofCat: [ 'Comum', 'Fora do Comum', 'Raro', 'Muito Raro' ],
				nextYear: 'Próximo Ano',
				theEnd: 'Final',
			},
			tr_TR: {
				description: '<h1>The West Etkinlikleri İçin Arkadaş Yöneticisi</h1><p style="margin: 8pt;">Üzerinde kara bulutların dolaşmasını istemiyorsan çok hızlı tıklama :)</p><p style="margin: 8pt;">Desteklenen Etkinlikler:</p><ul style="list-style: disc outside; margin-left: 16pt; padding-left: 16pt;"><li>Sevgililer Günü</li><li>Paskalya</li><li>Bağımsızlık Günü</li><li>Ekim Festivali</li><li>Ölülerin Günü</li></ul><p style="margin: 8pt;"><a target="_blank" href="https://greasyfork.org/scripts/2992-tw-friends/feedback">Geri Bildirim</a>: Açık Raporları, Fikirler, Çeviriler (İngilizce).</p><p style="margin: 8pt;"><b>Yapımcılar</b>: '+scriptCredits+'</p>',
				version: 'versiyon',
				version_upgrade: 'Yeni versiyon mevcut. Şimdi yükseltmek istiyor musun?',
				refresh: 'Yenile',
				timeLeft: 'Etkinliğin bitmesine kalan süre',
				serverTime: 'sunucu süresi',
				availFriends: 'Şimdi gönderebileceğin arkadaş sayısı',
				totalFriends: 'Arkadaş Sayısı',
				pendingInvitation: 'Bir davetiye bekliyor',
				pendingInvitations: 'bekleyen davetiyeler',
				noFriends: 'Arkadaş Yok',
				name: 'İsim',
				received: 'Alınan',
				frequency: 'Sıklık',
				removeFriend: 'Arkadaşı Sil',
				removeConfirm: 'Bu oyuncuyu gerçekten listeden silmek istiyor musun?',
				removeSuccess: 'Arkadaşın listeden silindi.',
				removeFailed: 'Arkadaş silinemedi',
				exporter: 'Çıkar',
				everything: 'Her şey',
				stats: 'İstatistikler',
				since: 'başlangıç',
				collected: 'Toplanan',
				friends: 'Arkadaşlar',
				jobs: 'Çalışmalar',
				fortBattles: 'Kale Savaşları',
				adventures: 'Maceralar',
				duels: 'Düellolar',
				npcDuels: 'Haydut Düelloları',
				construction: 'Kurma',
				quests: 'Görevler',
				itemUse: 'Kullanılan Ürünler',
				other: 'Diğer',
				used: 'Kullanılan',
				timerReset: 'Zamanlayıcıyı Sıfırla',
				bribe: 'Rüşvet',
				gameAction: 'Etkinlik oyunu eylemi',
				inventory: 'Envanter',
				wofCat: [ 'Sıradan', 'Sıradan olmayan', 'Nadir', 'Çok nadir' ],
				nextYear: 'Gelecek Yıl',
				theEnd: 'Son',
			},
		},
		timeLeft : 0,
		total : 0,
		avail: 0,
		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 },
		spanCounter: $("<span />", { id: "hiro_friends_counter", style: "position: absolute; right: 5px; color: #f8c57c; font-size: 13pt; height: 25px; line-height: 25px; bottom: 0px" }),
		spanInvitations: null,
		divTombola: null,
		divFriendsAvail: null,
		imgFriendsAvail: null,
		/* Inno buildDateObject() function currently buggy */
		buildDateObject: function(timeStr, isServerTime) {
			var regEx, match, d = new Date(0), today = new Date();
			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|\*))?)?$/;
			if(match = timeStr.match(regEx)) {
				d.setFullYear(match[3] !== undefined ? (match[3] == '*' ? today.getFullYear() : parseInt(match[3], 10)) : today.getFullYear());
				d.setMonth(match[2] !== undefined ? (match[2] == '*' ? today.getMonth() : parseInt(match[2], 10) - 1) : today.getMonth());
				d.setDate(match[1] !== undefined ? (match[1] == '*' ? today.getDate() : parseInt(match[1], 10)) : today.getDate());
				d.setHours(match[4] !== undefined ? (match[4] == '*' ? today.getHours() : match[4]) : 0);
				d.setMinutes(match[5] !== undefined ? (match[5] == '*' ? today.getMinutes() : match[5]) : 0);
				d.setSeconds(match[6] !== undefined ? (match[6] == '*' ? today.getSeconds() : match[6]) : 0);
				d.setMilliseconds(0);
			}
			if(isServerTime) d = new Date(d - Game.serverTimeDifference);
			return d;
		},
		buildTimeStamp: function (timeStr, isServerTime) {
			return this.buildDateObject(timeStr, isServerTime).getTime();
		},
		items: {
			Hearts: {
				2557000 : 1250,		/* Small Heart Bag - 1250 hearts */
				2558000 : 2500,		/* Large Heart Bag - 2500 hearts */
				2561000 : 100,		/* Love Apple - 100 hearts */
				2562000 : 500,		/* Sugar hearts - 500 hearts */
				2563000 : 650,		/* 650 hearts */
				2564000 : 1500,		/* 1500 hearts */
				2565000 : 3250,		/* 3250 hearts */
				2566000 : 9000,		/* 9000 hearts */
				2567000 : 16000,	/* 16000 hearts */
			},
			Easter: {
				2698000 : 2500,		/* Efficient Easter egg container - 2500 eggs */
				2590000 : 650,		/* 650 Eggs */
				2591000 : 1500,		/* 1500 Eggs */
				2592000 : 3250,		/* 3250 Eggs */
				2593000 : 9000,		/* 9000 Eggs */
				2594000 : 16000,	/* 16000 Eggs */
			},
			Independence: {
				2619000 : 650,
				2620000 : 1500,
				2621000 : 3250,
				2622000 : 9000,
				2623000 : 16000,
			},
			Octoberfest: {
				50691000 : 2500,	/* Bag of Pretzels */
				371000 : 650,
				973000 : 1500,
				974000 : 3250,
				975000 : 9000,
				976000 : 16000,
			},
			DayOfDead: {
				2665000 : 1250,		/* Flower pot - 1250 Cempasúchil flowers */
				2666000 : 2500,		/* Big Flower pot - 2500 Cempasúchil flowers */
				2675000 : 25,		/* Cempasúchil Case - 25 Cempasúchil flowers */
				2676000 : 650,
				2677000 : 1500,
				2678000 : 3250,
				2679000 : 9000,
				2680000 : 16000,
			}
		},
		eventItems: {
			divInventory: null,
			imgInventory: null,
			imgTitle: '',
			Inventory: [],
			Available: [],
			total: 0,
			coolDownComplete: false,
			check: function () {
				HiroFriends.eventItems.Inventory = [];
				HiroFriends.eventItems.Available = [];
				HiroFriends.eventItems.total = 0;
				HiroFriends.eventItems.coolDownComplete = false;
				if(undefined === HiroFriends.items[HiroFriends.eventName]) return false;
				var now = new ServerDate().getTime()/1e3, coolDown, invItem;
				$.each(HiroFriends.items[HiroFriends.eventName], function(itemId, amount) {
					invItem = Bag.getItemByItemId(itemId);
					if(invItem) {
						HiroFriends.eventItems.Inventory.push(invItem);
						coolDown = Bag.itemCooldown[itemId];
						if(!coolDown) {
							HiroFriends.eventItems.Available.push(invItem);
							HiroFriends.eventItems.total += invItem.count*amount;
						}
						else if(coolDown <= now) {
							HiroFriends.eventItems.coolDownComplete = true;
							HiroFriends.eventItems.Available.push(invItem);
							HiroFriends.eventItems.total += amount;
						}
					}
				});
				HiroFriends.eventItems.imgInventory.attr('src', HiroFriends.eventItems.coolDownComplete ? HiroFriends.cdnBase+'/images/icons/clock.png' : HiroFriends.eventCurrencyImage);
				HiroFriends.eventItems.imgInventory.attr('title', HiroFriends.eventItems.total ? HiroFriends.eventItems.total+' <img src="' + HiroFriends.eventCurrencyImage + '" alt="">' : '');
				return true;
			},
			display: function() {
				HiroFriends.eventItems.check();
				if(HiroFriends.eventItems.Inventory.length > 0) {
					if(!Bag.loaded) {
						EventHandler.listen('inventory_loaded', function () {
							Wear.open();
							Inventory.showSearchResult(HiroFriends.eventItems.Inventory);
							return EventHandler.ONE_TIME_EVENT;
						});
						Bag.loadItems();
					}
					else {
						Wear.open();
						Inventory.showSearchResult(HiroFriends.eventItems.Inventory);
					}
				}
				HiroFriends.eventItems.divInventory.hide();
			},
		},
		signalHandlers: function() {
			var signal = Game.sesData[HiroFriends.eventName].counter.key;
			EventHandler.listen(signal, function(data) {
				if (HiroFriends.wofId) {
					var newAmount = parseInt(data);
					if (newAmount < HiroFriends.wallet) HiroFriends.getWofStatus();
					else if (newAmount > HiroFriends.wallet) {
						HiroFriends.wallet = newAmount;
						HiroFriends.divTombola.fadeOut(400, function() { HiroFriends.displayWofStatus(); }).fadeIn(400);
					}
				}
			});
			if(enableInv) {
				EventHandler.listen(['inventory_changed', 'cooldown_changed'], function() {
					if(HiroFriends.eventItems.check() && HiroFriends.eventItems.Available.length > 0)
						HiroFriends.eventItems.divInventory.show(5000);
					else HiroFriends.eventItems.divInventory.hide();
				});
			}
		},
		display: function(sort) {
			var friend_time, server_time = Game.getServerTime();
			var maindiv = $('<div class="hiro_friends_maindiv" />');
			var friends = [];
			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 });
			if(!friends.length) $('<h1 style="text-align: center; color: #990000; margin-bottom: 80px;">'+this.localeMsg('noFriends')+'</h1>').appendTo(maindiv);
			else {
				var hiroTable;
				switch(sort) {
					case "name" 	:	friends.sort(this.sortByName); break;
					case "name_desc":	friends.sort(this.sortByName).reverse(); break;
					case "recv" 	:	friends.sort(this.sortByRecv); break;
					case "recv_asc"	:	friends.sort(this.sortByRecv).reverse(); break;
					case "time_asc"	:	friends.sort(this.sortByTime).reverse(); break;
					case "time"	:
					default		:	sort = "time"; friends.sort(this.sortByTime);
				}
				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; });
				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; });
				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; }) : '';
				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;
				var now = Date.now()/1e3;
				$.each(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 style="cursor: pointer;">'+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();
								HiroFriends.friends[val.id].activation_time = Date.now()/1e3;
								if(HiroFriends.avail) -- HiroFriends.avail;
								HiroFriends.updateCounter();
								if(WestUi.FriendsBar.friendsBarUi !== null)
									WestUi.FriendsBar.friendsBarUi.friendsBar.eventActivations[val.id][HiroFriends.eventName] = response.activationTime;
							});
							return false;
						});
					}
					recvCell = '';
					if(enableLog) {
						if(val.recv) {
							var recv_list = '';
							HiroFriends.log.friendLog[val.id].dates.sort(function(a, b){ return new Date(a)-new Date(b); });
							if(HiroFriends.log.friendLog[val.id].total && HiroFriends.log.friendLog[val.id].dates.length > 1) {
								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>';
							}
							recv_list += '<ol style=&quot;list-style-type: decimal; padding: 0 0 0 20px;&quot;>';
							$.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 * 1e3).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="'+URL_INSTALL+'"><img src="'+this.cdnBase+'/images/icons/link.png" alt=""></a>');
				hiroTable.appendToCell('foot', 'hf_player', '<a target="_blank" href="'+URL_INSTALL+'">'+scriptName+'</a> '+this.localeMsg('version')+' ' + this.version.toFixed(2));
				if('https://gr1.the-west.gr' == Game.gameURL || 'https://gr4.the-west.gr' == Game.gameURL || 'https://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>');
				else hiroTable.appendToCell('foot', 'hf_action', 'by '+scriptAuthor);
				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>');
				if(enableLog) hiroTable.appendToCell('foot', 'hf_log', $('<a style="cursor: pointer;">'+HiroFriends.localeMsg('exporter')+'</a>').click(function() {
					HiroFriends.log.entries.sort(function(a,b) { return a.date - b.date; });
					var tsv_friends = "id\t"+HiroFriends.localeMsg('name')+"\t"+HiroFriends.localeMsg('received')+"\r\n";
					$.each(HiroFriends.log.friendLog, function(key,val) { tsv_friends += key+"\t"+val.name+"\t"+val.total+"\r\n"; });
					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();
					return false;
				}) );
			}
			if(enableLog || this.eventItems.total) {
				var statsTable = '<table style="margin: auto; width: 96%;">';
				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>' : '');
				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>';
				statsTable += '</table>';
				$(statsTable).appendTo(maindiv);
			}
			var hiroPane = new west.gui.Scrollpane();
			hiroPane.appendContent(maindiv);
			var hiroWindow = wman.open("HiroFriends_"+this.eventName, null, "noreload").setMiniTitle(this.eventInfo.label).setTitle(this.eventInfo.label).appendToContentPane(hiroPane.getMainDiv());
		},
		eventManager: function(eventName) {
			if(undefined === Game.sesData[eventName] || undefined === Game.sesData[eventName].friendsbar) return false;
			this.eventName = eventName;
			this.eventInfo = Game.sesData[eventName].friendsbar;
			if(undefined === Game.sesData[this.eventName].meta.end) return false;
			this.eventEndStamp = (this.buildTimeStamp(Game.sesData[this.eventName].meta.end) - Game.serverTimeDifference) / 1e3;
			this.timeLeft = this.eventEndStamp - Game.getServerTime();
			if(this.timeLeft < 0) return false;
			this.cdnBase = (undefined === Game.cdnURL) ? "https://westzzs.innogamescdn.com" : Game.cdnURL;
			$.when(this.getLog()).done(function() {
				try { HiroFriends.wofId = west.wof.WofManager.wofs.octoberwof.getId(); } catch(e) { }
				HiroFriends.design();
			});
		},
		design: function() {
			if ('Octoberfest' == this.eventName) {
				this.divTombola = $("<div />", { id: "hiro_wof_container", style: "position: absolute; left: 2px; top: 4px; height: 16px;" });
				$("<div />", { id: "hiro_wof_1", class: "hasMousePopup", style: "display: inline-block; width: 13px; height: 16px; background: url('"+HiroFriends.cdnBase+"/images/tw2gui/iconset.png?14') no-repeat -64px -80px; opacity: 0.5;" }).appendTo(HiroFriends.divTombola);
				$("<div />", { id: "hiro_wof_2", class: "hasMousePopup", style: "display: inline-block; width: 13px; height: 16px;" }).appendTo(HiroFriends.divTombola);
				$("<div />", { id: "hiro_wof_3", class: "hasMousePopup", style: "display: inline-block; width: 13px; height: 16px;" }).appendTo(HiroFriends.divTombola);
				$("<div />", { id: "hiro_wof_4", class: "hasMousePopup", style: "display: inline-block; width: 13px; height: 16px;" }).appendTo(HiroFriends.divTombola);
			}
			else HiroFriends.divTombola = $("<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')+')' });
			var eventImage = HiroFriends.cdnBase + "/images/interface/friendsbar/events/" + HiroFriends.eventName + ".png";	// event based
			if(HiroFriends.eventName == 'Octoberfest') eventImage = HiroFriends.cdnBase + "/images/window/events/octoberfest/pretzels_icon.png";
			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" });
			if(HiroFriends.pendingInvitations) {
				HiroFriends.spanCounter.css("right", "20px");
				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;" });
				HiroFriends.spanInvitations.hover(function() { $(this).css("background-position", "0px -25px"); }, function() { $(this).css("background-position", ""); });
				HiroFriends.spanInvitations.click(function() { $(this).hide(); HiroFriends.spanCounter.css("right", "5px"); FriendslistWindow.open('openrequests'); return false; });
				divCounter.append(HiroFriends.spanInvitations);
			}
			divContainer.append(divRefresh.append(spanRefresh), spanSend.append(imageSend), divCounter.append(HiroFriends.divTombola, HiroFriends.spanCounter)).appendTo("#user-interface");
			spanRefresh.hover(function() { $(this).css("background-position", ""); }, function() { $(this).css("background-position", "0px -20px"); });
			spanRefresh.click(function() {
				if ('Octoberfest' == HiroFriends.eventName) {
					HiroFriends.divTombola.slideUp(500, function() { if (HiroFriends.wofId) HiroFriends.getWofStatus(); }).slideDown(1500); 
				}
				HiroFriends.spanCounter.slideUp(500, function() { HiroFriends.fetch(); }).slideDown(1500);
				return false;
			});
			imageSend.click(function() { HiroFriends.open(); return false; });
			HiroFriends.eventCurrencyImage = "/images/icons/"+HiroFriends.eventName+".png";
			if(enableInv) {
				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");
				HiroFriends.eventItems.imgInventory = $('<img src="'+HiroFriends.eventCurrencyImage+'" alt="" title="">').click(function(e){ e.preventDefault(); HiroFriends.eventItems.display(); return false; }).appendTo(HiroFriends.eventItems.divInventory);
			}
			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");
			HiroFriends.imgFriendsAvail = $('<img src="'+HiroFriends.eventCurrencyImage+'" alt="" title="'+scriptName+'">').click(function(e){ e.preventDefault(); HiroFriends.open(); return false; }).appendTo(HiroFriends.divFriendsAvail);
			if('Octoberfest' == HiroFriends.eventName) { HiroFriends.getWofId(); }
			else { 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");
			HiroFriends.fetch();
			HiroFriends.signalHandlers();
		},
		fetch: function() {
			if(this.interval !== false) clearInterval(this.interval);
			var event_times = {};
			var friends = {}, total = 0, avail = 0, recv = 0;
			var server_time = Game.getServerTime(), activation_time, friend_time;
			if(this.timeLeft < 0) {
				$("#hiro_friends_container").slideUp(5000);
				if(enableInv) HiroFriends.eventItems.divInventory.hide(5000);
				throw "Event is over";
			}
			if(enableInv) {
				if(HiroFriends.eventItems.check() && HiroFriends.eventItems.Available.length > 0)
					HiroFriends.eventItems.divInventory.show(5000);
				else HiroFriends.eventItems.divInventory.hide();
			}
			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;
						if(undefined === HiroFriends.log.friendLog[val.player_id]) {
							recv = 0;
							HiroFriends.log.friendLog[val.player_id] = { name: val.name, total: 0, dates: [] };
						}
						else recv = HiroFriends.log.friendLog[val.player_id].total;
						friends[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.updateCounter();
				if(HiroFriends.avail) {
					HiroFriends.imgFriendsAvail.attr('title', 'TW Friends: '+HiroFriends.avail+'/'+HiroFriends.total);
					HiroFriends.divFriendsAvail.show(5000);
				}
				else HiroFriends.divFriendsAvail.hide();
				HiroFriends.interval = setInterval(function() { HiroFriends.fetch(); }, refreshMs);
			});
		},
		displayWofStatus: function() {
			$.fn.hiro_wof_status = function(cat, wof_state) {
				var ar_title1 = HiroFriends.localeMsg('wofCat');
				var ar_title2 = HiroFriends.localeMsg('wofState');
				var ar_title3 = ar_title2[HiroFriends.eventName];
				switch(wof_state) {
					case 0	: $(this).css({ "background": "url('"+HiroFriends.cdnBase+"/images/tw2gui/iconset.png?14') no-repeat -98px 0", "opacity": "0.5" }); break;
					case 1	: $(this).css({ "background": "url('"+HiroFriends.cdnBase+"/images/tw2gui/iconset.png?14') no-repeat -82px -16px", "opacity": "1" }); break;
					case 2	: $(this).css({ "background": "url('"+HiroFriends.cdnBase+"/images/tw2gui/iconset.png?14') no-repeat -112px -16px", "opacity": "1" }); break;
					case 3	: $(this).css({ "background": "url('"+HiroFriends.cdnBase+"/images/tw2gui/iconset.png?14') no-repeat -98px -16px", "opacity": "1" }); break;
					default	: $(this).css({ "background": "url('"+HiroFriends.cdnBase+"/images/tw2gui/iconset.png?14') no-repeat -66px -80px", "opacity": "0.5" });
				}
				$(this).addMousePopup({
					'teaser' : '<b>' + ar_title1[cat] + '</b>',
					'content': '<div style="max-width: 250px;">' + ar_title3[wof_state] + '</div>'
				});
				return $(this);
			};
			$.fn.hiro_wof_insufficient = function(cat) { return $(this).hiro_wof_status(cat, 1); };
			$.fn.hiro_wof_working = function(cat) { return $(this).hiro_wof_status(cat, 0); };
			$.fn.hiro_wof_can_play = function(cat) { return $(this).hiro_wof_status(cat, 2); };
			$.fn.hiro_wof_can_bribe = function(cat) { return $(this).hiro_wof_status(cat, 3); };
			var data = HiroFriends.wofStatus;
			var cost_bribe = data.mode.cost.bribe * data.mode.conversion.ses;
			var cost_uncommon = data.prizes.enhancements[2] * data.mode.conversion.ses;
			var cost_rare = data.prizes.enhancements[1] * data.mode.conversion.ses;
			var cost_veryRare = data.prizes.enhancements[0] * data.mode.conversion.ses;
			var currencyAvailable = Character.ses_currency[HiroFriends.eventName.toLowerCase()];
			var state_common = undefined == data.mode ? undefined : data.mode.states[0];
			var state_uncommon = undefined == data.mode ? undefined : data.mode.states[25];
			var state_rare = undefined == data.mode ? undefined : data.mode.states[150];
			var state_veryRare = undefined == data.mode ? undefined : data.mode.states[800];
			if (undefined == state_common || !state_common.being_built) {
				if (currencyAvailable >= cost_bribe) $("#hiro_wof_1").hiro_wof_can_bribe(0);
				else $("#hiro_wof_1").hiro_wof_can_play(0);
			}
			else $("#hiro_wof_1").hiro_wof_working(0);
			if (undefined == state_uncommon || !state_uncommon.being_built) {
				if (currencyAvailable < cost_uncommon) $("#hiro_wof_2").hiro_wof_insufficient(1);
				else if (currencyAvailable < cost_uncommon + cost_bribe) $("#hiro_wof_2").hiro_wof_can_play(1);
				else $("#hiro_wof_2").hiro_wof_can_bribe(1);
			}
			else $("#hiro_wof_2").hiro_wof_working(1);
			if (undefined == state_rare || !state_rare.being_built) {
				if (currencyAvailable < cost_rare) $("#hiro_wof_3").hiro_wof_insufficient(2);
				else if (currencyAvailable < cost_rare + cost_bribe) $("#hiro_wof_3").hiro_wof_can_play(2);
				else $("#hiro_wof_3").hiro_wof_can_bribe(2);
			}
			else $("#hiro_wof_3").hiro_wof_working(2);
			if (undefined == state_veryRare || !state_veryRare.being_built) {
				if (currencyAvailable < cost_veryRare) $("#hiro_wof_4").hiro_wof_insufficient(3);
				else if (currencyAvailable < cost_veryRare + cost_bribe) $("#hiro_wof_4").hiro_wof_can_play(3);
				else $("#hiro_wof_4").hiro_wof_can_bribe(3);
			}
			else $("#hiro_wof_4").hiro_wof_working(3);
		},
		getWofId: function() {
			var wof_id = undefined;
			try { wof_id = west.wof.WofManager.wofs.octoberwof.getId(); } catch (e) { }
			if (wof_id) {
				HiroFriends.wofId = wof_id;
				HiroFriends.getWofStatus();
			}
			else setTimeout(function() { HiroFriends.getWofId(); }, 1e3);
		},
		getWofStatus: function() {
			clearTimeout(HiroFriends.wofTimeout);
			return $.ajax({ type: "POST", url: "/game.php?window=wheeloffortune&mode=init", data: { wofid: HiroFriends.wofId }, success: function(data) {
				HiroFriends.wofStatus = data;
				should_check_again = 86400*1e3;	/* 1 day */
				if (undefined !== data.mode && undefined !== data.mode.states) {
					now = Date.now()/1e3;
					$.each(data.mode.states, function(key, val) {
						if (val.being_built) should_check_again = Math.min((val.finish_date-now)*1e3, should_check_again);
					});
				}
				var will_check_again = Math.min(refreshWof, Math.max(1e3, should_check_again));
				HiroFriends.wallet = Character.ses_currency[HiroFriends.eventName.toLowerCase()];
				HiroFriends.displayWofStatus();
				HiroFriends.wofTimeout = setTimeout(function() { HiroFriends.getWofStatus(); }, will_check_again);
			} });
		},
		getLogPage: function(page, limit, deferred) {
			return $.ajax({ type: "POST", url: "/game.php?window=ses&mode=log", data: { ses_id: HiroFriends.eventName, page: page, limit: limit }, success: function(data) {
				var details;
				var hasNext = data.hasNext;
				var count = 0;
				var limit = data.limit;
				page = data.page + 1;
				$.each(data.entries, function(key, val) {
					count = parseInt(val.value);
					if(val.date < HiroFriends.log.firstLog) HiroFriends.log.firstLog = val.date;
					if(val.date <= HiroFriends.log.lastLog) {
						hasNext = false;
						return false;
					}
					HiroFriends.log.entries.push(val);
					if(val.date > HiroFriends.log.newLastLog) {
						HiroFriends.log.newLastLog = val.date;
					}
					switch(val.type) {
						case "friendDrop":
							if(null !== val.details) {
								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 "questDrop":	HiroFriends.log.count_quest += 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(null !== val.details) {
								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;
					}
				});
				if (hasNext) return HiroFriends.getLogPage(page, limit, deferred);
				else {
					/* Done */
					HiroFriends.log.lastLog = HiroFriends.log.newLastLog;
					Chat.Request.Nop();
					deferred.resolve();
				}
			} });
		},
		getLog: function() {
			if(enableLog) {
				var deferred = new $.Deferred();
				var limit = 100;
				HiroFriends.log.newLastLog = HiroFriends.log.lastLog;
				this.getLogPage(1, limit, deferred);
				return deferred.promise();
			}
		},
		getPendingInvitations: function() {
			return $.post("/game.php?window=character&mode=get_open_requests", function(data) {
				var openReq = 0;
				$.each(data.open_friends, function(key, val) { if(val.inviter_id != Character.playerId) ++ openReq; });
				HiroFriends.pendingInvitations = openReq;
			});
		},
		localeMsg: function(msg) {
			if(undefined !== this.messages[this.locale][msg]) return this.messages[this.locale][msg];
			if(undefined !== this.messages['en_US'][msg]) return this.messages['en_US'][msg];
			return '';
		},
		open: function() {
			if(!WestUi.FriendsBar.hidden) WestUi.FriendsBar.toggle();
			$.when(this.getLog()).done(function() {
				HiroFriends.fetch().done(function() {
					HiroFriends.divFriendsAvail.hide();
					HiroFriends.getPendingInvitations().done(function() {
						HiroFriends.display('time');
					});
				});
			});
		},
		pendingInvitationsMsg: function() { return this.pendingInvitations == 1 ? this.localeMsg('pendingInvitation') : this.pendingInvitations+' '+this.localeMsg('pendingInvitations'); },
		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();
						delete(HiroFriends.friends[charId]);
						if(HiroFriends.avail) -- HiroFriends.avail;
						if(HiroFriends.total) -- HiroFriends.total;
						HiroFriends.updateCounter();
						Chat.Friendslist.removeFriend(charId);
					}
					else new UserMessage(HiroFriends.localeMsg('removeFailed'), UserMessage.TYPE_ERROR).show();
				})
			}).addButton("no").show();
		},
		sortByName: function(a, b) { return a.name.toLowerCase().localeCompare(b.name.toLowerCase()); },
		sortByRecv: function(a, b) { return b.recv - a.recv; },
		sortByTime: function(a, b) { return a.activation_time - b.activation_time; },
		updateCounter: function() {
			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>');
		},
		updateTimer: function() {
			this.timeLeft = this.eventEndStamp - Game.getServerTime();
			if(this.timeLeft <= 0) {
				this.divTombola.html(this.localeMsg('theEnd'));
				this.fetch();
				return;
			}
			this.divTombola.html(this.timeLeft.formatDurationBuffWay());
			var seconds = 0;
			if(this.timeLeft < 70) seconds = 1;
			else if(this.timeLeft < 3660) seconds = 10;
			else if(this.timeLeft < 86520) seconds = 60;
			else seconds = 120;
			setTimeout(function() { HiroFriends.updateTimer(); }, seconds * 1e3);
		},
		versionCheck: function(user_initiated = true) {
			try {
				$.getScript(URL_VERSION).done(function() {
					if(HiroFriends.latestVersion && HiroFriends.latestVersion > VERSION) {
						var upgradeDialog = new west.gui.Dialog(scriptName + ' ' + HiroFriends.localeMsg('version')+' ' + HiroFriends.latestVersion, HiroFriends.localeMsg('version_upgrade'), west.gui.Dialog.SYS_WARNING).addButton('ok', function() {
							try { upgradeDialog.hide(); location.href = URL_CODE; } catch(e) {}
						}).addButton('cancel').show();
					}
					else if (user_initiated) new west.gui.Dialog(scriptName + ' ' + HiroFriends.localeMsg('version')+' ' + HiroFriends.version.toFixed(2), HiroFriends.localeMsg('version_ok'), west.gui.Dialog.SYS_OK).addButton("ok").show();
				});
			}
			catch(e) {
				new west.gui.Dialog(scriptName, HiroFriends.localeMsg('version_checkFailed'), west.gui.Dialog.SYS_WARNING).addButton(HiroFriends.localeMsg('version_checkManual'), function() { window.open(URL_INSTALL, '_blank'); }).addButton("cancel").show();
			}
		},
		scriptInit: function(tries, maxTries) {
			var ev, eventName;
			if(tries >= maxTries) return false;
			if(Game && Game.loaded && Character.playerId) {
				this.locale = (undefined === Game.locale || undefined == this.messages[Game.locale]) ? "en_US" : Game.locale;
				this.api.setGui(this.localeMsg('description'));
				if (enableVersionCheck) this.versionCheck(false);
				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 || 'Octoberfest' == eventName) {
						this.getPendingInvitations().done(function() {
							HiroFriends.eventManager(eventName);
						});
						return false;
					}
				}
				return true;
			}
			++ tries;
			setTimeout(function() { HiroFriends.scriptInit(tries, maxTries); }, tries * 1e3);
		},
	}
	try { HiroFriends.scriptInit(0, 100); } catch(e) { }
});