HH Unlock Images

This script unlocks images of both recruited girls and non-recruited girls.

  1. // ==UserScript==
  2. // @name HH Unlock Images
  3. // @namespace hhUnlock
  4. // @version 2.06
  5. // @license MIT
  6. // @description This script unlocks images of both recruited girls and non-recruited girls.
  7. // @author YanDee
  8. // @match *://nutaku.haremheroes.com/harem*
  9. // @match *://*.hentaiheroes.com/harem*
  10. // @match *://*.gayharem.com/harem*
  11. // @match *://*.comixharem.com/harem*
  12. // @match *://*.hornyheroes.com/harem*
  13. // @match *://*.pornstarharem.com/harem*
  14. // @grant unsafeWindow
  15. // ==/UserScript==
  16.  
  17. (function(uW, $, girlsDataList, number_format_lang, number_reduce, GT) {
  18. if (document.visibilityState == "hidden" || typeof uW.Girl?.prototype?.showInRightOrig == "function"){
  19. return;
  20. }
  21. let YD_sheet = false;
  22. function YD_addStyle(rules_obj){
  23. if (!YD_sheet){
  24. let style = document.createElement("style");
  25. document.getElementsByTagName("head")[0].appendChild(style);
  26. YD_sheet = document.styleSheets[document.styleSheets.length - 1];
  27. }
  28.  
  29. Object.entries(rules_obj).map(v => {
  30. YD_sheet.insertRule(v[0] + "{" + Object.entries(v[1]).map(
  31. s => s[0] + ":" + s[1] + ";"
  32. ).join("") + "}");
  33. });
  34. }
  35.  
  36. let totalIncome = Math.round(Object.values(girlsDataList).reduce((t,v) => v.own? t + v.salary_per_hour : t, 0)),
  37. $girls_levels = $("#filter_girls").siblings(".girls_levels");
  38. $girls_levels.children().addClass("orig_node");
  39. $girls_levels.append(
  40. $("<span>", {class: "hudSC_mix_icn"}),
  41. $("<p>").append($("<span>", {class: "pompous_text", text: GT.design.haremdex_income})),
  42. $("<p>").append(
  43. $("<p>", {
  44. class: "focus_text",
  45. hh_title: number_format_lang(totalIncome) + " / " + GT.time.h,
  46. "tooltip-id": "tooltip_1",
  47. text: (totalIncome >= 1e6? number_reduce(totalIncome) : number_format_lang(totalIncome)) + " / " + GT.time.h
  48. }),
  49. $("<p>", {
  50. class: "focus_text",
  51. hh_title: number_format_lang(24 * totalIncome) + " / " + GT.time.d,
  52. "tooltip-id": "tooltip_1",
  53. text: (24 * totalIncome >= 1e6? number_reduce(24 * totalIncome) : number_format_lang(24 * totalIncome)) + " / " + GT.time.d
  54. })
  55. )
  56. );
  57. if (sessionStorage.haremLevDispMode != "default"){
  58. sessionStorage.haremLevDispMode = "income";
  59. $("div.girls_levels").addClass("show_income");
  60. }
  61. let styles = {
  62. "div.girls_levels": {"cursor": "pointer"},
  63. "#harem_left div.girls_levels.show_income>.orig_node": {"display": "none"},
  64. "#harem_left div.girls_levels:not(.show_income)>:not(.orig_node)": {"display": "none"},
  65. "#harem_left div.girls_levels p:not(.orig_node)": {"margin": "0"},
  66. "#harem_whole #harem_right img.avatar": {"filter": "none"},
  67. "#harem_whole #harem_right div.middle_part.missing_girl": {"margin-top": "0"},
  68. "#harem_right .diamond-bar .showing": {
  69. "box-shadow": "0 0 3px 5px rgba(20,255,0,0.75)",
  70. "opacity": "1"
  71. },
  72. "#harem_right .diamond-bar :not(.showing)": {"cursor": "pointer"},
  73. "div.diamond-bar>.diamond.anim:before": {"content": "'A'"}
  74. };
  75. YD_addStyle(styles);
  76. $("#harem_left").on("click", ".girls_levels", function(){
  77. this.classList.toggle("show_income");
  78. sessionStorage.haremLevDispMode = this.classList.contains("show_income")? "income" : "default";
  79. });
  80. $("#harem_right").on("click contextmenu", ".diamond-bar .diamond:not(.showing)", function(e){
  81. $(this).addClass("showing").siblings(".showing").removeClass("showing");
  82. changeSkin(this.getAttribute("grade"), $(this).closest("[girl]").attr("girl"));
  83. return e.type != "contextmenu";
  84. });
  85.  
  86. function getDiamondBar(grade){
  87. let body = $("<div>", {class: "diamond-bar"});
  88. for (let i = 0; i < grade; i++) {
  89. $("<div>", {class: "diamond locked" + (i? "" : " showing"), grade: i}).appendTo(body);
  90. };
  91. return body;
  92. }
  93.  
  94. function getHeader(g_id){
  95. let g_info = uW.girlsDataList[g_id] || {}, gem = g_info.element_data?.type, flavor = g_info.element_data?.flavor || "??";
  96. let body = $("<h3>", {text: g_info.ref?.full_name || g_info.name || "Unknown"});
  97. if (gem){
  98. body.append($("<span>", {
  99. class: gem + "_element_icn element_harem_details_icn domination-toggle",
  100. "data-src": g_info.element_data?.ico_url || uW.IMAGES_URL + "/pictures/girls_elements/" + flavor + ".png",
  101. "generic-tooltip": flavor
  102. }));
  103. }
  104. body.append($("<span>", {carac: "class" + g_info.class}));
  105. return [body, $("<p>", {class: "girl-rarity " + g_info.rarity, text: GT.design["girls_rarity_" + g_info.rarity]})];
  106. }
  107.  
  108. function changeSkin(num, girl_id){
  109. let gData = uW.girlsDataList[girl_id], $box = $(".avatar-box", "#harem_right");
  110. if (typeof uW.girlAnimationInstance?.removeCurrentAnimation == "function"){
  111. uW.girlAnimationInstance.removeCurrentAnimation();
  112. }
  113. if (Array.isArray(gData?.animated_grades) && gData.animated_grades.includes(String(num)) && !uW.Hero.infos.no_pachinko_anim){
  114. $box.empty().append(
  115. $("<canvas>", {class: "animated-girl-display", id: "id_" + girl_id + "_grade_" + num + "_animated"})
  116. );
  117. uW.girlAnimationInstance = new uW.GirlAnimation;
  118. uW.girlAnimationInstance.initAnimation(girl_id, num);
  119. return;
  120. }
  121. let ava = (gData?.avatar || "").replace(/av(a|b)\d/g, "ava" + num).toImageUrl("ava");
  122. if ($box.length){
  123. $box.empty().append(
  124. $("<img>", {class: "avatar", src: ava})
  125. );
  126. return;
  127. }
  128. $("img.avatar:not([unappear])", "#harem_right").attr("src", ava);
  129. }
  130.  
  131. function perform(){
  132. let $opened = $("#harem_right").children(".opened[girl]"),
  133. girl_id = $opened.attr("girl"),
  134. g_data = girlsDataList[girl_id];
  135. if (g_data?.own){
  136. $(".diamond-bar .diamond.selected", $opened).addClass("showing");
  137. }
  138. else {
  139. let grade = ((g_data?.graded2 || "").match(/<g[^>]*>[^<>]*<[^>]*\/g>/gi) || []).length + 1;
  140. $("img.avatar:not([unappear])", $opened).before(getHeader(girl_id)).after(getDiamondBar(grade));
  141. changeSkin(0, girl_id);
  142. }
  143. if (Array.isArray(g_data?.animated_grades)){
  144. $(".diamond-bar .diamond", $opened).each((i,d) => $(d).toggleClass("anim", g_data.animated_grades.includes(String(i))));
  145. }
  146. }
  147.  
  148. uW.Girl.prototype.showInRightOrig = uW.Girl.prototype.showInRight;
  149. uW.Girl.prototype.showInRight = function(){
  150. this.showInRightOrig.apply(this);
  151. perform();
  152. };
  153. perform();
  154. })(unsafeWindow, unsafeWindow.jQuery, unsafeWindow.girlsDataList, unsafeWindow.number_format_lang, unsafeWindow.number_reduce, unsafeWindow.GT);