require 'common.globals' local Dimensions = require 'common.dimensions' local Animation = require 'api.animation' local Animations = { Crit = Animation.new('gameplay/hit_animation_frames/critical_taps', { centered = true, }), Near = Animation.new('gameplay/hit_animation_frames/near_taps', { centered = true, }), HoldCrit = Animation.new('gameplay/hit_animation_frames/hold_critical', { centered = true, loop = true, }), HoldDome = Animation.new('gameplay/hit_animation_frames/hold_dome', { centered = true, loop = true, loopPoint = 10 }), HoldEnd = Animation.new('gameplay/hit_animation_frames/hold_end', { centered = true, }), HoldInner = Animation.new('gameplay/hit_animation_frames/hold_inner', { centered = true, loop = true, }), }; ---@class HoldStateTable ---@field Crit AnimationState ---@field Dome AnimationState ---@field End AnimationState ---@field Inner AnimationState ---@type HoldStateTable[] local holdStateTables = {} for i = 1, 6 do holdStateTables[i] = { Crit = Animations.HoldCrit:createState(), Dome = Animations.HoldDome:createState(), End = Animations.HoldEnd:createState(), Inner = Animations.HoldInner:createState() } end ---@type AnimationState[] local tapStates = {} local HitFX = { }; local function setupLaneTransform(lanePosition, critCenterX, critCenterY) local critLine = gameplay.critLine; local x = critCenterX + (critLine.line.x2 - critLine.line.x1) * lanePosition; local y = critCenterY + (critLine.line.y2 - critLine.line.y1) * lanePosition; Dimensions.setUpTransforms(x, y, -critLine.rotation); end function HitFX.render(deltaTime, critCenterX, critCenterY, critRotation, cursors) local baseHitSize = 325; for i = 1, 6 do local hitSize = baseHitSize; if (i > 4) then hitSize = hitSize * 1.5; end local laneWidth = (track.GetCurrentLaneXPos(2) - track.GetCurrentLaneXPos(1)) * (i <= 4 and 1 or 2); local lanePosition = track.GetCurrentLaneXPos(i) + laneWidth / 2 if (i == 5) then lanePosition = -track.GetCurrentLaneXPos(6) - laneWidth / 2 end -- Holds local isHeld = gameplay.noteHeld[i] local holdStates = holdStateTables[i] local isAnimationPlaying = holdStates.Dome.running if isHeld and not isAnimationPlaying then holdStates.Crit:restart() holdStates.Dome:restart() holdStates.Inner:restart() end if not isHeld and isAnimationPlaying then holdStates.Crit:stop() holdStates.Dome:stop() holdStates.Inner:stop() holdStates.End:restart() end setupLaneTransform(lanePosition, critCenterX, critCenterY) holdStates.Inner:render(deltaTime, { centered = true, width = hitSize, height = hitSize }) holdStates.Dome:render(deltaTime, { centered = true, width = hitSize, height = hitSize }) holdStates.Crit:render(deltaTime, { centered = true, width = hitSize, height = hitSize }) holdStates.End:render(deltaTime, { centered = true, width = hitSize, height = hitSize }) -- Taps local tapState = tapStates[i] if tapState then tapState:render(deltaTime, { centered = true, width = hitSize, height = hitSize, }); end gfx.ResetTransform() end end function HitFX.TriggerAnimation(name, lane) tapStates[lane] = Animations[name]:start(); end return HitFX;