Advertisement
MarrKoo

Neon moodle levels fix

Feb 5th, 2025
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.03 KB | None | 0 0
  1. require "MF_ISMoodle"
  2.  
  3. ISNeonMoodleLevels = {}
  4.  
  5. function ISNeonMoodleLevels:new()
  6.     local o = {}
  7.     setmetatable(o, self)
  8.     self.__index = self
  9.     o.defaultMoodleSize = 48
  10.     o.moodleAlpha = 1.0
  11.     o.active = false
  12.     o.hidden = false
  13.     o.cache = {indicator = {} , background = {}}
  14.     o.moodleSlotsDesiredPos = {};
  15.     o.moodleSlotsPos = {};
  16.     o.moodleLevel = {}
  17.     o.options = {alwaysOnTop = false}
  18.     o.moodlesCount = 0
  19.     o.useCharacter = {}
  20.     o.characterASleep = false
  21.     o.goodBadNeutral = {}
  22.     o.moodleLevel = {}
  23.     o.panelY = 0
  24.     o.panelX = 0
  25.     o.currentMoodleSize = nil
  26.     o.trackedMoodleFrameworkObjects = {}
  27.     o.moodleParked = {}
  28.     o.emptyPath = "media/ui/neonMoodleIndicator_empty.png"
  29.     o.backgroundPathUnformatted = "media/ui/neonMoodleIndicator_%d_%d.png"
  30.     o.indicatorPathUnformatted = "media/ui/neonMoodleIndicator_%d_%d_i.png"
  31.     o.moodleFrameworkIntegrated = false
  32.    
  33.     o.moodleSlotsRestPos = 10000 -- digged from java zombie.ui.MoodlesUI.class #24 and other hardcoded lines
  34.     o.moodleSlotsStartPos = 500 -- digged from java zombie.ui.MoodlesUI.class #421
  35.     o.verticalMargin = 10  -- digged from java zombie.ui.MoodlesUI.class #379 , can be set with ISNeonMoodleLevels:setVerticalMargin(size)
  36.  
  37.     return o
  38. end
  39.  
  40. function ISNeonMoodleLevels:setCharacter(character)
  41.     self.useCharacter[1] = character
  42. end
  43.  
  44. function ISNeonMoodleLevels:setCharacter2(character)
  45.     self.useCharacter[2] = character
  46. end
  47.  
  48.  
  49. function ISNeonMoodleLevels:clearCache()
  50.     self.cache = {}
  51.     self.indicator = {}
  52.     self.background = {}
  53. end
  54.  
  55. function ISNeonMoodleLevels:hide()
  56.     self.hidden = true
  57. end
  58.  
  59. function ISNeonMoodleLevels:show()
  60.     self.hidden = true
  61. end
  62.  
  63. function ISNeonMoodleLevels:cacheTextureIfNeeded(object, texturePath, goodBadNeutralId, moodleLevel)
  64.     if object[goodBadNeutralId] == nil or object[goodBadNeutralId][moodleLevel] == nil or object[goodBadNeutralId][moodleLevel].texture == nil and object[goodBadNeutralId][moodleLevel].texture ~= false then
  65.         if goodBadNeutralId and goodBadNeutralId > 0 and goodBadNeutralId < 3 and moodleLevel > 0 and moodleLevel < 5 and texturePath then
  66.             if object[goodBadNeutralId] == nil then
  67.                 object[goodBadNeutralId] = {}
  68.             end
  69.             if object[goodBadNeutralId][moodleLevel] == nil then
  70.                 object[goodBadNeutralId][moodleLevel] = {}
  71.                 object[goodBadNeutralId][moodleLevel].texture = nil
  72.                 object[goodBadNeutralId][moodleLevel].width = 128
  73.                 object[goodBadNeutralId][moodleLevel].height = 128
  74.                 object[goodBadNeutralId][moodleLevel].realWidth = 128
  75.                 object[goodBadNeutralId][moodleLevel].realHeight = 128
  76.                 object[goodBadNeutralId][moodleLevel].currentWidth = 128
  77.                 object[goodBadNeutralId][moodleLevel].moodleSize = 128
  78.             end
  79.             object[goodBadNeutralId][moodleLevel].texture = getTexture(texturePath)
  80.             if object[goodBadNeutralId][moodleLevel].texture == nil then
  81.                 object[goodBadNeutralId][moodleLevel].texture = false
  82.             else
  83.                 object[goodBadNeutralId][moodleLevel].realWidth = object[goodBadNeutralId][moodleLevel].texture:getWidth()
  84.                 object[goodBadNeutralId][moodleLevel].realHeight = object[goodBadNeutralId][moodleLevel].texture:getHeight()
  85.                 object[goodBadNeutralId][moodleLevel].width = object[goodBadNeutralId][moodleLevel].realWidth
  86.                 object[goodBadNeutralId][moodleLevel].height = object[goodBadNeutralId][moodleLevel].realHeight
  87.             end
  88.         else
  89.             error("Check arguments")
  90.         end
  91.     end
  92. end
  93.  
  94. function ISNeonMoodleLevels:start()
  95.     self.active = true
  96. end
  97.  
  98. function ISNeonMoodleLevels:stop()
  99.     self.active = false
  100. end
  101.  
  102. function ISNeonMoodleLevels:resetMoodlePosition(moodleId)
  103.     self.moodleSlotsDesiredPos[moodleId] = self.moodleSlotsRestPos;
  104.     self.moodleSlotsPos[moodleId] = self.moodleSlotsRestPos;
  105. end
  106.  
  107. function ISNeonMoodleLevels:cacheSizes(object, moodleSize)
  108.     object.height = moodleSize
  109.     object.moodleSize = moodleSize
  110.     object.realWidth = object.texture:getWidth()
  111.     object.realHeight = object.texture:getHeight()
  112.     if object.realWidth ~= object.realHeight then
  113.         if object.realWidth == moodleSize then
  114.             object.width = moodleSize
  115.         else
  116.             object.width = round(object.realWidth * moodleSize / object.realHeight, 0)
  117.         end
  118.     else
  119.         object.width = moodleSize
  120.     end
  121. end
  122. function ISNeonMoodleLevels:update(isGlobalPrerender)
  123.   for _,player in pairs(self.useCharacter) do
  124.     if player then
  125.         self.moodlesCount = MoodleType.ToIndex(MoodleType.MAX)
  126.         self.characterASleep = player:isAsleep()
  127.         if isGlobalPrerender then
  128.             self:prerender()
  129.         end
  130.         self:render(isGlobalPrerender)
  131.     end
  132.   end
  133. end
  134.  
  135. function ISNeonMoodleLevels:render(isGlobalPrerender)
  136.     if self.hidden then
  137.         return
  138.     end
  139.     local moodlesUI = MoodlesUI.getInstance()
  140.     if not self.useCharacter[1] or not self.active or not self.active or moodlesUI == nil or moodlesUI ~= nil and not moodlesUI:isVisible() then
  141.         return
  142.     end
  143.  
  144.     for moodleId = 0, self.moodlesCount -1 do
  145.         if self.moodleSlotsPos[moodleId] ~= self.moodleSlotsRestPos and self.goodBadNeutral[moodleId] ~= nil and self.moodleLevel[moodleId] ~= nil then
  146.             local goodBadNeutralId = self.goodBadNeutral[moodleId]
  147.             local moodleLevel = self.moodleLevel[moodleId]
  148.  
  149.             if goodBadNeutralId and moodleLevel then
  150.                 local background = self.cache.background[goodBadNeutralId] and self.cache.background[goodBadNeutralId][moodleLevel] or nil
  151.                 local indicator = self.cache.indicator[goodBadNeutralId] and self.cache.indicator[goodBadNeutralId][moodleLevel] or nil
  152.  
  153.                 if self:isRenderIndicatorOnly() or (not isGlobalPrerender and ( self.characterASleep or self.options.alwaysOnTop)) then
  154.                     UIManager.DrawTexture(indicator.texture, self.panelX, self.moodleSlotsPos[moodleId], indicator.width, indicator.height, self.moodleAlpha)
  155.                 elseif self:isRenderBackground() and isGlobalPrerender then
  156.                     UIManager.DrawTexture(background.texture, self.panelX, self.moodleSlotsPos[moodleId], background.width, background.height, self.moodleAlpha)
  157.                 end
  158.             end
  159.         end
  160.     end
  161. end
  162.  
  163. function ISNeonMoodleLevels:prerender()
  164.     local moodlesUI = MoodlesUI.getInstance()
  165.     if not self.active or moodlesUI ~= nil and not moodlesUI:isVisible() then
  166.         return
  167.     end
  168.     local moodleSize = self:getMoodleSize()
  169.       for _,player in pairs(self.useCharacter) do
  170.     if player ~= nil and player:getMoodles() ~= nil then
  171.         local moodles = player:getMoodles()
  172.         local moodlesUI = MoodlesUI.getInstance()
  173.         local renderedId = 0
  174.  
  175.         self.panelY = moodlesUI:getAbsoluteY()
  176.         self.panelX = moodlesUI:getAbsoluteX()
  177.  
  178.         for moodleId = 0, self.moodlesCount - 1 do
  179.             local moodleType = MoodleType.FromIndex(moodleId)
  180.             local moodleLevel = moodles:getMoodleLevel(moodleType)
  181.             local goodBadNeutralId = moodles:getGoodBadNeutral(moodleId)
  182.            
  183.             self.goodBadNeutral[moodleId] = goodBadNeutralId
  184.             self.moodleLevel[moodleId] = moodleLevel
  185.  
  186.             if self.moodleSlotsDesiredPos[moodleId] == nil and self.moodleSlotsPos[moodleId] == nil then
  187.                 self:resetMoodlePosition(moodleId)
  188.             end
  189.  
  190.             if (moodleType == MoodleType.FoodEaten) and moodleLevel < 3 then
  191.                 -- reset positions
  192.                 self:resetMoodlePosition(moodleId)
  193.                 self.moodleLevel[moodleId] = moodleLevel -- but keep real level?
  194.             elseif moodleLevel > 0 then
  195.                 -- Cache background texture
  196.                 self:cacheTextureIfNeeded(self.cache.background,string.format(self.backgroundPathUnformatted, goodBadNeutralId, moodleLevel), goodBadNeutralId, moodleLevel)
  197.                 -- Cache indicator texture
  198.                 self:cacheTextureIfNeeded(self.cache.indicator,string.format(self.indicatorPathUnformatted, goodBadNeutralId, moodleLevel), goodBadNeutralId, moodleLevel)
  199.  
  200.                 local background = self.cache.background[goodBadNeutralId][moodleLevel]
  201.                 local indicator = self.cache.indicator[goodBadNeutralId][moodleLevel]
  202.                
  203.                 -- Cache background sizes
  204.                 if background and background.texture and background.moodleSize ~= moodleSize then
  205.                     self:cacheSizes(background, moodleSize)
  206.                 end
  207.                 -- Cache indicator sizes
  208.                 if indicator and indicator.texture and  indicator.moodleSize ~= moodleSize then
  209.                     self:cacheSizes(indicator, moodleSize)
  210.                 end
  211.                 -- Recalculate position
  212.                 if self.moodleLevel[moodleId] ~= moodleLevel then
  213.                     self.moodleLevel[moodleId] = moodleLevel
  214.                 end
  215.                 self.moodleParked[moodleId] = self.moodleSlotsPos[moodleId] == self.moodleSlotsDesiredPos[moodleId]
  216.                 self.moodleSlotsDesiredPos[moodleId] = self.panelY + (self.verticalMargin + moodleSize) * renderedId
  217.  
  218.                 if self.moodleSlotsPos[moodleId] == self.moodleSlotsRestPos then
  219.                     self.moodleSlotsPos[moodleId] = self.moodleSlotsDesiredPos[moodleId] + self.moodleSlotsStartPos
  220.  
  221.                 end
  222.                
  223.  
  224.                 if math.abs(self.moodleSlotsPos[moodleId] - self.moodleSlotsDesiredPos[moodleId]) > 0.8 then
  225.                     if not self.moodleParked[moodleId] then
  226.                         self.moodleSlotsPos[moodleId] = self.moodleSlotsPos[moodleId] + (self.moodleSlotsDesiredPos[moodleId] - self.moodleSlotsPos[moodleId]) * 0.15
  227.                     end
  228.                 else
  229.                     self.moodleSlotsPos[moodleId] = self.moodleSlotsDesiredPos[moodleId]
  230.                 end
  231.  
  232.  
  233.                 renderedId = renderedId + 1
  234.             else
  235.                 self:resetMoodlePosition(moodleId)
  236.                 self.moodleLevel[moodleId] = 0
  237.             end
  238.         end
  239.     end  
  240.     end
  241. end
  242.  
  243.  
  244. function ISNeonMoodleLevels:setVerticalMargin(size)
  245.     if size and size >= 0 then
  246.         self.verticalMargin = size
  247.     else
  248.         error("Wrong value. Should be positive number")
  249.     end
  250. end
  251.  
  252. function ISNeonMoodleLevels:getVerticalMargin()
  253.     return self.verticalMargin
  254. end
  255.  
  256. function ISNeonMoodleLevels:setDefaultMoodleSize(size)
  257.     if size and size >= 0 then
  258.         self.defaultMoodleSize = size
  259.     else
  260.         error("Wrong value. Should be positive number")
  261.     end
  262. end
  263.  
  264. function ISNeonMoodleLevels:getDefaultMoodleSize()
  265.     return self.defaultMoodleSize
  266. end
  267.  
  268. function ISNeonMoodleLevels:getMoodleSize()
  269.     -- Get Preset
  270.     if self.currentMoodleSize then
  271.         return self.currentMoodleSize
  272.     end
  273.     local moodleSize = getCore():getOptionMoodleSize()
  274.      -- Auto size
  275.     if moodleSize == 7 then
  276.         local fontEnum = UIFont.Small
  277.         return getTextManager():getFontFromEnum(fontEnum):getLineHeight()*3 -- from java zombie.ui.MoodlesUI.class #205
  278.     elseif moodleSize == 6 then
  279.         moodleSize = moodleSize + 1
  280.     elseif moodleSize > 7 then
  281.         return self.defaultMoodleSize
  282.     end
  283.    
  284.     self.currentMoodleSize = (moodleSize + 1) * 16
  285.     return self.currentMoodleSize
  286. end
  287.  
  288. function ISNeonMoodleLevels:applyOptions()
  289.     local newOptions = PZAPI.ModOptions:getOptions("neonMoodleLevels")
  290.     self.options.alwaysOnTop = newOptions:getOption("alwaysOnTop"):getValue()
  291.     self.options.renderBackground = newOptions:getOption("renderBackground"):getValue()
  292.     self.options.renderIndicator = newOptions:getOption("renderIndicator"):getValue()
  293.     self.options.integrateMoodleFramework = newOptions:getOption("integrateMoodleFramework"):getValue()
  294.    
  295.     if self.moodleFrameworkIntegrated or self.options.integrateMoodleFramework then
  296.         for i, object in pairs(self.trackedMoodleFrameworkObjects) do
  297.             self:updateMoodleFrameworkObjectTextures(object)
  298.         end
  299.         if not self.options.integrateMoodleFramework then
  300.             self.moodleFrameworkIntegrated = false
  301.         end
  302.     end
  303. end
  304.  
  305. function ISNeonMoodleLevels:initConfig()
  306.     local PZOptions = PZAPI.ModOptions:create("neonMoodleLevels", "Neon Moodle Levels")
  307.     PZOptions:addTickBox("renderBackground", getText("UI_nML_renderBackground"), true, "UI_nML_renderBackground_tooltip")
  308.     PZOptions:addTickBox("renderIndicator", getText("UI_nML_renderIndicator"), true, "UI_nML_renderIndicator_tooltip")
  309.     PZOptions:addTickBox("alwaysOnTop", getText("UI_nML_alwaysOnTop"), false, "UI_nML_alwaysOnTop_tooltip")
  310.     PZOptions:addTickBox("integrateMoodleFramework", getText("UI_nML_integrateMoodleFramework"), true, "UI_nML_integrateMoodleFramework_tooltip")
  311.    
  312.     local s = self
  313.     PZOptions.apply = function (self)
  314.         s:applyOptions()
  315.     end
  316.     Events.OnMainMenuEnter.Add(function()
  317.         PZOptions:apply()
  318.     end)
  319.     self:applyOptions()
  320. end
  321.  
  322. function ISNeonMoodleLevels:isRenderIndicatorOnly()
  323.     return not self.options.renderBackground and (self.options.alwaysOnTop or self.options.renderIndicator)
  324. end
  325. function ISNeonMoodleLevels:isRenderBackground()
  326.     return self.options.renderBackground
  327. end
  328.  
  329. -- moodleFrameWork integration api
  330. function ISNeonMoodleLevels:trackMoodleFrameworkObject(object)
  331.     table.insert(self.trackedMoodleFrameworkObjects, object)
  332. end
  333.  
  334. function ISNeonMoodleLevels:updateMoodleFrameworkObjectTextures(object)
  335.     if object == nil or object.setBackground == nil then
  336.         return
  337.     end
  338.     if self.options.integrateMoodleFramework then
  339.         local empty = true
  340.         local indicatorOnly = false
  341.         local unformated = ""
  342.         if self:isRenderIndicatorOnly() then
  343.             empty = false
  344.             indicatorOnly = true
  345.             unformated = self.indicatorPathUnformatted
  346.         elseif self:isRenderBackground() then
  347.             empty = false
  348.             unformated = self.backgroundPathUnformatted
  349.         end
  350.         for g = 1, 2 do
  351.             for l = 1, 4 do
  352.                 if empty then
  353.                     object:setBackground(g,l,getTexture(self.emptyPath))
  354.                 else
  355.                     object:setBackground(g,l,getTexture(string.format(unformated,g,l)))
  356.                 end
  357.             end
  358.         end
  359.         self.moodleFrameworkIntegrated = true
  360.     elseif self.moodleFrameworkIntegrated then
  361.         for g = 1, 2 do
  362.             for l = 1, 4 do
  363.                 if object.bkg and object.bkg[g] then
  364.                     object.bkg[g][l] = nil
  365.                 end
  366.             end
  367.         end
  368.     end
  369. end
  370.  
  371.  
  372.  
  373.  
  374. -- handler
  375.  
  376. ISNeonMoodleLevelsHandle = ISNeonMoodleLevels:new()
  377.  
  378. ISNeonMoodleLevelsHandle:initConfig()
  379.  
  380. ISNeonMoodleLevelsHandle:start()
  381.  
  382. local function onPreUIDraw()
  383.     if isServer() then return end
  384.     ISNeonMoodleLevelsHandle:update(true)
  385. end
  386. local function onPostUIDraw()
  387.     if isServer() then return end
  388.     ISNeonMoodleLevelsHandle:update(false)
  389. end
  390. local function updateCharacter(id,player)
  391.    if player == getSpecificPlayer(0) then
  392.     ISNeonMoodleLevelsHandle:setCharacter(player)
  393.    elseif player == getSpecificPlayer(1) then
  394.     ISNeonMoodleLevelsHandle:setCharacter2(player)
  395.    end
  396. end
  397. local function onloadMoodles ()
  398.     ISNeonMoodleLevelsHandle.currentMoodleSize = nil
  399. end
  400.  
  401. Events.OnPreUIDraw.Add(onPreUIDraw)
  402. Events.OnPostUIDraw.Add(onPostUIDraw)
  403. Events.OnCreatePlayer.Add(updateCharacter)
  404. Events.OnLoad.Add(onloadMoodles)
  405.  
  406. -- moodleFramework settings integration
  407. if MF ~= nil then
  408.     local oldNew = MF.ISMoodle.new
  409.     function MF.ISMoodle.new(self,moodleName,character)
  410.         local o = oldNew(self,moodleName,character)
  411.         ISNeonMoodleLevelsHandle:trackMoodleFrameworkObject(o)
  412.         ISNeonMoodleLevelsHandle:updateMoodleFrameworkObjectTextures(o)
  413.         return o
  414.     end
  415. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement