Facebook
From Voluminous Mockingbird, 6 Years ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 475
  1. // ==UserScript==
  2. // @name         Panel Dodatków NI
  3. // @namespace    http://the-crudness.xaa.pl/NIAddons/panel.user.js
  4. // @version      2.5
  5. // @description  Dodaje do wbudowanego panelu dodatków inne dodatki.
  6. // @author       Priveeq
  7. // @include              http://aldous.margonem.pl/
  8. // @include              http://tempest.margonem.pl/
  9. // @include              http://mordor.margonem.pl/
  10. // @include              http://invisible.margonem.pl/
  11. // @include              http://dionizos.margonem.pl/
  12. // @include              http://genos.margonem.pl/
  13. // @include              http://majorka.margonem.pl/
  14. // @include              http://aequus.margonem.pl/
  15. // @include              http://experimental-ni.margonem.pl/
  16. // @include              http://husaria.margonem.com/
  17. // @include              http://cronus.margonem.com/
  18. // @grant        none
  19. // ==/UserScript==
  20. // ==Changelog==
  21. // 2.5 - znów pełno zmian w API, kolejny nowy dodatek
  22. // 2.4 - pierdyliard zmian w API, nowy dodatek, usunięte na obecną chwile dodatki darrefulla bo mu hosting padł czy coś
  23. // 2.3 - nowy dodatek, naprawione loader.require
  24. // 2.2 - włączenie dodatku pokazywanie kolizji dla angielskiego margonem, bo działają już tam widgety. Trochę wewnętrznych zmian w tym skrypcie
  25. // 2.1 - dodatek lepsza walka, trochę zmian w tym kodzie żeby łatwiej się robiło dodatki (event emmitery anyone?)
  26. // 2.0.1 - pierwsza nietestowa wersja
  27. // ==/Changelog==
  28. window.priwAddons = new (function() {
  29.         var addons = this;
  30.         window.API.priw = this;
  31.         var Storage = API.Storage;
  32.         var Templates = API.Templates;
  33.         this.list = {
  34.                 priw_clbl: {
  35.                         namePL: "Błoga klanowe",
  36.                         nameEN: "Guild blessings",
  37.                         descPL: "Dodaje pod torbami panel wyboru błogosławieństwa klanowego, taki skrót. Nie ma sensu instalować na nakładce NI, bo w starym systemie klanów tych błogosławieństw nie ma.",
  38.                         descEN: "Adds shortcuts to guild blessings under the bags.",
  39.                         urlPL: "http://the-crudness.xaa.pl/NIAddons/get/NIblesspanel.js?",
  40.                         urlEN: "http://the-crudness.xaa.pl/NIAddons/get/NIblesspanel.js?",
  41.                         img: "http://aldous.margonem.pl/img/gui/buttony.png?v=4|-561 -12",
  42.                         author: "Priveeq|3779166"
  43.                 },
  44.                 priw_ntpd: {
  45.                         namePL: "Notatnik",
  46.                         nameEN: "Notepad",
  47.                         descPL: "Dodaje prosty notatnik, dostępny pod torbami.",
  48.                         descEN: "Adds a simple notepad under the bags.",
  49.                         urlPL: "http://the-crudness.xaa.pl/NIAddons/get/notepadNI.js?",
  50.                         urlEN: "http://the-crudness.xaa.pl/NIAddons/get/notepadNI.js?",
  51.                         img: "http://aldous.margonem.pl/img/gui/buttony.png?v=4|-437 -12",
  52.                         author: "Priveeq|3779166"
  53.                 },
  54.                 priw_extl: {
  55.                         namePL: "Instalator zewnętrznych skryptów",
  56.                         nameEN: "External script loader",
  57.                         descPL: "Pozwala instalować zewnętrzne dodatki przez wpisanie adresu do skryptu. <a href='https://gyazo.com/42856b0a644881f93b17e27ec02674ac' target='_blank'>Wygląda to tak.</a>",
  58.                         descEN: "Allows installing external scripts from a given url, as shown <a href='https://gyazo.com/dbdbffca2a65e982293caef243b96981' target='_blank'>here.</a>",
  59.                         urlPL: "http://the-crudness.xaa.pl/NIAddons/get/NIextLoader.js?",
  60.                         urlEN: "http://the-crudness.xaa.pl/NIAddons/get/NIextLoader.js?",
  61.                         img: "http://aldous.margonem.pl/img/gui/buttony.png?v=4|-282 -12",
  62.                         author: "Priveeq|3779166",
  63.                         widget: {
  64.                                 color: "blue",
  65.                         }
  66.                 },
  67.                 priw_obw: {
  68.                         namePL: "Lepsza walka",
  69.                         nameEN: "Better battle",
  70.                         descPL: "Dodaje następujące rzeczy do walki:<br>-animowanie przesuwania się postaci<br>-bardziej widoczne pokazywanie naszej tury<br>-mniejsze odległości między postaciami w walce<br>-ilość życia, many i energii w tipach (dymkach) nad postaciami<br>-wybór umiejętności jak na starym interfejsie (można wyłączyć w dolnej części konfiguracji gry)",
  71.                         descEN: "Adds following features to the battle window:<br>-characters now move smoothly from place to place, instead of teleporting<br>-better indication of player's turn<br>-distance between characters is smaller<br>-health, energy and mana is shown in tooltips above characters<br>-alternative skill selection method, samilar to how it was on the old interface (this feature can be disabled at the bottom of game config)",
  72.                         //urlPL: "http://192.168.0.110:1337/NIoldBattle.js",
  73.                         urlPL: "http://the-crudness.xaa.pl/NIAddons/get/NIoldBattle.js?7",
  74.                         urlEN: "http://the-crudness.xaa.pl/NIAddons/get/NIoldBattle.js?7",
  75.                         img: "http://aldous.margonem.pl/img/gui/addons-icons.png|-4 -34",
  76.                         author: "Priveeq|3779166"
  77.                 },
  78.                 priw_mmp: {
  79.                         namePL: "miniMap+",
  80.                         nameEN: "miniMap+",
  81.                         descPL: "Dodaje do gry wielofunkcyjną minimapę. Domyślnie otwiera sie klawiszem [R]",
  82.                         descEN: "Adds a multifunctional minimap. Default hotkey to open it is set to [R]. Note that it hasn't been translated to english.",
  83.                         urlPL: "http://the-crudness.xaa.pl/NIAddons/get/miniMapPlusNI.js",
  84.                         urlEN: "http://the-crudness.xaa.pl/NIAddons/get/miniMapPlusNI.js",
  85.                         img: "http://aldous.margonem.pl/img/gui/buttony.png|-158 -12",
  86.                         author: "Priveeq|3779166"
  87.                 },
  88.                 priw_tth: {
  89.                         namePL: "Titan Helper+",
  90.                         nameEN: "Titan Helper+",
  91.                         descPL: "Pokazuje w oknie walki użyteczne informacje (ilość tur od użycia aury SA, aktualnie ładowany atak specjalny tytana itp)",
  92.                         descEN: "Shows some useful info in the battle window (amount of turns that has passed since someone used attack speed aura, spell that is currently being charged by a titan etc). It hasn't been translated from polish, but I think it should be easy enough to figure out what it shows.",
  93.                         urlPL: "http://the-crudness.xaa.pl/NIAddons/get/titanHelperPlusNI.js",
  94.                         urlEN: "http://the-crudness.xaa.pl/NIAddons/get/titanHelperPlusNI.js",
  95.                         img: "http://aldous.margonem.pl/img/gui/addons-icons.png|-4 -34",
  96.                         author: "Priveeq|3779166"
  97.                 },
  98.                 priw_sf: {
  99.                         namePL: "ShopFilter",
  100.                         nameEN: "ShopFilter",
  101.                         descPL: "Dodaje do sklepów dodatkowe opcje filtrowania.",
  102.                         descEN: "Adds additional filters to shops.",
  103.                         urlPL: "http://the-crudness.xaa.pl/NIAddons/get/shopFilterNI.js",
  104.                         urlEN: "http://the-crudness.xaa.pl/NIAddons/get/shopFilterNI.js",
  105.                         img: "http://aldous.margonem.pl/img/gui/addons-icons.png|-128 -3",
  106.                         author: "Priveeq|3779166"
  107.                 },
  108.                 priw_sakwa: {
  109.                         namePL: "Sakwa",
  110.                         nameEN: "Pouch",
  111.                         descPL: "Przywraca funkcjonalną sakwę ze starego interfejsu.",
  112.                         descEN: "Restores a functional pouch from the old interface.",
  113.                         urlPL: "http://the-crudness.xaa.pl/NIAddons/get/pouch.js",
  114.                         urlEN: "http://the-crudness.xaa.pl/NIAddons/get/pouch.js",
  115.                         img: "/obrazki/npc/mas/nic32x32.gif",
  116.                         author: "Priveeq|3779166"
  117.                 },
  118.                 priw_h2h: {
  119.                         namePL: "https2http",
  120.                         nameEN: "https2http",
  121.                         descPL: "Linki które mają z przodu https nie działają na chacie. Dodatek zamienia w wysyłanych wiadomościach https na http i wtedy działają.",
  122.                         descEN: "Fixes a bizzare bug that causes links that contain https to not work by replacing https with http in sent messages.",
  123.                         urlPL: "http://the-crudness.xaa.pl/NIAddons/get/https2httpNI.js",
  124.                         urlEN: "http://the-crudness.xaa.pl/NIAddons/get/https2httpNI.js",
  125.                         img: "http://aldous.margonem.pl/img/gui/buttony.png?v=4|-406 -12",
  126.                         author: "Priveeq|3779166"
  127.                 },
  128.                 groov_gll: {
  129.                         namePL: "Global lootlog",
  130.                         descPL: "Jest to dodatek, który umieszcza nasze looty heroiczne i legendarne na stronie, aby później móc je przeglądać. Podczas lootnięcia itemu zawsze mamy możliwość zdecydowania, czy ma on zostać tam dodany, czy też nie.<br><br>Dodatek zapisuje zdobycze ze światów publicznych i prywatnych.<br><br>Strona główna: <a href='http://grooove.pl/lootlog/' target='_blank'>http://grooove.pl/lootlog/</a>",
  131.                         urlPL: "http://addons2.margonem.pl/get/70/70663dev.js",
  132.                         img: "http://aldous.margonem.pl/img/gui/buttony.png|-158 -12",
  133.                         author: "Groove Armada|3088295",
  134.                         beforeInstall: function() {
  135.                                 if ($("#GLobalLootlogLauncher").length) {
  136.                                         message("Global lootlog jest już zainstalowany z innego źródła.");
  137.                                         return true;
  138.                                 };
  139.                         },
  140.                         noEN: true
  141.                 },
  142.                 groov_pw: {
  143.                         namePL: "Panel walk",
  144.                         nameEN: "Battle panel",
  145.                         descPL: "Dodatek automatycznie zapisuje walki z graczami na stronie, gdzie później ładnie je wyświetla.<br>Przykład: <a href='http://grooove.pl/battle/id-1' target='_blank'>http://grooove.pl/battle/id-1</a>",
  146.                         descEN: "This addon automatically saves battles aganist other players on a website, where they are nicely displayed.<br>Example: <a href='http://grooove.pl/battle/id-1' target='_blank'>http://grooove.pl/battle/id-1</a>",
  147.                         urlPL: "http://addons2.margonem.pl/get/70/70674dev.js",
  148.                         urlEN: "http://addons2.margonem.pl/get/70/70674dev.js",
  149.                         img: "http://aldous.margonem.pl/img/gui/addons-icons.png|-4 -34",
  150.                         author: "Groove Armada|3088295",
  151.                         beforeInstall: function() {
  152.                                 if ($("#PWLauncher").length) {
  153.                                         message("Panel walk jest już zainstalowany z innego źródła.");
  154.                                         return true;
  155.                                 };
  156.                         },
  157.                 },
  158.                 groov_count: {
  159.                         namePL: "Licznik ubić by Groove",
  160.                         nameEN: "Kill counter",
  161.                         descPL: "Liczy ubicia elit, elit II, herosów, tytanów i eventowych potworów.<br><br>Aby zresetować licznik lub usunąć pojedynczy wpis, należy wejść na stronę <a href='http://grooove.pl/licznik/' target='_blank'>http://grooove.pl/licznik/</a> i się zalogować.",
  162.                         descEN: "Counts how many times you've killed monsters with ranks above elite. To reset the counter or delete a single entry, you have to visit <a href='http://grooove.pl/licznik/' target='_blank'>http://grooove.pl/licznik/</a> and log in.",
  163.                         urlPL: "http://addons2.margonem.pl/get/70/70632dev.js",
  164.                         urlEN: "http://addons2.margonem.pl/get/70/70688dev.js",
  165.                         img: "http://aldous.margonem.pl/img/gui/addons-icons.png|-97 -34",
  166.                         author: "Groove Armada|3088295",
  167.                         beforeInstall: function() {
  168.                                 if ($("#GACounterLauncher").length) {
  169.                                         message("Licznik ubić jest już zainstalowany z innego źródła.");
  170.                                         return true;
  171.                                 };
  172.                         },
  173.                 },
  174.                 ake_coll: {
  175.                         namePL: "Pokazywanie kolizji",
  176.                         nameEN: "Show collisions",
  177.                         descPL: "Pokazuje kolizje na mapie.",
  178.                         descEN: "Shows map collisions.",
  179.                         urlPL: "http://addons2.margonem.pl/get/76/76788dev.js?3",
  180.                         urlEN: "http://addons2.margonem.pl/get/76/76788dev.js?3",
  181.                         img: "http://aldous.margonem.pl/img/gui/buttony.png|-702 -710",
  182.                         author: "Akechi|229327",
  183.                         widget: {
  184.                                 color: "blue"
  185.                         }
  186.                 },
  187.                 ccar_evo: {
  188.                         namePL: "Evolution Manager",
  189.                         nameEN: "Evolution Manager",
  190.                         descPL: "Wielofunkcyjny manager dodatków. <a target='_blank' href='https://www.margonem.pl/?task=forum&show=posts&id=469794'>Temat na forum</a>.<br>Instaluje się jego osobny userscript.",
  191.                         descEN: "multifunctional addon manager. <a target='_blank' href='https://www.margonem.pl/?task=forum&show=posts&id=469794'>Polish forum thread</a>.<br>Installs as a separate userscript.",
  192.                         urlPL: "http://m.ccrr.pl/evo/client/start.user.js",
  193.                         urlEN: "http://m.ccrr.pl/evo/client/start.user.js",
  194.                         img: "http://aldous.margonem.pl/img/gui/buttony.png|-437 -12",
  195.                         author: "Programista CcarderR|2210626",
  196.                         beforeInstall: function() {
  197.                                 if (typeof (evoStart) != "undefined") {
  198.                                         message("Evolution Manager jest już zainstalowany.");
  199.                                 } else {
  200.                                         window.open("http://m.ccrr.pl/evo/client/start.user.js");
  201.                                 };
  202.                                 return true;
  203.                         },
  204.                 },
  205.                 //eeeeeee darrowi padł hosting to na chwilę obecną wywalam z panelu
  206.                 /*darr_mm: {
  207.                         namePL: "Margomap",
  208.                         nameEN: "Margomap",
  209.                         descPL: "Prosta minimapa, otwiera się przyciskiem [E]",
  210.                         descEN: "A simple minimap, can be opened with the [E] button.",
  211.                         urlPL: "http://addons2.margonem.pl/get/77/77011dev.js?3",
  212.                         urlEN: "http://addons2.margonem.pl/get/77/77011dev.js?3",
  213.                         data: "http://addons2.darro.eu/js/margomap.js",
  214.                         img: "http://aldous.margonem.pl/img/gui/buttony.png|-158 -12",
  215.                         author: "Darrefull|359424",
  216.                         beforeInstall: function() {
  217.                                 if (typeof window.DMargoMap != "undefined") {
  218.                                         message("Margomap jest już zainstalowany z innego źródła.");
  219.                                         return true;
  220.                                 };
  221.                         },
  222.                 },
  223.                 darr_akh: {
  224.                         namePL: "Licznik Akh-Mater",
  225.                         descPL: "Liczy nawróconych i zapytanych do questa Słowo Akh-Mater..",
  226.                         urlPL: "http://addons2.margonem.pl/get/77/77011dev.js?3",
  227.                         data: "http://addons2.darro.eu/js/akh-mater.js",
  228.                         img: "http://aldous.margonem.pl/img/gui/buttony.png|-189 -12",
  229.                         author: "Darrefull|359424",
  230.                         beforeInstall: function() {
  231.                                 if ($("div[data-tip*='Licznik do questa <br>Słowo Akh-Mate']").length > 0) {
  232.                                         message("Licznik Akh-Mater jest już zainstalowany z innego źródła.");
  233.                                         return true;
  234.                                 };
  235.                         },
  236.                         noEN: true
  237.                 },
  238.                 darr_coun: {
  239.                         namePL: "Licznik ubić by Darrefull",
  240.                         descPL: "Liczy ubicia elit/e2/herosów/tytanów.",
  241.                         urlPL: "http://addons2.margonem.pl/get/77/77011dev.js?3",
  242.                         data: "http://addons2.darro.eu/js/counter.js",
  243.                         img: "http://aldous.margonem.pl/img/gui/addons-icons.png|-97 -34",
  244.                         author: "Darrefull|359424",
  245.                         beforeInstall: function() {
  246.                                 if (typeof window.eCounter != "undefined") {
  247.                                         message("Licznik ubić by Darrefull jest już zainstalowany z innego źródła.");
  248.                                         return true;
  249.                                 };
  250.                         },
  251.                         noEN: true
  252.                 }*/
  253.         };
  254.         this.addonIds = Object.keys(this.list);
  255.         this.storageKey = "priwAddons";
  256.         this.getStorage = function() {
  257.                 if (!this.storageCache) {
  258.                         this.storageCache = localStorage.getItem(this.storageKey) ? JSON.parse(localStorage.getItem(this.storageKey)) : [];
  259.                 };
  260.                 return this.storageCache;
  261.         };
  262.         this.setStorage = function(storage) {
  263.                 this.storageCache = storage;
  264.                 localStorage.setItem(this.storageKey, JSON.stringify(storage));
  265.         };
  266.         this.fixStorage = function() {
  267.                 var storage = this.getStorage();
  268.                 var len = storage.length;
  269.                 for (var i=0; i<storage.length; i++) {
  270.                         if (this.addonIds.indexOf(storage[i]) == -1) { //gracz ma nieinstniejący dodatek który zaśmieca storage
  271.                                 //jak dodatek co został wywalony z listy miał widget to go trza wywalić
  272.                                 if (typeof storage[i] == "number") { //stare wersje dodatku były dziwaczne, tak just in case gdyby ktoś miał stary typ jeszcze. Kiedyś to wywalę
  273.                                         if (API.Storage.get("hotWidget/addon_"+(storage[i]+1000))) API.Storage.remove("hotWidget/addon_"+(storage[i]+1000));
  274.                                 } else {
  275.                                         if (API.Storage.get("hotWidget/addon_"+storage[i])) API.Storage.remove("hotWidget/addon_"+storage[i]);
  276.                                 };
  277.                                 storage.splice(i, 1);
  278.                                 i--;
  279.                         };
  280.                 };
  281.                 if (len != storage.length) this.setStorage(storage);
  282.         };
  283.         this.getAddonState = function(id) {
  284.                 var storage = this.getStorage();
  285.                 return (storage.indexOf(id) > -1);
  286.         };
  287.         this.toggleAddon = function(id) {
  288.                 var storage = this.getStorage();
  289.                 if (storage.indexOf(id) > -1) {
  290.                         storage.splice(storage.indexOf(id), 1);
  291.                 } else {
  292.                         storage.push(id);
  293.                 };
  294.                 this.setStorage(storage);
  295.         };
  296.         this.fixStorage();
  297.         this.loader = new (function(_ajax){
  298.                 var self = this;
  299.                 this.addonsLoaded = 0;
  300.                 this.waitForInterfaceChanger = false; //eliminuje potencjalną możliwość zagryzienia się z dodatkiem SI2NI
  301.                 if (typeof __bootNI != "undefined" && __bootNI) {
  302.                         var _reCallInitQueue = Engine.reCallInitQueue;
  303.                         this.waitForInterfaceChanger = true;
  304.                         Engine.reCallInitQueue = function() { //funckja ta zostaje uruchomiona przez SI2NI gdy skończy ładować swoje dodatki
  305.                                 self.waitForInterfaceChanger = false;
  306.                                 Engine.reCallInitQueue = _reCallInitQueue;
  307.                                 self.loadAddon();
  308.                         };
  309.                 };
  310.                 $.ajax = function(options) {
  311.                         if (self.addonsLoaded < addons.addonIds.length && options.url.indexOf("engine?t=init") > -1) {
  312.                                 self.loadAddon();
  313.                                 return;
  314.                         } else if (options.url.indexOf("margonem.pl/config.php") > -1) {
  315.                                 var oldsuccess = options.success;
  316.                                 options.success = function(data) {
  317.                                         addons.afterGameBoot();
  318.                                         var ret = oldsuccess.apply(this, arguments);
  319.                                         addons.afterInterfaceLoad();
  320.                                         return ret;
  321.                                 };
  322.                         } else if (options.url.indexOf("engine?t=") > -1) {
  323.                                 var oldsuccess = options.success;
  324.                                 var url = options.url;
  325.                                 options.success = function(data) {
  326.                                         var ret = oldsuccess.apply(this, arguments);
  327.                                         addons.callbackParser(data, url);
  328.                                         return ret;
  329.                                 };
  330.                         };
  331.                         return _ajax.apply(this, arguments);
  332.                 };
  333.                 this.loadAddon = function() {
  334.                         var id = addons.addonIds[this.addonsLoaded];
  335.                         if (addons.getAddonState(id)) {
  336.                                 var addon = addons.list[id];
  337.                                 if (addon.beforeInstall && addon.beforeInstall()) { //failsafe jakby ktoś coś odwalił
  338.                                         addons.toggleAddon(id);
  339.                                         return this.onAddonLoad();
  340.                                 };
  341.                                 if (!$.cachedScript) jQuery.cachedScript=function(e,c){return c=$.extend(c||{},{dataType:"script",cache:!0,url:e}),jQuery.ajax(c)};
  342.                                 var url = this.getUrl(addon);
  343.                                 window.__currentAddon = {
  344.                                         id: addons.addonIds[this.addonsLoaded],
  345.                                         data: addon.data
  346.                                 };
  347.                                 if (url.indexOf("?") > -1) url += "&v="+((new Date()).toLocaleDateString());
  348.                                 else url += "?v="+((new Date()).toLocaleDateString());
  349.                                 $.cachedScript(url).done(this.onAddonLoad).fail((xhr) => this.failedAddonLoad(id, xhr));
  350.                                 //$.getScript(url).done(this.onAddonLoad).fail((xhr) => this.failedAddonLoad(id, xhr));
  351.                         } else {
  352.                                 this.onAddonLoad();
  353.                         };
  354.                 };
  355.                 this.onAddonLoad = function() {
  356.                         self.addonsLoaded++;
  357.                         if (self.addonsLoaded < addons.addonIds.length) {
  358.                                 self.loadAddon();
  359.                         } else {
  360.                                 self.loadExtraAddons();
  361.                         };
  362.                 };
  363.                 var extraLoadFinished = false;
  364.                 var extraAddonsLoaded = -1;
  365.                 this.loadExtraAddons = function() {
  366.                         extraAddonsLoaded++;
  367.                         if (extraAddonsLoaded < extraAddons.length) {
  368.                                 var url = extraAddons[extraAddonsLoaded];
  369.                                 $.cachedScript(url).done(self.loadExtraAddons).fail((xhr) => self.failedExtraAddonLoad(url, xhr));
  370.                         } else {
  371.                                 if (!self.waitForInterfaceChanger) {
  372.                                         extraLoadFinished = true;
  373.                                         Engine.reCallInitQueue();
  374.                                 };
  375.                         };
  376.                 };
  377.                 this.require = function(url) {
  378.                         if (!extraLoadFinished) extraAddons.push(url);
  379.                         else throw "Ładowanie już się zakończyło.";
  380.                 };
  381.                 var extraAddons = [];
  382.                 this.failedAddonLoad = function(id, xhr) {
  383.                         var addon = addons.list[id];
  384.                         if (_l() == "pl") console.warn("Nie udało się załadować dodatku "+addon.namePL+" ["+this.getUrl(addon)+"] ("+xhr.status + " - "+xhr.statusText+")");
  385.                         else console.warn("Failed to load addon "+addon.nameEN+" ["+this.getUrl(addon)+"] ("+xhr.status + " - "+xhr.statusText+")");
  386.                         this.onAddonLoad();
  387.                 };
  388.                 this.failedExtraAddonLoad = function(url, xhr) {
  389.                         if (_l() == "pl") console.warn("Nie udało się załadować skryptu z require "+url);
  390.                         else console.warn("Failed to load required script "+url);
  391.                         this.loadExtraAddons();
  392.                 };
  393.                 this.getUrl = function(addon) {
  394.                         return _l() == "pl" ? addon.urlPL : addon.urlEN;
  395.                 };
  396.         })($.ajax);
  397.         var __g = _g;
  398.         _g = function(url, extra) {
  399.                 var ret = addons.requestParser(url, extra);
  400.                 arguments[0] = ret[0];
  401.                 arguments[1] = ret[1];
  402.                 return __g.apply(this, arguments);
  403.         };
  404.         this.requestParser = function(url, extra) {
  405.                 for (var i=0; i<this.requestParsers.length; i++) {
  406.                         var ret =this.requestParsers[i](url, extra);
  407.                         url = ret[0];
  408.                         extra = ret[1];
  409.                 };
  410.                 return [url, extra];
  411.         };
  412.         this.requestParsers = [];
  413.         this.callbackParser = function(data, url) {
  414.                 for (var i=0; i<this.extraServerCallbacks.length; i++) {
  415.                         this.extraServerCallbacks[i](data, url);
  416.                 };
  417.                 for (var i in data) {
  418.                         this.emmiter.emit(i, data[i]);
  419.                 };
  420.                 this.emmiter.emit("game-response", data);
  421.         };
  422.         //idk moja implementacja pewnie nie w 100% taka sama
  423.         this.Emmiter = function() {
  424.                 var on = [];
  425.                 var once = [];
  426.                 this.on = function(type, fun) {
  427.                         on.push(type, fun);
  428.                         return fun;
  429.                 };
  430.                 this.once = function(type, fun) {
  431.                         once.push(type, fun);
  432.                         return fun;
  433.                 };
  434.                 this.off = function(fun) {
  435.                         for (var i=1; i<on.length; i+=2) {
  436.                                 if (on[i] == fun) {
  437.                                         return on.splice(i-1, 2);
  438.                                 };
  439.                         };
  440.                 };
  441.                 this.emit = function(type, data) {
  442.                         for (var i=0; i<once.length; i+=2) {
  443.                                 if (once[i] == type) {
  444.                                         once[i+1](data);
  445.                                         once.splice(i, 2);
  446.                                         i -= 2;
  447.                                 };
  448.                         };
  449.                         for (var i=0; i<on.length; i+=2) {
  450.                                 if (on[i] == type) {
  451.                                         on[i+1](data);
  452.                                 }
  453.                         };
  454.                 };
  455.         };
  456.         this.emmiter = new this.Emmiter();
  457.         this.extraServerCallbacks = [];
  458.         this.checkForMismatch = function() { //jakby coś poszło nie tak
  459.                 for (var i in this.list) {
  460.                         if (this.getAddonState(i) != Engine.addonsPanel.getStorageStateOfAddon(i)) {
  461.                                 Engine.addonsPanel.toggleStateAddon(i);
  462.                         };
  463.                 };
  464.         };
  465.         this.addedCustomAddons = false;
  466.         this.doAfterGameBoot = [];
  467.         this.doAfterInterfaceLoad = [];
  468.         this.afterGameBoot = function() {
  469.                 for (var i in this.list) {
  470.                         var addon = this.list[i];
  471.                         if (addon.widget) {
  472.                                 var store = API.Storage.get("hotWidget/addon_"+i);
  473.                                 if (store) Engine.addonsPanel.addKeyToWidgets(i, store, _l() == "pl" ? addon.namePL : addon.nameEN);
  474.                         };
  475.                 };
  476.                 var _addonsShow = Engine.addonsPanel.manageVisible;
  477.                 Engine.addonsPanel.manageVisible = function() {
  478.                         var ret = _addonsShow.apply(this, arguments);
  479.                         if (!addons.addedCustomAddons) {
  480.                                 addons.checkForMismatch();
  481.                                 addons.addCustomAddonsToList();
  482.                                 addons.addedCustomAddons = true;
  483.                         };
  484.                         addons.emmiter.emit("addons-toggle");
  485.                         return ret;
  486.                 };
  487.                 var fun = function(id) {
  488.                         if (addons.isCustomAddon(id)) {
  489.                                 if (addons.addedCustomAddons && !addons.getAddonState(id)) {
  490.                                         message(addons.reloadMsg);
  491.                                         addons.toggleAddon(id);
  492.                                         var addon = addons.list[id];
  493.                                         if (addon.widget && !window["addon_"+id]) {
  494.                                                 window["addon_"+id] = {
  495.                                                         manageVisible: () => message("Dodatek zacznie działać po odświeżeniu gry")
  496.                                                 };
  497.                                         };
  498.                                 };
  499.                         } else {
  500.                                 _startAddonScript.apply(this, arguments);
  501.                         };
  502.                 };
  503.                 //dziwna różnica iędzy polskim a angielskim margonem
  504.                 if (Engine.addonsPanel.startAddonScript) {
  505.                         var _startAddonScript = Engine.addonsPanel.startAddonScript;
  506.                         Engine.addonsPanel.startAddonScript = fun;
  507.                 } else {
  508.                         var _startAddonScript = Engine.addonsPanel.turnOnAddon;
  509.                         Engine.addonsPanel.turnOnAddon = fun;
  510.                 };
  511.                 var _turnOffAddon = Engine.addonsPanel.turnOffAddon;
  512.                 Engine.addonsPanel.turnOffAddon = function(id) {
  513.                         if (addons.isCustomAddon(id)) {
  514.                                 if (addons.addedCustomAddons && addons.getAddonState(id)) {
  515.                                         message(addons.reloadMsg);
  516.                                         addons.toggleAddon(id);
  517.                                         if (addons.list[id].widget) {
  518.                                                 $(".icon.addon_"+id).parent().remove();
  519.                                                 if (API.Storage.get("hotWidget/addon_"+id)) API.Storage.remove("hotWidget/addon_"+id);
  520.                                         };
  521.                                 };
  522.                         } else {
  523.                                 _turnOffAddon.apply(this, arguments);
  524.                         };
  525.                 };
  526.                 var _setStateAddon = Engine.addonsPanel.setStateAddon;
  527.                 Engine.addonsPanel.setStateAddon = function(state, id) {
  528.                         if (addons.isCustomAddon(id) && state && addons.addedCustomAddons) {
  529.                                 var addon = addons.list[id];
  530.                                 if (addon.beforeInstall && addon.beforeInstall()) return;
  531.                         };
  532.                         return _setStateAddon.apply(this, arguments);
  533.                 };
  534.                 this.initCss();
  535.                 for (var i=0; i<this.doAfterGameBoot.lenth; i++) {
  536.                         this.doAfterGameBoot[i]();
  537.                 };
  538.                 this.emmiter.emit("game-load");
  539.         };
  540.         this.afterInterfaceLoad = function() {
  541.                 for (var i=0; i<this.doAfterInterfaceLoad.length; i++) {
  542.                         this.doAfterInterfaceLoad[i]();
  543.                 };
  544.                 this.emmiter.emit("interface-load");
  545.         };
  546.         this.isCustomAddon = function(id) {
  547.                 return (this.addonIds.indexOf(id) > -1);
  548.         };
  549.         this.addCustomAddonsToList = function() {
  550.                 for (var i in this.list) {
  551.                         var addon = this.list[i];
  552.                         if (_l() == "en" && addon.noEN) continue;
  553.                         if (_l() == "pl" && addon.noPL) continue;
  554.                         var author = addon.author.split("|");
  555.                         var authorHtml = "<div class='addon-author'>by <a href='http://www.margonem.pl/?task=profile&id="+author[1]+"' target='_blank'>"+author[0]+"</a></div>";
  556.                         var addonToAdd = {
  557.                                 pl: {
  558.                                         name: addon.namePL,
  559.                                         description: addon.descPL + authorHtml
  560.                                 },
  561.                                 en: {
  562.                                         name: addon.nameEN,
  563.                                         description: addon.descEN + authorHtml
  564.                                 },
  565.                                 image: addon.img,
  566.                                 options: addon.widget ? 1 : 0
  567.                         };
  568.                         Engine.addonsPanel.createOneAddonOnList(addonToAdd, i);
  569.                         Engine.addonsPanel.createOneAddonDescription(addonToAdd, i);
  570.                 }
  571.         };
  572.         this.reloadMsg =  _l() == "pl" ? "Zmiany będą widoczne po odświeżeniu gry..." : "Changes will come into effect once the page has been reloaded...";
  573.         this.initCss = function() {
  574.                 var css = `
  575.                         .addon-author {
  576.                                 font-size: 75%;
  577.                                 text-align: right;
  578.                                 color: #333333;
  579.                         }
  580.                 `;
  581.                 var widgets = {};
  582.                 for (var i in this.list) {
  583.                         var addon = this.list[i];
  584.                         if (!addon.widget) continue;
  585.                         if (addon.widget !== true) {
  586.                                 widgets[i] = addon.widget;
  587.                                 widgets[i].id = i;
  588.                         };
  589.                         css += `
  590.                                 .icon.addon_`+i+` {
  591.                                         background: `+Engine.addonsPanel.createBackgroundString(addon.img)+` !important;
  592.                                 }
  593.                         `;
  594.                 };
  595.                 this.emmiter.once("interface-load", ()=>this.widget.changeWidgetCss(widgets));
  596.                 $("<style>"+css+"</style>").appendTo("head");
  597.         };
  598.         //kod z Interface.showPopupMenu
  599.         var $aLayer = $(document.getElementsByClassName("alerts-layer")[0]);
  600.         this.popupMenu = function(menu, e) {
  601.                 if (!menu.length) return;
  602.                 var $m = $('<div class="custom-popup-menu"></div>');
  603.                 var $btn = API.Templates.get('button').addClass('small');
  604.                 for (var i in menu) {
  605.                         (function (i) {
  606.                                 var clone = $('<div class="menu-item">' + menu[i][0] + '</div>');
  607.                                 if (isset(menu[i][2])) {
  608.                                         clone.addClass(menu[i][2].button.cls);
  609.                                 }
  610.                                 $(clone).click(function (e) {
  611.                                         if (menu[i][1]()) e.stopPropagation();
  612.                                 });
  613.                                 $m.append(clone);
  614.                         })(i);
  615.                 };
  616.                 var zIndex = $aLayer.children().size() + 1;
  617.                 $aLayer.append($m);
  618.                 $m.css({
  619.                         top: e.clientY - $m.height() / 2,
  620.                         left: e.clientX - $m.width() / 2,
  621.                         'z-index': zIndex
  622.                 }).addClass('show');
  623.         };
  624.         document.addEventListener("click", () => {
  625.                 $('.custom-popup-menu').remove();
  626.         })
  627.         var $popupStyle = document.createElement("style");
  628.         //nie, nie mogę użyć normalnej klasy popup-menu bo gra kasuje element zanim mój eveneListener odpali ._.
  629.         //nie rozumiem jakim prawem tak się dzieje, ale niektóre rzeczy trzeba po prostu przyjąć do wiadomości bez rozumienia
  630.         $popupStyle.innerHTML = `
  631.                 .custom-popup-menu {
  632.                         border: 5px solid;
  633.                         max-width: 150px;
  634.                         border-image: url(../img/gui/ramka.png) 6 repeat;
  635.                         -webkit-transform: scale(0);
  636.                         -webkit-transition: 0.2s linear;
  637.                         -webkit-transition-timing-function: cubic-bezier(0.68, 0.77, 0.4, 1.89);
  638.                         z-index: 1;
  639.                         background-color: #3F3B3D;
  640.                         background-clip: padding-box;
  641.                         pointer-events: auto;
  642.                         position: absolute;
  643.                 }
  644.                 .custom-popup-menu .menu-item {
  645.                         cursor: url(../img/gui/cursor/5.png), auto;
  646.                         padding: 2px 5px;
  647.                         display: block;
  648.                         margin-bottom: 1px;
  649.                         font-size: 12px;
  650.                         text-align: center;
  651.                         border-radius: 3px;
  652.                         background-color: #244518;
  653.                         color: white;
  654.                         border: 1px solid #396420;
  655.                 }
  656.                 .custom-popup-menu .menu-item:last-child {
  657.                         margin-bottom: 0px;
  658.                 }
  659.                 .custom-popup-menu .menu-item.label {
  660.                         cursor: url(../img/gui/cursor/1.png), auto;
  661.                         border: 0px;
  662.                         background-color: transparent;
  663.                 }
  664.                 .custom-popup-menu .menu-item:hover:not(.label) {
  665.                         border: 1px solid #4f7b21;
  666.                         background-color: #2e4f18;
  667.                 }
  668.                 .custom-popup-menu.show {
  669.                         -webkit-transform: scale(1);
  670.                 }
  671.                 .custom-popup-menu .s_cost {
  672.                         display: inline-block;
  673.                         margin-left: 5px;
  674.                         font-weight: bold;
  675.                         border: 1px solid rgba(0, 0, 0, 0.3);
  676.                         border-radius: 3px;
  677.                         background-color: rgba(0, 0, 0, 0.2);
  678.                         padding: 0px 3px;
  679.                         color: lightblue;
  680.                         line-height: 15px;
  681.                 }
  682.         `;
  683.         document.head.appendChild($popupStyle);
  684.  
  685.  
  686.         this.dictionary = new (function() {
  687.                 var list = {};
  688.                 this.get = function(id, data) {
  689.                         var str = list[id];
  690.                         if (!str) return "missing["+id+"]";
  691.                         str = str[_l()];
  692.                         if (!str) return "nolang["+id+"]";
  693.                         for (var i in data) {
  694.                                 str = str.replace(i, data[i]);
  695.                         };
  696.                         return str;
  697.                 };
  698.                 this.add = function(id, txt) {
  699.                         list[id] = txt; //txt = {en: "txten", pl: "txtpl"}
  700.                 };
  701.                 this.addMany = function(data) {
  702.                         for (var i=0; i<data.length; i++) {
  703.                                 this.add(data[i].id, data[i].txt);
  704.                         };
  705.                 };
  706.         })();
  707.         var _txt = this.dictionary.get;
  708.  
  709.         //custom settings for addons
  710.         this.settings = new (function() {
  711.                 var self = this;
  712.                 var extraSettings = [];
  713.                 var $extraSettings, $scrollPane;
  714.                 addons.dictionary.add("addon_settings", {
  715.                         pl: "Ustawienia dodatków",
  716.                         en: "Addon settings"
  717.                 })
  718.                 if (!Storage.get("addonsettings")) {
  719.                         Storage.set("addonsettings", {});
  720.                 };
  721.                 this.init = function() {
  722.                         var _old = Engine.settings.toggle;
  723.                         self.initSettingTable();
  724.                         Engine.settings.toggle = function() {
  725.                                 var ret = _old.apply(this, arguments);
  726.                                 self.manageExtraSettings();
  727.                                 addons.emmiter.emit("settings-toggle");
  728.                                 return ret;
  729.                         };
  730.                 };
  731.                 this.initSettingTable = function() {
  732.                         $extraSettings = document.createElement("div");
  733.                         $extraSettings.classList.add("seccond-c");
  734.  
  735.                         var $header = document.createElement("h2");
  736.                         $header.classList.add("settings-addons");
  737.                         $header.innerHTML = "<span>"+_txt("addon_settings")+"</span>";
  738.                         $extraSettings.appendChild($header);
  739.  
  740.                         var $list = document.createElement("ul");
  741.                         $list.classList.add("hero-options");
  742.                         var html = "", setting, enabled;
  743.                         for (var i=0; i<extraSettings.length; i++) {
  744.                                 setting = extraSettings[i];
  745.                                 enabled = Storage.get("addonsettings/"+setting.id) ? " active" : "";
  746.                                 html += "<li data-setting_id='"+setting.id+"'><span class='checkbox"+enabled+"'></span><span class='label'>"+setting.txt+"</span></li>";
  747.                         };
  748.                         $list.innerHTML = html;
  749.                         $list.addEventListener("click", this.toggleSetting);
  750.                         $extraSettings.appendChild($list);
  751.                 };
  752.                 this.toggleSetting = function(e) {
  753.                         for (var i=0; i<e.path.length; i++) {
  754.                                 if (e.path[i].dataset["setting_id"]) {
  755.                                         var li = e.path[i];
  756.                                         var children = li.children;
  757.                                         var enabled = !Storage.get("addonsettings/"+li.dataset["setting_id"]);
  758.                                         Storage.set("addonsettings/"+li.dataset["setting_id"], enabled);
  759.                                         for (var i=0; i<children.length; i++) {
  760.                                                 if (children[i].classList.contains("checkbox")) {
  761.                                                         if (enabled) children[i].classList.add("active");
  762.                                                         else children[i].classList.remove("active");
  763.                                                         break;
  764.                                                 };
  765.                                         };
  766.                                         addons.emmiter.emit("toggle-addon-"+li.dataset["setting_id"], enabled);
  767.                                         break;
  768.                                 };
  769.                         };
  770.                 };
  771.                 this.manageExtraSettings = function() {
  772.                         if (!extraSettings.length) return;
  773.                         var $settings = document.getElementsByClassName("settings-window")[0];
  774.                         if ($settings) {
  775.                                 //tfw uparłeś się na nieużywanie jquery
  776.                                 var children = $settings.children;
  777.                                 for (var i=0; i<children.length; i++) {
  778.                                         if (children[i].classList.contains("hero-options-config")) {
  779.                                                 children = children[i].children[0].children; //xd
  780.                                                 break;
  781.                                         };
  782.                                 };
  783.                                 for (var i=0; i<children.length; i++) {
  784.                                         if (children[i].classList.contains("scroll-pane")) {
  785.                                                 $scrollPane = children[i];
  786.                                                 break;
  787.                                         };
  788.                                 };
  789.                                 if (!$scrollPane) return console.warn("coś się zepsuło");
  790.                                 $scrollPane.appendChild($extraSettings);
  791.                         };
  792.                 };
  793.                 this.add = function(data) {
  794.                         extraSettings.push(data);
  795.                         if (Storage.get("addonsettings/"+data.id) == null) Storage.set("addonsettings/"+data.id, data.default);
  796.                 };
  797.                 this.get = function(id) {
  798.                         return Storage.get("addonsettings/"+id);
  799.                 };
  800.                 //this.add({
  801.                 //      txt: "test",
  802.                 //      id: "test-setting",
  803.                 //      default: true
  804.                 //});
  805.                 addons.emmiter.once("interface-load", this.init);
  806.         })();
  807.  
  808.         //window constructor
  809.         this.Window = function(options) {
  810.                 //zrobiłem to zanim odkryłem że jest API.Window
  811.                 //także iksde, ale to się chyba łatwiej używa to eeee zostawie, zwłaszcza że już 1 dodatek z tym zrobiłem xDD
  812.                 /* =OPTIONS=
  813.                   WYMAGANE:
  814.                     /Jedno z dwóch:
  815.                                 -txt: zawartość HTML okna
  816.                                 -element: element do podpięcia do zawartości okna (przez $(...).append)
  817.                         /
  818.                         -header: nagłówek okna
  819.                   OPCJONALNE
  820.                         -likemAlert: bool, czy okno ma posiadać klasę mAlert (default: false)
  821.                         -noClose: bool, czy ma zostać usunięty przycisk zamykania (default: false)
  822.                         -callbacks: array, taki sam jak ma mAlert w drugim argumencie (default: [])
  823.                         -onClose: f, funkcja jaka wykona się przy zamknięciu okna (default: none)
  824.                         -css: style css które będą nadane oknu
  825.                 */
  826.                 var txt = "this will be hijacked " + new Date().getTime();
  827.                 options.callbacks = options.callbacks ? options.callbacks : [];
  828.                 mAlert(txt, options.callbacks);
  829.                 this.$ = $(".border-window:contains('"+txt+"')"); //dobra użyję jquery bo robienie tego bez przekracza moją cierpliwość
  830.  
  831.                 var $content = this.$.find(".inner-content");
  832.                 if (options.txt) $content[0].innerHTML = options.txt;
  833.                 else {
  834.                         $content[0].innerHTML = "";
  835.                         $content.append(options.element);
  836.                 };
  837.                 if (options.css) {
  838.                         Object.assign(this.$[0].style, options.css);
  839.                 }
  840.  
  841.                 var $header = this.$.find(".text");
  842.                 $header[0].innerHTML = options.header;
  843.  
  844.                 var $close = this.$.find(".close-button");
  845.                 var close = $._data($close[0], "events").click[0].handler; //kradniemy funkcję zamykającą okno
  846.                 $close[0].removeEventListener("click", close);
  847.                 if (options.noClose) $close.parent().remove();
  848.  
  849.                 if (!options.likemAlert) this.$[0].classList.remove("mAlert");
  850.  
  851.                 this.setContent = function(html) {
  852.                         $content[0].innerHTML = html;
  853.                 };
  854.                 this.setHeader = function(html) {
  855.                         $header[0].innerHTML = html;
  856.                 };
  857.                 this.appendContent = function(element) {
  858.                         $content.append(element);
  859.                 };
  860.                 this.clearContent = function() {
  861.                         $content[0].innerHTML = "";
  862.                 };
  863.                 this.close = function() {
  864.                         if (options.onClose) options.onClose();
  865.                         close();
  866.                 };
  867.                 $close[0].addEventListener("click", this.close);
  868.         };
  869.  
  870.         //widget-related functionality
  871.         this.widget = new (function(addons) {
  872.                 /*
  873.                         stored widget data (in hotWidget/widgetID/):
  874.                                 [0] - number of spaces from corner
  875.                                 [1] - corner (top-left, bottom-right etc, can also be top-left-additional)
  876.  
  877.                         widget instance:
  878.                                 name: displayed name
  879.                                 index: stored data[0]
  880.                                 corner: stored data[1]; if set to FREE empty space for the widget will be found automatically (and index parameter can be ommited)
  881.                                 id: id to be stored
  882.                                 icon: bg, in format url|bpos, e.g. http://aldous.margonem.pl/img/gui/buttony.png?v=4|-406 -12
  883.                                 clb: callback function when widget is clicked
  884.                                 color (optional): color for the widget. Can be blue, red, violet or green. Defaults to green.
  885.                                 css (optional): object with css style that will be added to the widget. Set by Object.assign and not $(...).css, so all values must be valid
  886.                 */
  887.                 var self = this,
  888.                         addedWidgets = {},
  889.                         loaded = false,
  890.                         addedWidgets2 = {};
  891.                 var dict = addons.dictionary;
  892.                 this.addWidgetData = function() {
  893.                         var widgets = self.getCustomAddonList();
  894.                         var realID;
  895.                         var style = "";
  896.                         for (var id in widgets) {
  897.                                 realID = id.substring(14, id.length);
  898.                                 if (addedWidgets[realID]) {
  899.                                         Engine.addonsPanel.addKeyToWidgets("_custom_"+realID, widgets[id], addedWidgets[realID].name);
  900.                                         style += self.getAddonStyle(addedWidgets[realID].id, addedWidgets[realID].icon);
  901.                                 } else API.Storage.remove("hotWidget/"+id);
  902.                         };
  903.                         var $style = document.createElement("style");
  904.                         $style.innerHTML = style;
  905.                         document.head.appendChild($style);
  906.                         loaded = true;
  907.                 }
  908.                 this.getCustomAddonList = function() {
  909.                         var widgets = API.Storage.get("hotWidget");
  910.                         var custom = {};
  911.                         for (var id in widgets) {
  912.                                 if (id.indexOf("_custom_") > -1) {
  913.                                         custom[id] = widgets[id];
  914.                                 }
  915.                         }
  916.                         return custom;
  917.                 }
  918.                 this.add = function(widget) {
  919.                         if (!API.Storage.get("hotWidget/addon__custom_"+widget.id)) {
  920.                                 var pos = this.generateWidgetPos(widget);
  921.                                 if (pos) API.Storage.set("hotWidget/addon__custom_"+widget.id, pos);
  922.                                 else return true;
  923.                         };
  924.                         addedWidgets[widget.id] = widget;
  925.                         window["addon__custom_"+widget.id] = {
  926.                                 manageVisible: widget.clb
  927.                         };
  928.                         return false;
  929.                 }
  930.                 this.generateWidgetPos = function(widget) {
  931.                         if (widget.corner != "FREE") return [index, corner];
  932.                         else return this.findFreeWidgetPosition();
  933.                 }
  934.                 this.findFreeWidgetPosition = function() {
  935.                         var widgets = API.Storage.get("hotWidget");
  936.                         for (var i=0; i<2; i++) {
  937.                                 var pos1 = !i ? "top" : "bottom";
  938.                                 for (var j=0; j<2; j++) {
  939.                                         var pos2 = !j ? "left" : "right";
  940.                                         for (var k=0; k<2; k++) {
  941.                                                 if (pos1 == "top" && k) continue;
  942.                                                 var additional = !k ? "" : "-additional";
  943.                                                 var fullpos = pos1+"-"+pos2+additional;
  944.                                                 for (var l=0; l<7; l++) {
  945.                                                         if (!this.checkIfWidgetExists(l, fullpos, widgets)) return [l, fullpos];
  946.                                                 };
  947.                                         }
  948.                                 }
  949.                         }
  950.                         return false;
  951.                 }
  952.                 this.checkIfWidgetExists = function(pos, corner, widgets) {
  953.                         if (!widgets) widgets = API.Storage.get("hotWidget");
  954.                         for (var i in widgets) {
  955.                                 if (widgets[i][0] == pos && widgets[i][1] == corner) return true;
  956.                         }
  957.                         return false;
  958.                 }
  959.                 this.getAddonStyle = function(id, icon) {
  960.                         return `
  961.                                 .icon.addon__custom_${id} {
  962.                                         background: ${Engine.addonsPanel.createBackgroundString(icon)} !important;
  963.                                 }
  964.                         `;
  965.                 }
  966.                 this.changeWidgetCss = function(widgets, custom) {
  967.                         //cache stuff
  968.                         if (!custom) addedWidgets2 = widgets;
  969.                         for (var id in widgets) {
  970.                                 var widget = widgets[id];
  971.                                 if (widget.color || widget.css) {
  972.                                         var $widget = document.getElementsByClassName((custom ? "addon__custom_" : "addon_")+widget.id)[0];
  973.                                         if (!$widget) continue;
  974.                                         else $widget = $widget.parentElement;
  975.                                         if (widget.color) {
  976.                                                 $widget.classList.remove("green");
  977.                                                 $widget.classList.add(widget.color);
  978.                                         }
  979.                                         if (widget.css) {
  980.                                                 Object.assign($widget.style, widget.css);
  981.                                         }
  982.                                 }
  983.                         }
  984.                 }
  985.                 this.init = function() {
  986.                         addons.emmiter.once("game-load", this.addWidgetData);
  987.                         addons.emmiter.once("interface-load", ()=>{
  988.                                 this.changeWidgetCss(addedWidgets, true);
  989.                                 var observer = new MutationObserver(this.onWidgetUpdate);
  990.                                 for (var i=0; i<2; i++) {
  991.                                         var pos1 = i ? "top" : "bottom";
  992.                                         for (var j=0; j<2; j++) {
  993.                                                 var pos2 = j ? "right" : "left";
  994.                                                 observer.observe(document.querySelector("."+pos1+"-"+pos2+".main-buttons-container"), {
  995.                                                         childList: true
  996.                                                 })
  997.                                         }
  998.                                 }
  999.                         });
  1000.                 }
  1001.                 this.onWidgetUpdate = function(mutations, observer) {
  1002.                         if (mutations.length > 1) {
  1003.                                 addons.emmiter.emit("widget-update");
  1004.                                 //readd css to widgets as they are all reset if this code runs
  1005.                                 self.changeWidgetCss(addedWidgets, true);
  1006.                                 self.changeWidgetCss(addedWidgets2);
  1007.                         };
  1008.                 }
  1009.                 this.init();
  1010.         })(this);
  1011.  
  1012.         this.addonDisplay = new (function(addons) {
  1013.                 //TODO
  1014.                 //zmienić pokazywanie ikonek i nazwy klas bo założenia się trochę zmieniły w trakcie robienia a nazwy zostały
  1015.                 var self = this,
  1016.                         list = [],
  1017.                         movedToWindow = [],
  1018.                         hidden = true,
  1019.                         $wrapper,
  1020.                         $singleWrapper,
  1021.                         $scrollWrapper,
  1022.                         $scrollContent,
  1023.                         $title,
  1024.                         currentDisplay = false;
  1025.                 this.add = function(options) {
  1026.                         if (hidden) {
  1027.                                 $wrapper.style["display"] = "block";
  1028.                                 hidden = false;
  1029.                         }
  1030.                         var $element = document.createElement("div");
  1031.                         $element.classList.add("addonDisplay-single-display")
  1032.                         if (options.html) {
  1033.                                 $element.innerHTML += options.html;
  1034.                         } else if (options.element) {
  1035.                                 $element.appendChild(options.element);
  1036.                         }
  1037.                         var $shortcut = document.createElement("div");
  1038.                         if (!options.icon) {
  1039.                                 $shortcut.innerHTML = options.name.charAt(0);
  1040.                         } else {
  1041.                                 $shortcut.innerHTML = "<img width='25px' height='25px' src='"+options.icon+"'>";
  1042.                         }
  1043.                         $shortcut.addEventListener("click", () => {
  1044.                                 this.loadDisplay(options.id);
  1045.                         });
  1046.                         $shortcut.addEventListener("contextmenu", e => {
  1047.                                 e.preventDefault();
  1048.                                 this.moveDisplayToWindow(options.id);
  1049.                         });
  1050.                         $shortcut.dataset["tip"] = options.name;
  1051.                         $scrollContent.appendChild($shortcut);
  1052.                         list.push({
  1053.                                 $: $element,
  1054.                                 $short: $shortcut,
  1055.                                 id: options.id,
  1056.                                 name: options.name,
  1057.                                 wndStyle: options.wndStyle
  1058.                         })
  1059.                 }
  1060.                 this.moveDisplayToWindow = function(id) {
  1061.                         var display = this.getDisplayById(id);
  1062.                         display.$short.style["display"] = "none";
  1063.                         if (currentDisplay == display) {
  1064.                                 //display.$.remove();
  1065.                                 //$title.innerHTML = "";
  1066.                                 //currentDisplay = false;
  1067.                                 for (var i=0; i<list.length; i++) {
  1068.                                         var disp = list[i];
  1069.                                         if (disp.id != display.id && movedToWindow.indexOf(disp.id) == -1) {
  1070.                                                 this.loadDisplay(disp.id);
  1071.                                                 break;
  1072.                                         }
  1073.                                         if (i+1 == list.length) {
  1074.                                                 currentDisplay = false;
  1075.                                         }
  1076.                                 }
  1077.                         }
  1078.                         if (movedToWindow.indexOf(id) == -1) {
  1079.                                 movedToWindow.push(id);
  1080.                                 Storage.set("addonDisplay/movedToWindow", movedToWindow);
  1081.                         }
  1082.                         if (movedToWindow.length == list.length) {
  1083.                                 hidden = true;
  1084.                                 $wrapper.style["display"] = "none";
  1085.                         }
  1086.                         this.createDisplayWindow(display);
  1087.                 }
  1088.                 this.createDisplayWindows = function() {
  1089.                         for (var i=0; i<movedToWindow.length; i++) {
  1090.                                 var display = this.getDisplayById(movedToWindow[i]);
  1091.                                 if (display) {
  1092.                                         this.moveDisplayToWindow(display.id);
  1093.                                 } else {
  1094.                                         movedToWindow.splice(i,1);
  1095.                                         i -= 1;
  1096.                                 }
  1097.                         }
  1098.                         Storage.set("addonDisplay/movedToWindow", movedToWindow);
  1099.                 }
  1100.                 this.createDisplayWindow = function(display) {
  1101.                         var hwnd = new API.Window({
  1102.                                 onclose: () => {
  1103.                                         setTimeout( ()=>this.removeDisplayWindow(display), 200);
  1104.                                         hwnd.fadeAndRemove();
  1105.                                 }
  1106.                         });
  1107.                         Object.assign(hwnd.$[0].style, {
  1108.                                 width: "241px;",
  1109.                                 height: "260px"
  1110.                         });
  1111.                         if (display.wndStyle) {
  1112.                                 Object.assign(hwnd.$[0].style, display.wndStyle);
  1113.                         }
  1114.                         hwnd.title(display.name);
  1115.                         hwnd.content(display.$);
  1116.                         hwnd.setTransparentWindon();
  1117.                         hwnd.changeDragableContainment('.game-window-positioner');
  1118.                         hwnd.setSavePosWnd("display_"+display.id, {
  1119.                                 x: '251',
  1120.                                 y: '100'
  1121.                         });
  1122.                         $('.alerts-layer').append(hwnd.$);
  1123.                         hwnd.updatePos();
  1124.                 }
  1125.                 this.removeDisplayWindow = function(display) {
  1126.                         if (movedToWindow.length == list.length) {
  1127.                                 hidden = false;
  1128.                                 $wrapper.style["display"] = "block";
  1129.                                 this.loadDisplay(display.id);
  1130.                         }
  1131.                         display.$short.style["display"] = "block";
  1132.                         movedToWindow.splice(movedToWindow.indexOf(display.id),1);
  1133.                 }
  1134.                 this.loadDefaultDisplay = function() {
  1135.                         if (!list.length) return;
  1136.                         var lastId = Storage.get("addonDisplay/active");
  1137.                         if (lastId == null) lastId = list[0].id;
  1138.                         self.loadDisplay(lastId);
  1139.                         self.createDisplayWindows();
  1140.                 }
  1141.                 this.getDisplayById = function(id) {
  1142.                         for (var i=0; i<list.length; i++) {
  1143.                                 if (list[i].id == id) return list[i];
  1144.                         }
  1145.                         return false;
  1146.                 }
  1147.                 this.loadDisplay = function(id) {
  1148.                         var display = this.getDisplayById(id);
  1149.                         if (!display) display = list[0];
  1150.                         if (currentDisplay) {
  1151.                                 $singleWrapper.removeChild(currentDisplay.$);
  1152.                                 currentDisplay.$short.classList.remove("active");
  1153.                         }
  1154.                         display.$short.classList.add("active");
  1155.                         $singleWrapper.appendChild(display.$);
  1156.                         $title.innerHTML = display.name;
  1157.                         currentDisplay = display;
  1158.                         Storage.set("addonDisplay/active", id);
  1159.                         addons.emmiter.emit("display-load-"+id);
  1160.                 }
  1161.                 this.tutorial = function() {
  1162.                         if (Storage.get("addonDisplay/tutorial") || list.length == 0) return;
  1163.                         new addons.Window({
  1164.                                 header: "Tutorial",
  1165.                                 txt: _l() == "pl" ?
  1166.                                 "Wygląda na to, że zainstalowałeś dodatek wykorzystujący mechanikę pokazywania rzeczy pod torbami. Kilka informacji:<br>-na dole są ikonki dodatków korzystających z tej machaniki. Klikając je można się między nimi przełączać.<br>-kliknięcie ikonki prawym przyciskiem myszy spowoduje przeniesienie dodatku spod toreb do oddzielnego okienka, któte można dowolnie przesuwać." :
  1167.                                 "It appears that you've installed an addon that uses the mechanic of showing stuff under the bags. Some information:<br>-on the bottom, there are icons of addons using said mechanic. You can switch between addons by clicking these.<br>-by right clicking an icon you can move addon display to a separate window, which can be moved around freely.",
  1168.                                 css: {
  1169.                                         "max-width": "350px"
  1170.                                 }
  1171.                         })
  1172.                         Storage.set("addonDisplay/tutorial", true);
  1173.                 }
  1174.                 this.init = function() {
  1175.                         if (typeof Storage.get("addonDisplay") != "object") {
  1176.                                 Storage.set("addonDisplay", {});
  1177.                         }
  1178.                         var moved = Storage.get("addonDisplay/movedToWindow")
  1179.                         if (moved) movedToWindow = moved;
  1180.                         $wrapper = document.getElementById("b_wrapper");
  1181.                         $wrapper.innerHTML = "";
  1182.  
  1183.                         $title = document.createElement("div");
  1184.                         $title.classList.add("addonDisplay-header");
  1185.                         $wrapper.appendChild($title);
  1186.  
  1187.                         $singleWrapper = document.createElement("div");
  1188.                         $singleWrapper.classList.add("addonDisplay-single-wrapper");
  1189.                         $wrapper.appendChild($singleWrapper);
  1190.  
  1191.                         $scrollWrapper = document.createElement("div");
  1192.                         $scrollWrapper.classList.add("addonDisplay-scroll-wrapper");
  1193.                         $scrollContent = document.createElement("div");
  1194.                         $scrollContent.classList.add("addonDisplay-scroll-content");
  1195.                         $scrollWrapper.appendChild($scrollContent);
  1196.                         $wrapper.appendChild($scrollWrapper);
  1197.  
  1198.                         var style = `
  1199.                                 #b_wrapper {
  1200.                                         width: 241px;
  1201.                                         display: none;
  1202.                                         background: rgba(0,0,0,0.3);
  1203.                                         color: white;
  1204.                                         margin-left: 10px;
  1205.                                 }
  1206.                                 .addonDisplay-single-wrapper {
  1207.                                         overflow: hidden;
  1208.                                         width: 100%;
  1209.                                         height: 260px;
  1210.                                         padding: 5px;
  1211.                                 }
  1212.                                 .addonDisplay-single-display {
  1213.                                         color: white;
  1214.                                         width: 100%;
  1215.                                         overflow-y: scroll;
  1216.                                         overflow-x: hidden;
  1217.                                         height: 260px;
  1218.                                         padding-right: 17px;
  1219.                                         margin-top: 4px;
  1220.                                 }
  1221.                                 .addonDisplay-header {
  1222.                                         border-bottom: 1px gray dashed;
  1223.                                         font-size: 125%;
  1224.                                         padding: 5px;
  1225.                                 }
  1226.                                 .addonDisplay-scroll-wrapper {
  1227.                                         width: 100%;
  1228.                                         height: 27px;
  1229.                                         margin-top: 5px;
  1230.                                         border-top: 1px gray dashed;
  1231.                                 }
  1232.                                 .addonDisplay-scroll-content > div {
  1233.                                         float: left;
  1234.                                         width: 24.5px;
  1235.                                         height: 25px;
  1236.                                         line-height: 25px;
  1237.                                         font-size: 110%;
  1238.                                         text-align: center;
  1239.                                         border: 1px solid black;
  1240.                                         border-collapse: collapse;
  1241.                                         background: rgba(0,0,0,0.08);
  1242.                                         cursor: url(http://aldous.margonem.pl/img/gui/cursor/5.png), auto;;
  1243.                                         transition: background .1s ease-in-out;
  1244.                                 }
  1245.                                 .addonDisplay-scroll-content > div:hover {
  1246.                                         background: rgba(55,55,55,0.47);
  1247.                                 }
  1248.                                 .addonDisplay-scroll-content > div.active {
  1249.                                         background: rgba(70,70,70,0.47);
  1250.                                 }
  1251.                         `;
  1252.                         var $style = document.createElement("style");
  1253.                         $style.innerHTML = style;
  1254.                         document.head.appendChild($style);
  1255.  
  1256.                         addons.emmiter.once("game-load", this.loadDefaultDisplay);
  1257.                         addons.emmiter.once("interface-load", this.tutorial);
  1258.                 }
  1259.                 this.init();
  1260.         })(this);
  1261.         this.cursors = {
  1262.                 default: "url(http://aldous.margonem.pl/img/gui/cursor/1.png), auto",
  1263.                 npctalk: "url(http://aldous.margonem.pl/img/gui/cursor/2.png), auto",
  1264.                 fight: "url(http://aldous.margonem.pl/img/gui/cursor/3.png), auto",
  1265.                 grab: "url(http://aldous.margonem.pl/img/gui/cursor/4.png), auto",
  1266.                 pointer: "url(http://aldous.margonem.pl/img/gui/cursor/5.png), auto"
  1267.         }
  1268. })();