hwmSetsMaster

Меню наборов армии, навыков и оружия. Смена фракции.

当前为 2024-11-29 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name hwmSetsMaster
  3. // @author Tamozhnya1
  4. // @namespace Tamozhnya1
  5. // @description Меню наборов армии, навыков и оружия. Смена фракции.
  6. // @version 12.5
  7. // @include *heroeswm.ru/*
  8. // @include *lordswm.com/*
  9. // @exclude */rightcol.php*
  10. // @exclude */ch_box.php*
  11. // @exclude */chat*
  12. // @exclude */ticker.html*
  13. // @exclude */frames*
  14. // @exclude */brd.php*
  15. // @require https://update.greasyfork.org/scripts/490927/1360667/Tamozhnya1Lib.js
  16. // @grant GM_getValue
  17. // @grant GM_setValue
  18. // @grant GM_deleteValue
  19. // @grant GM.xmlHttpRequest
  20. // @license MIT
  21. // ==/UserScript==
  22.  
  23. if(!PlayerId) {
  24. return;
  25. }
  26. const Strings = {
  27. "ru": {
  28. Army: "Армия",
  29. Save: "Сохранить",
  30. Add: "Добавить",
  31. AddCurrent: "Добавить текущий",
  32. SetName: "Наименование набора",
  33. Delete: "Удалить",
  34. Talents: "Навыки",
  35. Inventory: "Оружие",
  36. RemoveAll: "Снять все",
  37. EnterJpg: "enter0.jpg",
  38. SignInTitle: "Войти",
  39. Castle: "Замок",
  40. Task: "Задание",
  41. Apply: "Применить",
  42. AvailablePoints: "Свободных очков",
  43. AvailableTalentPoints: "Свободных очков от навыка",
  44. IncreaseManyPointsTooltip: "Введите число от ${minValue} до ${maxValue}. Нажмите Tab."
  45. },
  46. "en": {
  47. Army: "Army",
  48. Save: "Save",
  49. Add: "Add",
  50. AddCurrent: "Add current",
  51. SetName: "Set name",
  52. Delete: "Delete",
  53. Talents: "Talents",
  54. Inventory: "Inventory",
  55. RemoveAll: "Un-equip all",
  56. EnterJpg: "enter0_eng.jpg",
  57. SignInTitle: "Sign in",
  58. Castle: "Castle",
  59. Task: "Task",
  60. Apply: "Apply",
  61. AvailablePoints: "Available points",
  62. AvailableTalentPoints: "Available talent points",
  63. IncreaseManyPointsTooltip: "Enter number from ${minValue} to ${maxValue}. Press Tab."
  64. }
  65. };
  66. const LocalizedString = Strings[lang];
  67. let Fraction;
  68. getFraction();
  69.  
  70. //const homeArtsPanelSelector = doc => isNewPersonPage ? doc.querySelector("div#inv_doll_stats") : getParent(doc.querySelector("div.arts_info.shop_art_info"), "table");
  71. const homeArtsPanelSelector = doc => isNewPersonPage ? doc.querySelector("div#inv_doll_stats") : doc.querySelector("body > center table.wb > tbody > tr:nth-child(3) > td > table:nth-child(2)");
  72. const homeStatsPanelSelector = doc => isNewPersonPage ? doc.getElementById("home_css_stats_wrap_div") : getParent(doc.querySelector("img[src*='attr_attack']"), "table", 2);
  73. const homeArmyPanelSelector = doc => isNewPersonPage ? doc.querySelector("div.home_pers_army") : doc.querySelector("center > div > div.cre_creature72").parentNode;
  74. const playerInfoArtsPanelSelector = doc => getParent(doc.querySelector("div[class^='slot']"), "div");
  75. const playerInfoStatsPanelSelector = doc => getParent(doc.querySelector("img[src*='attr_attack']"), "table");
  76. const playerInfoArmyPanelSelector = doc => doc.querySelector("center > div > div.cre_creature72").parentNode;
  77. const playerInfoPerksPanelSelector = doc => getParent(doc.querySelector("a[href^='showperkinfo.php']"), "table", 2);
  78. const mapHuntButtonsPanelSelector = doc => doc.querySelector("div#neut_right_block div.map_buttons_container");
  79. const mapHuntButtons2PanelSelector = doc => doc.querySelector("div#neut_right_block2 div.map_buttons_container");
  80. const mapMercenaryTaskPanelSelector = doc => getParent(doc.querySelector("div#map_right_block_inside > table.wbwhite.rounded_table.map_table_margin center a[href='mercenary_guild.php']"), "center");
  81. const inventoryStatsPanelSelector = doc => doc.querySelector("div.inventory_stats");
  82. const resourcesPath = `${location.protocol}//${location.host.replace("www", "dcdn")}`;
  83.  
  84. /************************************************************************************************************/
  85. const weaponSetsPreferences = {
  86. menuTitle: LocalizedString.Inventory,
  87. menuImage: `${resourcesPath}/i/combat/btn_inventory.png?v=7`,
  88. setReferencePage: "inventory.php",
  89. sets: new Array(),
  90. menuItems: {},
  91. currentMenuItem: undefined,
  92. initSetsApplyAction: function() {
  93. this.sets.length = 0;
  94. this.sets.push({ number: 0, name: LocalizedString.RemoveAll, method: "GET", url: "/inventory.php?all_off=100" });
  95. const weaponSets = JSON.parse(getPlayerValue("WeaponSets", "{}"));
  96. for(const setNumber in weaponSets) {
  97. this.sets.push({ number: setNumber, name: weaponSets[setNumber], method: "GET", url: `/inventory.php?all_on=${setNumber}` });
  98. }
  99. },
  100. name: "WeaponSet",
  101. getCurrentSetName: function() { return "WeaponSet"; },
  102. onPageLoad: function() {
  103. if(/inventory.php/.test(location.href)) {
  104. const undressDiv = document.querySelector("div[id ='undress_all_div']");
  105. addSetChangerListener(undressDiv, this, 0);
  106.  
  107. const setDivs = document.querySelectorAll("div[set_div_id]"); // Если setDivs.length = 0, то ничего не делаем - мы в заявке на бой
  108. if(setDivs.length > 0) {
  109. const weaponSets = {};
  110. for(const setDiv of setDivs) {
  111. const setNumber = setDiv.getAttribute("set_div_id");
  112. if(setDiv.hasAttribute("onclick")) {
  113. weaponSets[setNumber] = setDiv.innerText;
  114. addSetChangerListener(setDiv, this, setNumber);
  115. }
  116. }
  117. setPlayerValue("WeaponSets", JSON.stringify(weaponSets));
  118. }
  119. }
  120. this.findSetChangersAndAddListener();
  121. },
  122. findSetChangersAndAddListener: function() {
  123. let setRefs = document.querySelectorAll("a[href^='inventory.php?all_off=100']");
  124. for(const setRef of setRefs) {
  125. addSetChangerListener(setRef, this, 0);
  126. }
  127. setRefs = document.querySelectorAll("a[href*='inventory.php?all_on=']");
  128. for(const weaponSetReference of setRefs) {
  129. let setNumber = weaponSetReference.getAttribute("href").split("all_on=")[1];
  130. addSetChangerListener(weaponSetReference, this, setNumber);
  131. }
  132. }
  133. };
  134. /***********************************************************************************************************/
  135. const skillSetsPreferences = {
  136. menuTitle: LocalizedString.Talents,
  137. menuImage: `${resourcesPath}/i/combat/btn_skills_v3.png?v=7`,
  138. setReferencePage: "skillwheel.php",
  139. sets: new Array(),
  140. menuItems: {},
  141. currentMenuItem: undefined,
  142. onPageLoad: function() {
  143. const setRefs = document.querySelectorAll("a[href^='skillwheel.php?setuserperk']"); // skillwheel.php?setuserperk=1&prace=4&buildid=5 // skillwheel.php?rand=1&setstats=1&param0=20&param1=8&param2=0&param3=2
  144. const pageSets = {};
  145. for(const setRef of setRefs) {
  146. pageSets[setRef.innerHTML] = getUrlParamValue(setRef.href, "buildid");
  147. addSetChangerListener(setRef, this, parseInt(getUrlParamValue(setRef.href, "buildid")));
  148. }
  149. setPlayerFractionValue("SkillSets", JSON.stringify(pageSets));
  150. },
  151. initSetsApplyAction: function () {
  152. const skillSets = JSON.parse(getPlayerFractionValue("SkillSets", "{}"));
  153. this.sets = Object.keys(skillSets).map(x => { return { number: parseInt(skillSets[x]), name: x, method: "GET", url: `/skillwheel.php?setuserperk=1&prace=${Fraction}&buildid=${skillSets[x]}` }; });
  154. },
  155. name: "SkillSet",
  156. getCurrentSetName: function() { return getFractionKey("SkillSet"); },
  157. };
  158. /************************************************************************************************************/
  159. const armySetsPreferences = {
  160. menuTitle: LocalizedString.Army,
  161. menuImage: `${resourcesPath}/i/castle_im/btn_recruit.png`,
  162. setReferencePage: "army.php",
  163. sets: new Array(),
  164. menuItems: {},
  165. currentMenuItem: undefined,
  166. setsTable: null,
  167. name: "ArmySet",
  168. getCurrentSetName: function() { return getFractionKey("ArmySet"); },
  169. initSetsApplyAction: function () {
  170. const armySetsData = JSON.parse(getPlayerFractionValue("ArmySets", "{}"));
  171. const armySets = Object.keys(armySetsData).map(x => { const data = armySetsData[x].split("|"); return { Id: x, Name: data[0], Army: data.slice(1).map(y => Number(y)) } });
  172. this.sets = armySets.map(x => { return { number: parseInt(x.Id), name: x.Name, title: x.Army.join("+"), method: "POST", url: "/army_apply.php", data: "set_id=7&" + x.Army.map((x, i) => `countv${i + 1}=${x}`).join("&") }; });
  173. if(/\/army.php/.test(location.href)) {
  174. this.drawSetsTable(armySets);
  175. }
  176. },
  177. drawSetsTable: function(armySets) {
  178. const isInit = this.setsTable ? false : true;
  179. let container;
  180. if(isInit) {
  181. const hwm_for_zoom = document.getElementById("hwm_for_zoom") || document.getElementById("hwm_no_zoom");
  182. container = document.body;
  183. if(!isMobileInterface) {
  184. container = addElement("center", null, hwm_for_zoom);
  185. }
  186. this.setsTable = addElement("table", { class: "smithTable", style: `${isMobileInterface ? "margin-left: px;" : ""}` }, container);
  187. } else {
  188. this.setsTable.innerHTML = "";
  189. container = this.setsTable.parentNode;
  190. }
  191.  
  192. const cellWidths = [100, 60, 60, 60, 60, 60, 60, 60, 10, 10];
  193. for(const cellWidth of cellWidths) {
  194. this.setsTable.innerHTML += `<col style="width: ${cellWidth}px;" />`;
  195. }
  196. this.drawTableHeader();
  197. for(const armySet of armySets) {
  198. this.drawSetRow(armySet);
  199. }
  200. if(isInit) {
  201. const saveButton = addElement("input", { type: "button", value: LocalizedString.Save, class: "button-62", style: isMobileInterface ? "margin: 0 0 0 50px;" : "" }, container);
  202. saveButton.addEventListener("click", this.saveSets);
  203. const addCurrentButton = addElement("input", { type: "button", value: LocalizedString.AddCurrent, class: "button-62" }, container);
  204. addCurrentButton.addEventListener("click", function() { armySetsPreferences.drawSetRow(); });
  205. }
  206. },
  207. drawTableHeader: function () {
  208. if(!this.setsTable) {
  209. return;
  210. }
  211. const units = win.obj;
  212. //console.log(units)
  213. const tr = addElement("tr", null, this.setsTable);
  214. addElement("th", { innerHTML: LocalizedString.SetName.replace(/ /g, "<br>").replace(/-/g, "-<br>") }, tr);
  215. for(let i = 1; i <= 7; i++) {
  216. addElement("th", { innerHTML: (units[i]?.name || "").replace(/ /g, "<br>").replace(/-/g, "-<br>"), onClick: `ChangeSlider(event, ${i}, 0);` }, tr);
  217. }
  218. addElement("th", { style: "width: 30px;" }, tr);
  219. addElement("th", { style: "width: 30px;" }, tr);
  220. },
  221. drawSetRow: function(armySet) {
  222. const isNew = armySet ? false : true;
  223. const units = win.obj;
  224. //console.log(`armySet: ${armySet}, units: ${units}`);
  225. //console.log(units.slice(1));
  226. armySet = armySet || { Id: (new Date()).getTime(), Name: "", Army: [units[1], units[2], units[3], units[4], units[5], units[6], units[7]].map(x => x?.nownumberd || 0) };
  227. if(!this.setsTable) {
  228. return;
  229. }
  230. const tr = addElement("tr", { setId: armySet.Id }, this.setsTable);
  231. let td = addElement("td", {}, tr);
  232. let input = addElement("input", { value: armySet.Name, onfocus: `this.select();`, style: "width: 100%;" }, td);
  233. for(let i = 0; i < armySet.Army.length; i++) {
  234. td = addElement("td", {}, tr);
  235. input = addElement("input", { value: armySet.Army[i], onfocus: `ChangeSlider(event, ${i + 1}, 0); this.select();`, type: "number", style: "min-width: 47px; width: 100%; text-align: right;" }, td);
  236. }
  237. td = addElement("td", {}, tr);
  238. let delButton = addElement("input", { type: "button", value: "x", class: "button-62", style: "width: 100%;", title: LocalizedString.Delete }, td);
  239. delButton.addEventListener("click", this.deleteSet);
  240.  
  241. td = addElement("td", {}, tr);
  242. if(!isNew) {
  243. let applyButton = addElement("input", { type : "button", value : "v", class: "button-62", style: "width: 100%;", title : LocalizedString.Apply }, td);
  244. applyButton.addEventListener("click", function() {
  245. armySetsPreferences.saveSets();
  246. const data = armySet.Army.reduce((x, y, i) => `${x}&countv${i + 1}=${y}`, "set_id=7");
  247. //console.log(data);
  248. applySet(null, armySetsPreferences, {
  249. number: parseInt(armySet.Id),
  250. name: armySet.Name,
  251. title: armySet.Army.join("+"),
  252. method: "POST", url: "/army_apply.php",
  253. data: data
  254. });
  255. });
  256. }
  257. },
  258. saveSets: function () {
  259. const rows = Array.from(armySetsPreferences.setsTable.rows).slice(1);
  260. const armySetsData = rows.reduce((t, x) => ({ ...t, [x.getAttribute("setId")]: Array.from(x.cells).slice(0, 8).map(y => y.firstChild.value).join("|") }), {});
  261. setPlayerFractionValue("ArmySets", JSON.stringify(armySetsData));
  262. },
  263. deleteSet: function () {
  264. const table = this.parentNode.parentNode.parentNode;
  265. const row = this.parentNode.parentNode;
  266. table.removeChild(row);
  267. },
  268. };
  269. /************************************************************************************************************/
  270. const fractionsPreferences = {
  271. menuTitle: LocalizedString.Castle,
  272. menuImage: `${resourcesPath}/i/castle_im/btn_fraction.png`,
  273. setReferencePage: "castle.php",
  274. sets: [],
  275. menuItems: {},
  276. currentMenuItem: undefined,
  277. initSetsApplyAction: function() {
  278. const fractions = JSON.parse(getPlayerValue("Fractions", "{}"));
  279. this.sets = Object.keys(fractions).map(x => { return { number: fractions[x], name: x, method: "GET", url: `/castle.php?change_clr_to=${fractions[x]}&sign=${getPlayerValue("Sign")}` }; });
  280. },
  281. name: "Fraction",
  282. getCurrentSetName: function() { return "Fraction"; },
  283. onPageLoad: async function () {
  284. await this.initCastlesList();
  285. this.findSetChangersAndAddListener();
  286. },
  287. initCastlesList: async function () {
  288. if(location.pathname == '/castle.php' || !getPlayerValue("Fractions")) {
  289. const doc = location.pathname == '/castle.php' ? document : await getRequest("/castle.php");
  290. const fractions = Array.from(doc.querySelectorAll("div.castle_faction_div_inside")).reduce((t, x) => ({...t, [x.getAttribute("hint")]: getUrlParamValue(x.firstChild.href, "show_castle_f") }), {});
  291. setPlayerValue("Fractions", JSON.stringify(fractions));
  292. const changeCastleRef = doc.querySelector("div.castle_yes_no_dialog a[href*='castle.php?change_clr_to']");
  293. if(changeCastleRef) {
  294. setPlayerValue("Sign", getUrlParamValue(changeCastleRef.href, "sign"));
  295. }
  296. }
  297. },
  298. findSetChangersAndAddListener: function() {
  299. const setRefs = document.querySelectorAll("a[href*='castle.php?change_clr_to']");
  300. for(const setRef of setRefs) {
  301. addSetChangerListener(setRef, this, getUrlParamValue(setRef.href, "change_clr_to"));
  302. }
  303. },
  304. setChanged: function(newSetNumber) {
  305. Fraction = newSetNumber;
  306. setPlayerValue("Fraction", Fraction);
  307. createMenu();
  308. }
  309. };
  310.  
  311. /************************************************************************************************************/
  312. const preferences = [weaponSetsPreferences, skillSetsPreferences, armySetsPreferences, fractionsPreferences];
  313. const visibleMunuItems = [[], [], [], []];
  314. const dropdownPositions = { bottom: 1, right: 2 };
  315. main();
  316. function main() {
  317. if(isHeartOnPage && Fraction) {
  318. addStyle(`
  319. .button-62 {
  320. background: linear-gradient(to bottom right, #E47B8E, #FF9A5A);
  321. border: 0;
  322. border-radius: 5px;
  323. color: #FFFFFF;
  324. cursor: pointer;
  325. display: inline-block;
  326. font-family: -apple-system,system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  327. font-size: 16px;
  328. font-weight: 500;
  329. outline: transparent;
  330. padding: 0 5px;
  331. text-align: center;
  332. text-decoration: none;
  333. transition: box-shadow .2s ease-in-out;
  334. user-select: none;
  335. -webkit-user-select: none;
  336. touch-action: manipulation;
  337. white-space: nowrap;
  338. }
  339.  
  340. .button-62:not([disabled]):focus {
  341. box-shadow: 0 0 .25rem rgba(0, 0, 0, 0.5), -.125rem -.125rem 1rem rgba(239, 71, 101, 0.5), .125rem .125rem 1rem rgba(255, 154, 90, 0.5);
  342. }
  343.  
  344. .button-62:not([disabled]):hover {
  345. box-shadow: 0 0 .25rem rgba(0, 0, 0, 0.5), -.125rem -.125rem 1rem rgba(239, 71, 101, 0.5), .125rem .125rem 1rem rgba(255, 154, 90, 0.5);
  346. }
  347. .button-62:disabled,button[disabled] {
  348. background: linear-gradient(177.9deg, rgb(58, 62, 88) 3.6%, rgb(119, 127, 148) 105.8%);
  349. }
  350. table.smithTable {
  351. width: 100%;
  352. background: BurlyWood;
  353. border: 5px solid BurlyWood;
  354. border-radius: 5px;
  355. margin-top: 1px;
  356. }
  357. table.smithTable th {
  358. border: 1px none #f5c137;
  359. overflow: hidden;
  360. text-align: center;
  361. font-size: 11px;
  362. }
  363. table.smithTable td {
  364. border: 1px none #f5c137;
  365. overflow: hidden;
  366. text-align: center;
  367. }
  368. table.smithTable tr:nth-child(odd) {
  369. background: Wheat;
  370. }
  371. table.smithTable tr:nth-child(even) {
  372. background: white;
  373. }
  374. .waiting {
  375. cursor: wait;
  376. }
  377. .not-allowed {
  378. cursor: not-allowed;
  379. }
  380. `);
  381. update();
  382. for(const preference of preferences) {
  383. if(preference.onPageLoad) {
  384. preference.onPageLoad();
  385. }
  386. }
  387. createMenu();
  388. window.addEventListener("resize", function() { createMenu(true); });
  389. drowSkillChangers();
  390. if(location.pathname == '/home.php' && isNewPersonPage) {
  391. observe(document.querySelector("div#home_css_stats_wrap_div"), drowSkillChangers);
  392. }
  393. }
  394. }
  395. function update() {
  396. const fractionNumbers = [1, 101, 2, 102, 3, 103, 4, 104, 5, 105, 205, 6, 106, 7, 107, 8, 108, 9, 10];
  397. for(const fractionNumber of fractionNumbers) {
  398. //deletePlayerFractionValue("SkillSets", fractionNumber);
  399. const skillSetsOld = getValue(`SkillSets${PlayerId}Fraction${fractionNumber}`);
  400. const skillSets = getPlayerFractionValue("SkillSets", undefined, fractionNumber);
  401. // if(fractionNumber == 8) {
  402. // console.log(`fractionNumber: ${fractionNumber}, skillSetsOld: ${skillSetsOld}, skillSets: ${skillSets}, CurrentSkillSet: ${getValue(`CurrentSkillSet${PlayerId}Fraction${fractionNumber}`)}`);
  403. // }
  404. if(skillSetsOld && !skillSets) {
  405. setPlayerFractionValue("SkillSets", skillSetsOld, fractionNumber);
  406. setPlayerFractionValue("SkillSet", getValue(`CurrentSkillSet${PlayerId}Fraction${fractionNumber}`), fractionNumber);
  407. }
  408. //deletePlayerFractionValue("ArmySets", fractionNumber);
  409. const armySetsOld = getValue(`ArmySets${PlayerId}Fraction${fractionNumber}`);
  410. const armySets = getPlayerFractionValue("ArmySets", undefined, fractionNumber);
  411. // if(fractionNumber == 8) {
  412. // console.log(`fractionNumber: ${fractionNumber}, armySetsOld: ${armySetsOld}, armySets: ${armySets}, ArmySet: ${getValue(`ArmySet${PlayerId}Fraction${fractionNumber}`)}`);
  413. // }
  414. if(armySetsOld && !armySets) {
  415. setPlayerFractionValue("ArmySets", armySetsOld, fractionNumber);
  416. setPlayerFractionValue("ArmySet", getValue(`ArmySet${PlayerId}Fraction${fractionNumber}`), fractionNumber);
  417. }
  418. // if(fractionNumber == 8) {
  419. // console.log(`ArmySet: ${getPlayerFractionValue("ArmySet", undefined, fractionNumber)}`);
  420. // }
  421. }
  422. }
  423. function getTextWidth(text, font) {
  424. const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas")); // re-use canvas object for better performance
  425. const context = canvas.getContext("2d");
  426. context.font = font;
  427. const metrics = context.measureText(text);
  428. return metrics.width;
  429. }
  430. function getCssStyle(element, prop) { return window.getComputedStyle(element, null).getPropertyValue(prop); }
  431. function getCanvasFont(el = document.body) {
  432. const fontWeight = getCssStyle(el, 'font-weight') || 'normal';
  433. const fontSize = getCssStyle(el, 'font-size') || '16px';
  434. const fontFamily = getCssStyle(el, 'font-family') || 'Times New Roman';
  435. return `${fontWeight} ${fontSize} ${fontFamily}`;
  436. }
  437. function getOrCreateAndResizeDropdown(branchIndex, baseElement, style, dropdownPosition = dropdownPositions.bottom) {
  438. const dropdownId = `${baseElement.id}Dropdown`;
  439. let dropdown = document.getElementById(dropdownId);
  440. if(!dropdown) {
  441. const baseElementRect = baseElement.getBoundingClientRect();
  442. let top = baseElementRect.height - 1;
  443. let left = 0;
  444. if(dropdownPosition == dropdownPositions.right) {
  445. top = 0;
  446. left = baseElementRect.width;
  447. }
  448. dropdown = addElement("div", { id: dropdownId, style: `position: absolute; box-shadow: 3px 3px 5px #333; top: ${top}px; left: ${left}px;` + (style || "") }, baseElement);
  449. if(isMobileDevice) {
  450. baseElement.addEventListener("click", function() {
  451. dropdown.style.display = dropdown.style.display == "none" ? "block" : "none";
  452. if(dropdown.style.display == "block") {
  453. const dropdowns = document.querySelectorAll("div[id$=Dropdown]");
  454. for(const dropdown of dropdowns) {
  455. if(dropdown.id != dropdownId) {
  456. dropdown.style.display = "none";
  457. }
  458. }
  459. }
  460. });
  461. } else {
  462. let hideTimer;
  463. const dropdownTimeout = 100;
  464. baseElement.addEventListener("mouseenter", function() { clearTimeout(hideTimer); if(dropdown.style.display == "none") { setTimeout(function() { dropdown.style.display = "block"; }, dropdownTimeout); } });
  465. baseElement.addEventListener("mouseleave", function() { hideTimer = setTimeout(function() { dropdown.style.display = "none"; }, dropdownTimeout); });
  466. }
  467. }
  468. return dropdown;
  469. }
  470. function createMenu(isResize) {
  471. const menuPanel = document.querySelector("div#hwm_header") || document.querySelector("#main_top_table") || document.querySelector("body > table");
  472. if(!menuPanel) {
  473. armySetsPreferences.initSetsApplyAction();
  474. return;
  475. }
  476. const setsMenuPosition = getPlayerBool("ShowMenyAtRight") ? "right" : "left"; //const setsMenuPosition = isNewInterface && isMobileDevice || getPlayerBool("ShowMenyAtRight") ? "right" : "left";
  477. const homeRef = menuPanel.querySelector("a[href='home.php']");
  478. const framesRef = menuPanel.querySelector("a[href='frames.php']");
  479. const menuAnchor = setsMenuPosition == "left" ? (isNewInterface ? homeRef.parentNode : getParent(homeRef, "td", 3)) : (isNewInterface ? framesRef.parentNode : getParent(framesRef, "td", 3));
  480. if(!menuAnchor) {
  481. return;
  482. }
  483. const superSets = JSON.parse(getPlayerValue("SuperSets", "[]"));
  484. const anchorRect = menuAnchor.getBoundingClientRect();
  485. //console.log(anchorRect);
  486. const borderWidth = isNewInterface ? 1 : 2;
  487. const menuItemHeight = anchorRect.height - borderWidth * 2;
  488. const menuItemLineHeight = menuItemHeight - borderWidth;
  489. const menuItemTop = anchorRect.top + window.scrollY;
  490. const foreColor = "#f5c137";
  491. const backgroundColor = isNewInterface ? "linear-gradient(to top, #09203f 0%, #537895 100%)" : (document.querySelector("img[src*='i/top_ny']") ? "#003399" : "#6b6b69");
  492. const zIndex = location.pathname == "/photo_pl_photos.php" ? "0" : "100";
  493. let currentMenuItemLeft = setsMenuPosition == "left" ? (anchorRect.left - borderWidth - 1) : (anchorRect.right + borderWidth + 1);
  494. let previousWidth = 0;
  495. for(let i = preferences.length - 1; i >= 0; i--) {
  496. const currentPreferences = preferences[i];
  497. const mainMenuItemId = `SetsMenuItem${i}`;
  498. let mainMenuItem = document.getElementById(mainMenuItemId);
  499. let selectedValueHidden = document.getElementById(`hwmSetsMaster${currentPreferences.name}SelectedValue`);
  500. if(!mainMenuItem) {
  501. const menuHeaderStyle = `min-width: ${menuItemHeight}px; font-size: 9pt; position: absolute; border-radius: 5px; background: ${backgroundColor}; color: ${foreColor}; border: ${borderWidth}px solid ${foreColor}; padding: 0 3px 0 3px; font-weight: bold; text-align: center; z-index: ${zIndex};`;
  502. mainMenuItem = addElement("div", { id: mainMenuItemId, style: menuHeaderStyle }, document.body);
  503. let itemContent = currentPreferences.menuTitle;
  504. let itemTitle = "";
  505. if(currentPreferences.menuImage && isNewInterface) {
  506. itemTitle = currentPreferences.menuTitle;
  507. itemContent = `<img src="${currentPreferences.menuImage}" alt="${itemTitle}" style="height: 90%; margin-top: 2px; border-radius: 50%;">`;
  508. }
  509. let itemChild;
  510. if(isMobileDevice) {
  511. itemChild = addElement("span", { innerHTML: itemContent, style: `color: ${foreColor}; text-decoration: none;` }, mainMenuItem);
  512. } else {
  513. itemChild = addElement("a", { innerHTML: itemContent, href: currentPreferences.setReferencePage, style: `color: ${foreColor}; text-decoration: none; vertical-align: middle;` }, mainMenuItem);
  514. }
  515. if(itemTitle != "") {
  516. itemChild.title = itemTitle;
  517. }
  518. selectedValueHidden = addElement("div", { id: `hwmSetsMaster${currentPreferences.name}SelectedValue`, hidden: "hidden" }, mainMenuItem);
  519. if(i == 3) {
  520. createBuildButton();
  521. }
  522. visibleMunuItems[i] = [mainMenuItem];
  523. }
  524. mainMenuItem.style.height = `${menuItemHeight}px`;
  525. mainMenuItem.style.lineHeight = `${menuItemLineHeight}px`;
  526. mainMenuItem.style.top = `${menuItemTop}px`;
  527. const mainMenuItemRect = mainMenuItem.getBoundingClientRect();
  528. currentMenuItemLeft = currentMenuItemLeft + (setsMenuPosition == "left" ? (- mainMenuItemRect.width) : previousWidth);
  529. previousWidth = mainMenuItemRect.width;
  530. mainMenuItem.style.left = `${currentMenuItemLeft}px`;
  531.  
  532. const menuContent = getOrCreateAndResizeDropdown(i, mainMenuItem, ` z-index: ${zIndex}; list-style-position: inside; color: ${foreColor}; padding: 2px 3px 2px 3px; white-space: nowrap; background: ${backgroundColor}; line-height: normal;`);
  533. if(isResize) {
  534. continue;
  535. }
  536. currentPreferences.initSetsApplyAction();
  537. menuContent.style.display = "block"; // Перед заполнением покажем див для правильного определения его размеров (нужно, если он установлен в none)
  538. menuContent.innerHTML = '';
  539. const currentSetNumber = getPlayerValue(currentPreferences.getCurrentSetName(), -1);
  540. let maxClientWidth = menuContent.clientWidth;
  541. for(const currentSet of currentPreferences.sets) {
  542. const dropDownMenuItem = addElement("li", { type: "disc", style: "text-align: left;" }, menuContent);
  543. const currentSetReference = addElement("b", { id: `${currentPreferences.getCurrentSetName()}SetReference${currentSet.number}`, innerHTML: currentSet.name, title: currentSet.title || "", style: `color: ${foreColor}; cursor: pointer; position: relative;` }, dropDownMenuItem);
  544. if(currentSet.url) {
  545. currentSetReference.addEventListener("click", function() { applySet(currentSetReference, currentPreferences, currentSet); });
  546. }
  547. if(currentSet.number == currentSetNumber) {
  548. selectedValueHidden.innerHTML = currentSet.number;
  549. markCurrent(currentSetReference, currentPreferences, currentSet.number);
  550. }
  551. currentPreferences.menuItems[currentSet.number] = currentSetReference;
  552.  
  553. if(i == 3) {
  554. const fractionBuilds = superSets.filter(x => x.Fraction == currentSet.number);
  555. if(fractionBuilds.length > 0) {
  556. const superDropdown = getOrCreateAndResizeDropdown(i, currentSetReference, ` z-index: ${Number(zIndex) + 1}; list-style-position: inside; color: ${foreColor}; padding: 2px 3px 2px 3px; white-space: nowrap; background: ${backgroundColor};`, dropdownPositions.right);
  557. for(const build of fractionBuilds) {
  558. const superDropdownMenuItem = addElement("li", { type: "disc", style: "text-align: left;" }, superDropdown);
  559. const html = `${build.Name} <span id="deleteSuperSet${build.Id}Button" title='${isEn ? "Delete" : "Удалить"}' style="cursor: pointer; display: inline; color: yellow;">&times;</span>`
  560. const superDropdownText = addElement("b", { name: "superDropdownText", innerHTML: html, style: `color: ${foreColor}; cursor: pointer;` }, superDropdownMenuItem);
  561. document.getElementById(`deleteSuperSet${build.Id}Button`).addEventListener("click", function(e) { e.stopPropagation(); deleteSuperSet(build.Id, superDropdownMenuItem); });
  562. superDropdownMenuItem.addEventListener("click", function(e) { e.stopPropagation(); applyBuild(superDropdownText, build); });
  563. if(build.Id == getPlayerValue("SuperSet")) {
  564. superDropdownText.style.color = '#0f0';
  565. }
  566. }
  567. superDropdown.style.display = "none";
  568. }
  569. }
  570. let currentWidth = getTextWidth(currentSet.name, getCanvasFont(currentSetReference));
  571. if(maxClientWidth < currentWidth) {
  572. maxClientWidth = currentWidth;
  573. }
  574. }
  575. if(i == 3) {
  576. const showAddSuperSetButtonLable = addElement("label", { for: "showAddSuperSetButtonCheckbox", innerText: (isEn ? 'Show button "Create super set"' : 'Показать кнопку "Создать билд"') + "\t" }, menuContent);
  577. const showAddSuperSetButtonCheckbox = addElement("input", { id: "showAddSuperSetButtonCheckbox", type: "checkbox" }, menuContent);
  578. showAddSuperSetButtonCheckbox.checked = getPlayerBool("ShowAddSuperSetButton", true);
  579. showAddSuperSetButtonCheckbox.addEventListener("change", function() { setPlayerValue("ShowAddSuperSetButton", this.checked); }, false);
  580. addElement("br", {}, menuContent);
  581.  
  582. const showMenyAtRightLable = addElement("label", { for: "showMenyAtRightCheckbox", innerText: (isEn ? 'Show menu at right' : 'Показать меню справа') + "\t" }, menuContent);
  583. const showMenyAtRightCheckbox = addElement("input", { id: "showMenyAtRightCheckbox", type: "checkbox" }, menuContent);
  584. showMenyAtRightCheckbox.checked = getPlayerBool("ShowMenyAtRight");
  585. showMenyAtRightCheckbox.addEventListener("change", function() { setPlayerValue("ShowMenyAtRight", this.checked); }, false);
  586. }
  587. menuContent.style.minWidth = `${(maxClientWidth + 25)}px`;
  588. menuContent.style.display = "none";
  589. }
  590. }
  591. function createBuildButton() {
  592. if(!getPlayerBool("ShowAddSuperSetButton", true)) {
  593. return;
  594. }
  595. const fractionsMainMenuItem = document.getElementById(`SetsMenuItem3`);
  596. let addBuildButton = document.getElementById("addBuildButton");
  597. if(addBuildButton) {
  598. return;
  599. }
  600. if(isNewInterface) {
  601. addBuildButton = addElement("div", { id: "addBuildButton", class: "position_tr", innerHTML: `<img class="NotificationIcon" src="${resourcesPath}/i/new_top/_panelBattles.png" style="width: 16px; height: 16px;" title="${isEn ? "Create build" : "Создать билд"}" >` }, fractionsMainMenuItem);
  602. } else {
  603. addBuildButton = addElement("a", { id: "addBuildButton", href: "javascript:void(0);", style: "text-decoration: none; vertical-align: bottom;", innerHTML: `<img src="${resourcesPath}/i/new_top/_panelBattles.png" style="width: 16px; height: 16px; border-radius: 50%;" title="${isEn ? "Create build" : "Создать билд"}" >` }, fractionsMainMenuItem);
  604. }
  605. addBuildButton.addEventListener("click", function(e) { e.stopPropagation(); addBuild(); });
  606. }
  607. function addBuild() {
  608. const superSetName = prompt(isEn ? "Enter build name" : "Введите название билда");
  609. if(superSetName) {
  610. //deletePlayerValue("SuperSets");
  611. const superSets = JSON.parse(getPlayerValue("SuperSets", "[]"));
  612. superSets.push({
  613. Id: Date.now(),
  614. Name: superSetName,
  615. Fraction: Fraction,
  616. WeaponSet: getPlayerValue(weaponSetsPreferences.getCurrentSetName(), -1),
  617. SkillSet: getPlayerValue(skillSetsPreferences.getCurrentSetName(), -1),
  618. ArmySet: getPlayerValue(armySetsPreferences.getCurrentSetName(), -1)
  619. });
  620. setPlayerValue("SuperSets", JSON.stringify(superSets));
  621. }
  622. }
  623. function deleteSuperSet(id, menuItem) {
  624. const superSets = JSON.parse(getPlayerValue("SuperSets", "[]"));
  625. const deletingIndex = superSets.findIndex(x => x.Id == id);
  626. if(deletingIndex > -1) {
  627. superSets.splice(deletingIndex, 1);
  628. setPlayerValue("SuperSets", JSON.stringify(superSets));
  629. if(menuItem) {
  630. menuItem.remove();
  631. }
  632. }
  633. }
  634. async function applyBuild(superDropdownText, build) {
  635. const sets = [weaponSetsPreferences.name, skillSetsPreferences.name, armySetsPreferences.name];
  636. const originalText = superDropdownText ? superDropdownText.innerHTML : "";
  637. if(superDropdownText) {
  638. superDropdownText.innerHTML += " " + getWheelImage();
  639. }
  640. if(build.Fraction != Fraction) {
  641. await applySet(document.getElementById(`${fractionsPreferences.getCurrentSetName()}SetReference${build.Fraction}`), fractionsPreferences, fractionsPreferences.sets.find(x => x.number == build.Fraction), false);
  642. sets.push(fractionsPreferences.name);
  643. }
  644. await applySet(document.getElementById(`${weaponSetsPreferences.getCurrentSetName()}SetReference${build.WeaponSet}`), weaponSetsPreferences, weaponSetsPreferences.sets.find(x => x.number == build.WeaponSet), false);
  645. await applySet(document.getElementById(`${skillSetsPreferences.getCurrentSetName()}SetReference${build.SkillSet}`), skillSetsPreferences, skillSetsPreferences.sets.find(x => x.number == build.SkillSet), false);
  646. await applySet(document.getElementById(`${armySetsPreferences.getCurrentSetName()}SetReference${build.ArmySet}`), armySetsPreferences, armySetsPreferences.sets.find(x => x.number == build.ArmySet), false);
  647. await updatePanels(sets);
  648. setPlayerValue("SuperSet", build.Id);
  649. if(superDropdownText) {
  650. Array.from(document.querySelectorAll("b[name=superDropdownText]")).forEach(x => x.style.color = "#f5c137");
  651. superDropdownText.innerHTML = originalText;
  652. superDropdownText.style.color = '#0f0';
  653. }
  654. }
  655. function markCurrent(selectedMenuItem, currentPreferences, currentSetNumber) {
  656. setPlayerValue(currentPreferences.getCurrentSetName(), currentSetNumber);
  657. if(selectedMenuItem) {
  658. selectedMenuItem.style.color = '#0f0';
  659. if(currentPreferences.currentMenuItem && currentPreferences.currentMenuItem != selectedMenuItem) {
  660. currentPreferences.currentMenuItem.style.color = "#f5c137";
  661. }
  662. currentPreferences.currentMenuItem = selectedMenuItem;
  663. }
  664. }
  665. function addSetChangerListener(htmlElement, currentPreferences, setNumber) {
  666. htmlElement.addEventListener("click", function() { markCurrent(currentPreferences.menuItems[setNumber], currentPreferences, setNumber); });
  667. }
  668. async function applySet(selectedMenuItem, currentPreferences, currentSet, callPageRefreshFunction = true) {
  669. markCurrent(selectedMenuItem, currentPreferences, currentSet.number);
  670. const originalText = selectedMenuItem ? selectedMenuItem.innerHTML : "";
  671. if(selectedMenuItem) {
  672. selectedMenuItem.innerHTML += " " + getWheelImage();
  673. }
  674. if(currentSet.method == "POST") {
  675. await postRequest(currentSet.url, currentSet.data);
  676. } else {
  677. await getRequest(currentSet.url);
  678. }
  679. if(selectedMenuItem) {
  680. selectedMenuItem.innerHTML = originalText;
  681. if(isMobileDevice) {
  682. selectedMenuItem.parentNode.parentNode.style.display = "none";
  683. }
  684. }
  685. const selectedValueDiv = document.getElementById(`hwmSetsMaster${currentPreferences.name}SelectedValue`);
  686. if(selectedValueDiv) {
  687. selectedValueDiv.innerHTML = currentSet.number;
  688. }
  689. if(typeof(currentPreferences.setChanged) == "function") {
  690. await currentPreferences.setChanged(currentSet.number);
  691. }
  692. if(callPageRefreshFunction) {
  693. updatePanels([currentPreferences.name]);
  694. }
  695. }
  696. function drowSkillChangers() {
  697. if(location.pathname=='/home.php' && !document.querySelector(`#increaseattackAmountInput`)) {
  698. let skillsCount = 0;
  699. let re = new RegExp(isNewPersonPage ? `>${LocalizedString.AvailablePoints}:\\s(\\d+)<` : `<b>${LocalizedString.AvailablePoints}:</b>\\s(\\d+)`);
  700. const skillsExec = re.exec(document.body.innerHTML);
  701. if(skillsExec) {
  702. skillsCount += parseInt(skillsExec[1]);
  703. }
  704. re = new RegExp(isNewPersonPage ? `>${LocalizedString.AvailableTalentPoints}:\\s(\\d+)<` : `<b>${LocalizedString.AvailableTalentPoints}:</b>\\s(\\d+)`);
  705. const perksSkillsExec = re.exec(document.body.innerHTML);
  706. if(perksSkillsExec) {
  707. skillsCount += parseInt(perksSkillsExec[1]);
  708. }
  709. //console.log(`skillsCount: ${skillsCount}`);
  710. if(skillsCount == 0) {
  711. return;
  712. }
  713. const skillValueContainers = [];
  714. if(isNewPersonPage) {
  715. const container = document.querySelector("div#home_css_stats_wrap_div");
  716. const inv_stat_dataDivs = container.querySelectorAll("div.inv_stat_data.home_stat_data.show_hint");
  717. for(const inv_stat_dataDiv of inv_stat_dataDivs) {
  718. const increaseButton = inv_stat_dataDiv.querySelector("div.home_button2.btn_hover2");
  719. if(!increaseButton) {
  720. continue;
  721. }
  722. const skillValueContainer = inv_stat_dataDiv.querySelector("div.inv_stat_text.home_stat_text");
  723. skillValueContainers.push(skillValueContainer);
  724. }
  725. } else {
  726. const increaseRefs = document.querySelectorAll("a[href^='home.php?increase=']"); //home.php?increase=defence
  727. for(const increaseRef of increaseRefs) {
  728. const sklilIncreaseCell = getParent(increaseRef, "td");
  729. const skillValueContainer = sklilIncreaseCell.previousSibling;
  730. skillValueContainers.push(skillValueContainer);
  731. }
  732. }
  733. const skillNames = ["attack", "defence", "power", "knowledge"];
  734. let i = 0;
  735. for(const skillValueContainer of skillValueContainers) {
  736. const skillValue = Number((skillValueContainer.querySelector("b") || skillValueContainer).innerText);
  737. skillValueContainer.innerHTML = "";
  738. const skill = skillNames[i];
  739. const increaseAmountInput = addElement("input", { id: `increase${skill}AmountInput`, name: "increaseAmountInput", value: skillValue, type: "number", min: skillValue, max: skillValue + skillsCount, size: 4, onfocus: "this.select();", title: LocalizedString.IncreaseManyPointsTooltip.replace("${minValue}", skillValue + 1).replace("${maxValue}", skillValue + skillsCount) }, skillValueContainer);
  740. increaseAmountInput.addEventListener("change", function() { const targetValue = Number(increaseAmountInput.value); if(targetValue > skillValue && targetValue <= skillValue + skillsCount) { changeSkill(increaseAmountInput, isNewPersonPage, skill, skillValue, targetValue); } });
  741. i++;
  742. }
  743. }
  744. }
  745. async function changeSkill(increaseAmountInput, isNewPersonPage, skill, currentValue, targetValue) {
  746. while(currentValue < targetValue) {
  747. const url = `/home.php?increase=${skill}` + (isNewPersonPage ? `&info=1&js_output=1&rand=${Math.random() * 1000000}` : "");
  748. const txt = await getRequestText(url, isNewPersonPage ? "text/html; charset=UTF-8" : "text/html; charset=windows-1251");
  749. currentValue++;
  750. if(isNewPersonPage) {
  751. if (txt.substring(0, 7) != 'HCSS_OK') {
  752. window.location = '/home.php?info';
  753. return;
  754. }
  755. const data = txt.split('@');
  756. const home_css_stats_wrap_div = document.getElementById('home_css_stats_wrap_div');
  757. if(data && data[1] && home_css_stats_wrap_div) {
  758. home_css_stats_wrap_div.innerHTML = data[1];
  759. if(data.length > 2 && document.getElementById('home_css_mana_count')) {
  760. document.getElementById('home_css_mana_count').innerHTML = parseInt(data[2]);
  761. }
  762. if(typeof win.hwm_hints_init === 'function') win.hwm_hints_init();
  763. }
  764. } else {
  765. increaseAmountInput.value = currentValue;
  766. }
  767. }
  768. if(!isNewPersonPage) {
  769. location.reload();
  770. }
  771. }
  772. function getWheelImage() { return `<img border="0" align="absmiddle" height="11" src="${resourcesPath}/css/loading.gif">`; }
  773. function getFraction() {
  774. let currentFractionNumber;
  775. if(location.pathname == '/home.php') {
  776. // for new home page
  777. let currentFractionIconContainer = document.querySelector("div.home_css_pl_fract.show_hint");
  778. if(!currentFractionIconContainer) {
  779. currentFractionIconContainer = document.querySelector("a[href^='castle.php?change_faction_dialog']");
  780. }
  781. if(currentFractionIconContainer) {
  782. const currentFractionIconImg = currentFractionIconContainer.querySelector("img");
  783. currentFractionNumber = currentFractionIconImg.src.split("i/f/r")[1].split(".png")[0];
  784. }
  785. } else if(location.pathname=='/pl_info.php' && getUrlParamValue(location.href, "id") == PlayerId) {
  786. const fractionImage = document.querySelector("img[src*='i/f/r']");
  787. const regExp = new RegExp('\\/i\\/f\\/r(\\d+)\\.png');
  788. const regExpExec = regExp.exec(fractionImage.src);
  789. if(regExpExec) {
  790. currentFractionNumber = regExpExec[1];
  791. }
  792. } else if(location.pathname=='/castle.php') {
  793. const selectedFractionImg = document.querySelector("div.castle_faction_div_inside2 img");
  794. const selectedFractionImgName = selectedFractionImg.getAttribute("src");
  795. const selectedFractionNumber = selectedFractionImgName.split("kukla_png/kukla")[1].split(".")[0]; //dcdn.heroeswm.ru/i/kukla_png/kukla5.png
  796.  
  797. const fractionsDiv = document.querySelector("div[id='faction_list']");
  798. if(fractionsDiv.getAttribute("style").includes("display:none;")) {
  799. currentFractionNumber = selectedFractionNumber;
  800. }
  801. }
  802. if(currentFractionNumber) {
  803. setPlayerValue("Fraction", currentFractionNumber);
  804. }
  805. Fraction = parseInt(getPlayerValue("Fraction"));
  806. }
  807. async function updatePanels(sets) {
  808. let pageReloadNeeded = false;
  809. let panels = [];
  810. if(sets.includes(weaponSetsPreferences.name) && ["/home.php", "/inventory.php", "/pl_info.php", "/map.php"].includes(location.pathname)) {
  811. pageReloadNeeded = true;
  812. if(location.pathname == '/home.php') {
  813. pushNew(panels, homeArtsPanelSelector);
  814. pushNew(panels, homeStatsPanelSelector);
  815. pageReloadNeeded = false;
  816. }
  817. if(location.pathname == '/pl_info.php') {
  818. if(getUrlParamValue(location.href, "id") == PlayerId) {
  819. pushNew(panels, playerInfoArtsPanelSelector);
  820. pushNew(panels, playerInfoStatsPanelSelector);
  821. }
  822. pageReloadNeeded = false;
  823. }
  824. if(location.pathname == '/map.php') {
  825. pushNew(panels, mapHuntButtons2PanelSelector);
  826. pushNew(panels, mapMercenaryTaskPanelSelector);
  827. pageReloadNeeded = false;
  828. }
  829. }
  830. if(sets.includes(skillSetsPreferences.name) && ["/skillwheel.php", "/pl_info.php", "/home.php", "/inventory.php"].includes(location.pathname)) {
  831. pageReloadNeeded = true;
  832. if(location.pathname == '/home.php') {
  833. pushNew(panels, homeStatsPanelSelector);
  834. pageReloadNeeded = false;
  835. }
  836. if(location.pathname == '/pl_info.php') {
  837. if(getUrlParamValue(location.href, "id") == PlayerId) {
  838. pushNew(panels, playerInfoStatsPanelSelector);
  839. pushNew(panels, playerInfoPerksPanelSelector);
  840. }
  841. pageReloadNeeded = false;
  842. }
  843. if(location.pathname == '/inventory.php') {
  844. pushNew(panels, inventoryStatsPanelSelector);
  845. pageReloadNeeded = false;
  846. }
  847. }
  848. if(sets.includes(armySetsPreferences.name) && ["/home.php", "/army.php", "/pl_info.php"].includes(location.pathname)) {
  849. pageReloadNeeded = true;
  850. if(location.pathname == '/home.php') {
  851. pushNew(panels, homeArmyPanelSelector);
  852. pageReloadNeeded = false;
  853. }
  854. if(location.pathname == '/pl_info.php') {
  855. if(getUrlParamValue(location.href, "id") == PlayerId) {
  856. pushNew(panels, playerInfoArmyPanelSelector);
  857. }
  858. pageReloadNeeded = false;
  859. }
  860. }
  861. if(sets.includes(fractionsPreferences.name) && ["/home.php", "/army.php", "/pl_info.php", "/castle.php", "/inventory.php", "/skillwheel.php"].includes(location.pathname)) {
  862. pageReloadNeeded = true;
  863. }
  864. if(pageReloadNeeded) {
  865. if(location.pathname == "/army.php") {
  866. location = "/army.php";
  867. } else {
  868. window.location.reload();
  869. }
  870. } else {
  871. await refreshUpdatePanels(panels);
  872. }
  873. }
  874. // API
  875. function getPlayerFractionValue(key, defaultValue, fraction = Fraction) { return getPlayerValue(getFractionKey(key, fraction), defaultValue); };
  876. function setPlayerFractionValue(key, value, fraction = Fraction) { setPlayerValue(getFractionKey(key, fraction), value); };
  877. function deletePlayerFractionValue(key, fraction = Fraction) { return deletePlayerValue(getFractionKey(key, fraction)); };
  878. function getFractionKey(key, fraction = Fraction) { return `${key}${fraction}f`; }