| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547 |
- HudUnits = class()
- local g = love.graphics
- function HudUnits:init()
- self.geometry = setmetatable({}, {__index = function(t, k)
- return rawset(t, k, self.geometryFunctions[k]())[k]
- end})
- self.geometryFunctions = {
- units = function()
- local u, v = ctx.hud.u, ctx.hud.v
- local atlas = data.atlas.hud
- local upgradeFactor, t = ctx.hud.upgrades:getFactor()
- local inc = u * (.2 + (.075 * upgradeFactor))
- local xx = .5 * u - (inc * (self.count - 1) / 2)
- local p = ctx.player
- local w, h = data.atlas.hud:getDimensions('minion')
- local res = {scale = scale, imageScale = is}
- for i = 1, self.count do
- local deck = p.deck[i]
- local yy = v * .005
- res[i] = {x = xx, y = yy}
- local selectFactor = math.lerp(self.prevSelectFactor[i], self.selectFactor[i], ls.accum / ls.tickrate)
- local scale = 1 + .6 * upgradeFactor + .1 * selectFactor
- local is = (.2 * scale * v) / h
- res[i].selectFactor = selectFactor
- res[i].scale = scale
- res[i].imageScale = is
- -- Background
- res[i].bg = {xx, yy, 0, is, is, w / 2, 0}
- -- Title bar
- local w, h = atlas:getDimensions('title')
- local tx = xx - (w / 2) * is
- local ty = yy + (10 * is)
- local xsc = is * (1 - (deck.cooldown / deck.maxCooldown))
- res[i].title = {xx, ty, 0, is, is, w / 2, 0}
- -- Runes
- do
- local runes = {}
- local ct = 3
- local size = v * .04 * scale
- local inc = size + .01 * v * scale
- local xx = xx - (inc * (ct - 1) / 2)
- local yy = yy + .174 * v * scale
- for j = 1, 3 do
- local rune = p.deck[i].runes and p.deck[i].runes[j]
- if rune then
- runes[j] = {}
- -- Stone
- local w, h = atlas:getDimensions('runeBg' .. rune.background:capitalize())
- local scale = size / h
- runes[j].bg = {'runeBg' .. rune.background:capitalize(), xx, yy, 0, scale, scale, w / 2, h / 2}
- -- Rune
- local w, h = atlas:getDimensions('rune' .. rune.image)
- local scale = (size * .5) / h
- runes[j].rune = {'rune' .. rune.image, xx, yy, 0, scale, scale, w / 2, h / 2}
- end
- xx = xx + inc
- end
- res[i].runes = runes
- end
- xx = xx + inc
- end
- return res
- end,
- upgrades = function()
- local u, v = ctx.hud.u, ctx.hud.v
- local p = ctx.player
- local upgradeFactor, t = ctx.hud.upgrades:getFactor()
- local inc = .1 * upgradeFactor * v
- local yy = (.15 * upgradeFactor) * v + (.35 * v)
- local size = math.max(.08 * v * upgradeFactor, .01)
- local units = self.geometry.units
- local res = {}
- for i = 1, self.count do
- res[i] = {}
- local xx = units[i].x
- for j, upgrade in ipairs(data.unit[p.deck[i].code].upgrades) do
- local line = {}
- if upgrade.connectedTo then
- table.each(upgrade.connectedTo, function(other, k)
- local connection = data.unit[p.deck[i].code].upgrades[other]
- line[k] = {xx + (inc * upgrade.x), yy + (.1 * v * upgrade.y), xx + (inc * connection.x), yy + (.1 * v * connection.y)}
- end)
- end
- table.insert(res[i], {xx + (inc * upgrade.x) - size / 2, yy + (.1 * v * upgrade.y) - size / 2, size, size, line})
- end
- end
- return res
- end,
- attributes = function()
- local u, v = ctx.hud.u, ctx.hud.v
- local upgradeFactor, t = ctx.hud.upgrades:getFactor()
- local inc = .1 * upgradeFactor * v
- local yy = (.15 * upgradeFactor) * v + (.25 * v)
- local size = math.max(.08 * v * upgradeFactor, .01)
- local units = self.geometry.units
- local res = {}
- for i = 1, self.count do
- res[i] = {}
- local x = units[i].x - (inc * (4 - 1) / 2)
- for j = 1, 4 do
- table.insert(res[i], {x - size / 2, yy - size / 2, size, size})
- x = x + inc
- end
- end
- return res
- end
- }
- self:ready()
- end
- function HudUnits:update()
- local p = ctx.player
- for i = 1, #self.selectFactor do
- self.prevSelectFactor[i] = self.selectFactor[i]
- self.selectFactor[i] = math.lerp(self.selectFactor[i], p.deck[i].selected and 1 or (p.summonSelect == i and .5 or 0), math.min(8 * ls.tickrate, 1))
- if self.selectFactor[i] > .01 and self.selectFactor[i] < .99 then table.clear(self.geometry) end
- end
- for i = 1, #self.cooldownPop do
- self.prevCooldownPop[i] = self.cooldownPop[i]
- self.cooldownPop[i] = math.lerp(self.cooldownPop[i], 0, math.min(12 * ls.tickrate, 1))
- end
- local _, t = ctx.hud.upgrades:getFactor()
- if t ~= 0 and t ~= 1 then ctx:mousemoved(love.mouse.getPosition()) end
- end
- function HudUnits:draw()
- if ctx.ded or not ctx.tutorial:shouldShowHudUnits() then return end
- local u, v = ctx.hud.u, ctx.hud.v
- local upgradeFactor, t = ctx.hud.upgrades:getFactor()
- if t > 0 and t < 1 then table.clear(self.geometry) end
- self:drawBackground()
- self:drawForeground()
- end
- function HudUnits:drawBackground()
- local u, v = ctx.hud.u, ctx.hud.v
- local ct = self.count
- local p = ctx.player
- local upgradeFactor, t = ctx.hud.upgrades:getFactor()
- local upgradeAlphaFactor = (t / ctx.hud.upgrades.maxTime) ^ 3
- local units = self.geometry.units
- self.spriteBatch:bind()
- if upgradeFactor > 0 then
- g.setColor(0, 0, 0, 80 * math.clamp(upgradeFactor, 0, 1))
- g.rectangle('fill', 0, 0, u, v)
- end
- for i = 1, #units do
- local unit = units[i]
- local xx, yy = unit.x, unit.y
- local deck = p.deck[i]
- local selectFactor = math.lerp(self.prevSelectFactor[i], self.selectFactor[i], ls.accum / ls.tickrate)
- local alpha = .45 + selectFactor * .35
- -- Backdrop
- g.setColor(255, 255, 255, 255 * alpha)
- self:batch('bg' .. i, 'minion', unpack(unit.bg))
- -- Cooldown
- g.setColor(255, 255, 255, 80 * alpha)
- local x, y, a, sx, sy, ox, oy = unpack(unit.title)
- self:batch('title' .. i, 'title', x, y, a, sx, sy, ox, oy)
- g.setColor(255, 255, 255, 255 * alpha)
- local cd = 1 - (deck.cooldown / deck.maxCooldown)
- self:batch('titleBar' .. i, 'title', x - ox * sx, y, a, sx * cd, sy)
- -- Runes
- for j = 1, 3 do
- if unit.runes[j] then
- g.setColor(255, 255, 255)
- self:batch('runeBg' .. i .. j, unpack(unit.runes[j].bg))
- g.setColor(config.runes.colors[deck.runes[j].color])
- self:batch('rune' .. i .. j, unpack(unit.runes[j].rune))
- end
- end
- end
- if t > 0 then
- -- Attributes
- local attributes = self.geometry.attributes
- for i = 1, #attributes do
- for j = 1, #attributes[i] do
- local x, y, w, h = unpack(attributes[i][j])
- local attribute = config.attributes.list[j]
- local scale = w / data.atlas.hud:getDimensions('frame')
- local val = (p.juju >= 30 + 20 * data.unit[p.deck[i].code].attributes[attribute]) and 255 or 150
- x, y = math.round(x), math.round(y)
- -- Frame
- g.setColor(val, val, val, 255 * upgradeAlphaFactor)
- self:batch('attributeFrame' .. i .. j, 'frame', x, y, 0, scale, scale)
- local image = data.media.graphics.hud.icons[attribute]
- if image then
- local scale = math.min((w - (v * .03)) / image:getWidth(), (h - (v * .03)) / image:getHeight())
- local code = 'attributeIcon' .. i .. j
- g.setColor(255, 255, 255, 255 * upgradeAlphaFactor)
- self:batch(code, attribute, x + w / 2, y + h / 2, 0, scale, scale, image:getWidth() / 2, image:getHeight() / 2)
- end
- end
- end
- -- Upgrade Connectors
- local upgrades = self.geometry.upgrades
- g.setLineWidth(2)
- for i = 1, #upgrades do
- for j = 1, #upgrades[i] do
- local who, what = p.deck[i].code, data.unit[p.deck[i].code].upgrades[j].code
- local _, _, _, _, line = unpack(upgrades[i][j])
- local upgrade = data.unit[who].upgrades[what]
- if line and #line > 0 then
- table.each(line, function(points, k)
- local other = data.unit[p.deck[i].code].upgrades[upgrade.connectedTo[k]]
- if other.level >= upgrade.prerequisites[other.code] then
- g.setColor(0, ctx.options.colorblind and 0 or 200, ctx.options.colorblind and 200 or 0, 200 * upgradeAlphaFactor ^ 2)
- else
- g.setColor(200, 0, 0, 200 * upgradeAlphaFactor ^ 2)
- end
- local xscale = .005 * v
- local yscale = math.distance(unpack(points)) / 20
- local angle = math.direction(unpack(points)) - math.pi / 2
- self:batch('upgradeConector' .. i .. j .. k, 'healthbarBar', points[1], points[2], angle, xscale, yscale, .5, 0)
- end)
- end
- end
- end
- g.setLineWidth(1)
- -- Upgrades
- local upgrades = self.geometry.upgrades
- for i = 1, #upgrades do
- for j = 1, #upgrades[i] do
- local who, what = p.deck[i].code, data.unit[p.deck[i].code].upgrades[j].code
- local x, y, w, h = unpack(upgrades[i][j])
- local scale = w / data.atlas.hud:getDimensions('frame')
- local upgrade = data.unit[who].upgrades[what]
- local val = (upgrade.level > 0 or ctx.upgrades.canBuy(who, what)) and 255 or 150
- x, y = math.round(x), math.round(y)
- -- Frame
- g.setColor(val, val, val, 255 * upgradeAlphaFactor)
- self:batch('upgradeFrame' .. i .. j, 'frame', x, y, 0, scale, scale)
- -- Icon
- local qw, qh = data.atlas.hud:getDimensions(what)
- if qw and qh then
- local val = (upgrade.level > 0 or ctx.upgrades.canBuy(who, what)) and 255 or 200
- local scale = math.min((w - (v * .02)) / qw, (h - (v * .02)) / qh)
- local x, y = x + w / 2, y + h / 2
- local ox, oy = qw / 2, qh / 2
- local code = 'upgradeIcon' .. i .. j
- g.setColor(val, val, val, 255 * upgradeAlphaFactor)
- self:batch(code, what, x, y, 0, scale, scale, ox, oy)
- end
- end
- end
- end
- self.spriteBatch:unbind()
- g.draw(self.spriteBatch)
- end
- function HudUnits:drawForeground()
- local u, v = ctx.hud.u, ctx.hud.v
- local mx, my = ctx.view:frameMouseX(), ctx.view:frameMouseY()
- local p = ctx.player
- local atlas = data.atlas.hud
- local upgradeFactor, t = ctx.hud.upgrades:getFactor()
- local upgradeAlphaFactor = (t / ctx.hud.upgrades.maxTime) ^ 3
- local units = self.geometry.units
- for i = 1, #units do
- local unit = units[i]
- local xx, yy = unit.x, unit.y
- local deck = p.deck[i]
- local alpha = .45 + unit.selectFactor * .35
- local scale = unit.scale
- local imageScale = unit.imageScale
- -- Cooldown
- local cooldownPop = math.lerp(self.prevCooldownPop[i], self.cooldownPop[i], ls.accum / ls.tickrate)
- g.setBlendMode('additive')
- g.setColor(255, 255, 255, 200 * cooldownPop)
- g.draw(atlas.texture, atlas.quads.title, unpack(unit.title))
- g.setBlendMode('alpha')
- -- Animation
- g.setCanvas(self.canvas)
- self.canvas:clear(0, 0, 0, 0)
- g.pop()
- self.animations[i]:draw(100, 100)
- ctx.view:guiPush()
- g.setCanvas()
- g.setColor(255, 255, 255)
- g.draw(self.canvas, xx, yy + .1 * scale * v, 0, imageScale, imageScale, 100, 100)
- -- Text
- local x, y, a, sx, sy, ox, oy = unpack(unit.title)
- local w, h = data.atlas.hud:getDimensions('title')
- local unit = data.unit[p.deck[i].code]
- local font = g.setFont('mesmerize', math.round(.02 * scale * v))
- local str = unit.name
- local unitCount = #ctx.units:filter(function(u) return u.player end)
- local cost = unit.cost * (unitCount == 0 and 0 or 1)
- if math.inside(mx, my, x - ox * sx, y, w * sx, h * sy) then
- str = string.format('%.2f', p.deck[i].cooldown)
- end
- g.setColor(255, 255, 255)
- g.printShadow(str, math.round(xx), math.round(yy + (.025 * v * scale)), true)
- g.printShadow(cost, xx - (.091 * v * scale), yy + (.0975 * v * scale), true, {0, 100, 0, 200})
- local count = table.count(ctx.units:filter(function(u) return u.class.code == p.deck[i].code end))
- g.printShadow(count, xx + (.087 * v * scale), yy + (.1 * v * scale), true, {0, 100, 0, 200})
- end
- if t > 0 then
- -- Attribute text
- local attributes = self.geometry.attributes
- for i = 1, #attributes do
- for j = 1, #attributes[i] do
- local x, y, w, h = unpack(attributes[i][j])
- local attribute = config.attributes.list[j]
- local level = data.unit[p.deck[i].code].attributes[attribute]
- g.setFont('mesmerize', math.round(.0175 * v))
- g.setColor(200, 200, 200, 255 * upgradeAlphaFactor)
- g.printShadow(level, x + .01 * v, y + .005 * v)
- end
- end
- -- Upgrade outlines
- local upgrades = self.geometry.upgrades
- for i = 1, #upgrades do
- for j = 1, #upgrades[i] do
- local x, y, w, h = unpack(upgrades[i][j])
- local who, what = p.deck[i].code, data.unit[p.deck[i].code].upgrades[j].code
- local upgrade = data.unit[who].upgrades[what]
- -- Upgrade progress test
- local ct = upgrade.maxLevel
- local size = .008 * v
- local inc = w / ct
- local yy = (y + h / 2) - (inc * (ct - 1) / 2)
- for i = 1, ct do
- g.setColor(upgrade.level >= i and {100, 255, 100, 255 * upgradeAlphaFactor} or {255, 255, 255, 100 * upgradeAlphaFactor})
- local image = data.media.graphics.particles.softCircle
- local scale = size / image:getWidth()
- g.draw(image, x + .005 * v, yy, 0, scale, scale, image:getWidth() / 2, image:getHeight() / 2)
- yy = yy + inc
- end
- end
- end
- end
- end
- function HudUnits:mousereleased(mx, my, b)
- if ctx.ded then return end
- if not ctx.tutorial:shouldShowHudUnits() or not ctx.tutorial:shouldPurchaseUpgrade() then return end
- if b ~= 'l' then return end
- local p = ctx.player
- -- Upgrade click
- local upgrades = self.geometry.upgrades
- for i = 1, #upgrades do
- for j = 1, #upgrades[i] do
- local who, what = p.deck[i].code, data.unit[p.deck[i].code].upgrades[j].code
- local x, y, w, h = unpack(upgrades[i][j])
- if math.inside(mx, my, x, y, w, h) then
- local upgrade = data.unit[who].upgrades[what]
- local nextLevel = upgrade.level + 1
- if ctx.upgrades.canBuy(who, what) and p:spend(upgrade.costs[nextLevel]) then
- ctx.upgrades.unlock(who, what)
- ctx.sound:play('upgrade')
- ctx.particles:emit('upgrade', mx, my, 10)
- else
- ctx.sound:play('misclick')
- end
- end
- end
- end
- -- Attribute click
- local attributes = self.geometry.attributes
- for i = 1, #attributes do
- for j = 1, #attributes[i] do
- local who, what = p.deck[i].code, config.attributes.list[j]
- local x, y, w, h = unpack(attributes[i][j])
- if math.inside(mx, my, x, y, w, h) then
- if ctx.upgrades.canBuyAttribute(who, what) and p:spend(data.unit[who].attributeCosts[what]) then
- ctx.upgrades.unlockAttribute(who, what)
- ctx.sound:play('upgrade')
- ctx.particles:emit('upgrade', mx, my, 10)
- else
- ctx.sound:play('misclick')
- end
- end
- end
- end
- end
- function HudUnits:mousemoved(mx, my)
- if not ctx.tutorial:shouldShowHudUnits() then return end
- local p = ctx.player
- -- Attribute tooltips
- local attributes = self.geometry.attributes
- for i = 1, #attributes do
- for j = 1, #attributes[i] do
- local attribute = config.attributes.list[j]
- local x, y, w, h = unpack(attributes[i][j])
- if math.inside(mx, my, x, y, w, h) then
- ctx.hud.tooltip:setAttributeTooltip(attribute, p.deck[i].code)
- return
- end
- end
- end
- -- Upgrade tooltips
- local upgrades = self.geometry.upgrades
- for i = 1, #upgrades do
- for j = 1, #upgrades[i] do
- local who, what = p.deck[i].code, data.unit[p.deck[i].code].upgrades[j].code
- local x, y, w, h = unpack(upgrades[i][j])
- if math.inside(mx, my, x, y, w, h) then
- ctx.hud.tooltip:setUpgradeTooltip(who, what)
- return
- end
- end
- end
- -- Rune/Unit tooltips
- local units = self.geometry.units
- for i = 1, #units do
- local unit = units[i]
- local size = .09 * ctx.hud.v * unit.scale
- if math.inside(mx, my, unit.x - size / 2, unit.y + .096 * unit.scale * ctx.hud.v - size / 2, size, size) then
- ctx.hud.tooltip:setUnitTooltip(p.deck[i].code)
- end
- for j = 1, 3 do
- local rune = unit.runes[j]
- local w, h = data.atlas.hud:getDimensions('runeBgNormal')
- if rune then
- local x, y, w, h = rune.bg[2], rune.bg[3], rune.bg[5] * w, rune.bg[6] * h
- if math.inside(mx, my, x - w / 2, y - h / 2, w, h) then
- ctx.hud.tooltip:setRuneTooltip(p.deck[i].runes[j])
- return
- end
- end
- end
- end
- end
- function HudUnits:ready()
- local p = ctx.player
- self.count = #p.deck
- self.selectFactor = {}
- self.prevSelectFactor = {}
- self.cooldownPop = {}
- self.prevCooldownPop = {}
- self.animations = {}
- self.canvas = g.newCanvas(200, 200)
- self.spriteBatch = g.newSpriteBatch(data.atlas.hud.texture, 512, 'stream')
- self.spriteBatchMap = {}
- local animationScaleFactors = {
- bruju = 1.5,
- thuju = .85,
- xuju = .85,
- kuju = .85
- }
- local animationOffsets = {
- bruju = -12,
- thuju = -16,
- xuju = -24,
- kuju = -16
- }
- for i = 1, self.count do
- self.selectFactor[i] = 0
- self.prevSelectFactor[i] = self.selectFactor[i]
- self.cooldownPop[i] = 0
- self.prevCooldownPop[i] = self.cooldownPop[i]
- local code = p.deck[i].code
- local animation = data.animation[code]
- local scale = animation.scale * animationScaleFactors[code]
- local offsety = animation.offsety + animationOffsets[code]
- self.animations[i] = data.animation[p.deck[i].code]({scale = scale, offsety = offsety})
- self.animations[i]:on('complete', function()
- self.animations[i]:set('idle', {force = true})
- end)
- end
- end
- function HudUnits:batch(code, quad, ...)
- local id = self.spriteBatchMap[code]
- self.spriteBatch:setColor(love.graphics.getColor())
- if id then
- self.spriteBatch:set(id, data.atlas.hud.quads[quad], ...)
- else
- self.spriteBatchMap[code] = self.spriteBatch:add(data.atlas.hud.quads[quad], ...)
- end
- end
|