local DonBG = require("background/bg_objects/donbg") local BGNormal = require("background/bg_objects/bg_normal") local BGFever = require("background/bg_objects/bg_fever") local Fever = require("background/bg_objects/fever") local Footer = require("background/bg_objects/footer") local Dancer = require("background/bg_objects/dancer") local RendaController = require("background/bg_objects/renda") local ChibiController = require("background/bg_objects/chibi") local PracticeBackground = require("background/bg_collabs/practice") local TutorialBackground = require("background/bg_collabs/tutorial") local A3Background = require("background/bg_collabs/a3") local AnimalBackground = require("background/bg_collabs/animal") local ButtoBackground = require("background/bg_collabs/buttoburst") local DanBackground = require("background/bg_collabs/dan") local DQ10Background = require("background/bg_collabs/dq10") local FunassyiBackground = require("background/bg_collabs/funassyi") local ImasBackground = require("background/bg_collabs/imas") local ImasSidemBackground = require("background/bg_collabs/imas_sidem") local OshiriBackground = require("background/bg_collabs/oshiri") local COLLABS = { PRACTICE = { PracticeBackground.new, nil, 1 }, TUTORIAL = { TutorialBackground.new, nil, 1 }, A3 = { A3Background.new, "background/collab/a3", 4 }, ANIMAL = { AnimalBackground.new, "background/collab/animal", 5 }, BUTTOBURST = { ButtoBackground.new, "background/collab/buttoburst", 4 }, DAN = { DanBackground.new, "background/collab/dan", 1 }, DQ10 = { DQ10Background.new, "background/collab/dq10", 5 }, FUNASSYI = { FunassyiBackground.new, "background/collab/funassyi", 5 }, IMAS = { ImasBackground.new, "background/collab/imas", 5 }, IMAS_CG = { ImasBackground.new, "background/collab/imas_cg", 3 }, IMAS_ML = { ImasBackground.new, "background/collab/imas_ml", 3 }, IMAS_SIDEM = { ImasSidemBackground.new, "background/collab/imas_sidem", 3 }, OSHIRI = { OshiriBackground.new, "background/collab/oshiri", 5 }, } Background = {} Background.__index = Background function Background.new(player_num, bpm, scene_preset) local self = setmetatable({}, Background) self.player_num = player_num self.bpm = bpm self.scene_preset = scene_preset self.is_2p = (player_num == 3) -- PlayerNum::TWO_PLAYER tex.load_animations("background") local entry = scene_preset and COLLABS[scene_preset] if entry then local ctor, path, max_dancers = entry[1], entry[2], entry[3] if path then self.collab = ctor(player_num, bpm, path, max_dancers) else self.collab = ctor(player_num, bpm) end else -- Standard (non-collab) case local max_dancers = 5 self.max_dancers = max_dancers if self.is_2p then local donbg_index = math.random(1, 6) self.donbg_1 = DonBG.create(1, "background", donbg_index) self.donbg_2 = DonBG.create(2, "background", donbg_index) local skin_cfg = tex.get_skin_config("game_2p_offset") self.p2_y_offset = skin_cfg and skin_cfg.y or 0 self.is_clear_1 = false self.is_clear_2 = false else self.donbg = DonBG.create(player_num, "background") self.bg_normal = BGNormal.create(math.random(0, 4), "background") self.bg_fever = BGFever.create(math.random(0, 3), "background") self.fever = Fever.create(math.random(0, 3), bpm, "background") self.dancer = Dancer.create(math.random(0, 20), bpm, "background", max_dancers) self.footer = Footer.new("background", math.random(0, 2)) end self.renda = RendaController.new("background", math.random(0, 2)) self.chibi = ChibiController.new(bpm, "background") self.is_clear = false self.is_rainbow = false self.last_milestone = 1 end return self end function Background:update(current_ms, bpm) self.bpm = bpm if self.collab then self.collab:update(current_ms, bpm) else if self.is_2p then self.donbg_1:update(current_ms) self.donbg_2:update(current_ms) else self.donbg:update(current_ms) self.bg_normal:update(current_ms) self.bg_fever:update(current_ms) self.fever:update(current_ms, bpm) self.dancer:update(current_ms, bpm) end self.renda:update(current_ms) self.chibi:update(current_ms, bpm) end end function Background:handle_good(player_num) if self.collab then self.collab:handle_good(player_num) else self.chibi:add_chibi(player_num, false) end end function Background:handle_ok(player_num) if self.collab then self.collab:handle_ok(player_num) else self.chibi:add_chibi(player_num, false) end end function Background:handle_bad(player_num) if self.collab then self.collab:handle_bad(player_num) else self.chibi:add_chibi(player_num, true) end end function Background:handle_drumroll(player_num) if self.collab then self.collab:handle_drumroll(player_num) else self.renda:add_renda() end end function Background:handle_balloon(player_num) if self.collab then self.collab:handle_balloon(player_num) else self.renda:add_renda() end end function Background:handle_gauge(player_num, progress, is_clear, is_rainbow) if self.collab then self.collab:handle_gauge(player_num, progress, is_clear, is_rainbow) elseif self.is_2p then -- Update each player's donbg clear state independently if player_num == 1 then self.donbg_1:set_clear(is_clear) self.is_clear_1 = is_clear elseif player_num == 2 then self.donbg_2:set_clear(is_clear) self.is_clear_2 = is_clear end self.is_clear = self.is_clear_1 or self.is_clear_2 self.is_rainbow = is_rainbow else self.donbg:set_clear(is_clear) if is_clear and not self.is_clear then self.bg_fever:start() end if is_rainbow and not self.is_rainbow then self.fever:start() end self.is_clear = is_clear self.is_rainbow = is_rainbow local md = self.max_dancers local current_milestone if is_clear then current_milestone = md else current_milestone = math.min(md - 1, math.floor(progress * md)) end if current_milestone > self.last_milestone then for _ = 1, current_milestone - self.last_milestone do self.dancer:add_dancer() end self.last_milestone = current_milestone elseif current_milestone < self.last_milestone then for _ = 1, self.last_milestone - current_milestone do self.dancer:remove_dancer() end self.last_milestone = current_milestone end end end function Background:draw_back() if self.collab then self.collab:draw_back() else if not self.is_2p then if self.is_clear then if not self.bg_fever.transitioned then self.bg_normal:draw() self.bg_fever:draw() else self.bg_fever:draw() end else self.bg_normal:draw() end end if self.is_2p then self.donbg_1:draw(0) self.donbg_2:draw(self.p2_y_offset) else self.donbg:draw() end self.renda:draw() if not self.is_2p then self.dancer:draw() self.footer:draw() if self.is_rainbow then self.fever:draw() end end self.chibi:draw() end end function Background:draw_fore() if self.collab then self.collab:draw_fore() end end function Background:destroy() if self.collab then self.collab:destroy() else if self.is_2p then self.donbg_1:destroy() self.donbg_2:destroy() else self.donbg:destroy() self.bg_normal:destroy() self.bg_fever:destroy() self.fever:destroy() self.dancer:destroy() self.footer:destroy() end self.renda:destroy() self.chibi:destroy() end end