-- ============================================================ -- Dance Room Solver | Hold attack 500-1000ms after move‑start -- + Beat‑sync start (wait for first bass sound) -- + Extended MOVES table (96 moves) – no special handling -- ============================================================ local player = require("player") -- ===== PERFORMANCE ===== local PERFORMANCE_MODE = false -- false for debug messages local function log(msg) if not PERFORMANCE_MODE then player.addMessage(msg) end end -- ===== CONFIGURATION ===== local TOLERANCE = 0.3 local BASE_MOVE_MS = 1500 local ACTION_DELAY_MS = 0 local JUMP_HOLD_MS = 150 local JUMP_DELAY_MS = 200 local ROTATION_SMOOTH_MS = 400 local FAIL_RESTART_DELAY_MS = 4000 -- Hold attack from 500ms to 1000ms after move‑start local ATTACK_PRESS_MS = 500 local ATTACK_RELEASE_MS = 1000 -- Extra delay after first beat (ms) local BEAT_OFFSET_MS = 0 local MOVE_DEAD = 0.2 local POINTS = { { x = -264.5, z = -107.5 }, { x = -264.5, z = -105.5 }, { x = -262.5, z = -105.5 }, { x = -262.5, z = -107.5 }, } -- ===== MOVES (96 entries – original 48 + 48 extra punch moves) ===== local MOVES = { -- Round 1 { sneak = false, jump = false, punch = false }, { sneak = false, jump = false, punch = false }, { sneak = false, jump = false, punch = false }, { sneak = false, jump = false, punch = false }, -- Round 2 { sneak = false, jump = false, punch = false }, { sneak = true, jump = false, punch = false }, { sneak = false, jump = false, punch = false }, { sneak = true, jump = false, punch = false }, -- Round 3 { sneak = false, jump = false, punch = false }, { sneak = true, jump = false, punch = false }, { sneak = false, jump = false, punch = false }, { sneak = true, jump = false, punch = false }, -- Round 4 { sneak = false, jump = false, punch = false }, { sneak = true, jump = true, punch = false }, { sneak = false, jump = true, punch = false }, { sneak = true, jump = false, punch = false }, -- Round 5 { sneak = false, jump = false, punch = false }, { sneak = true, jump = true, punch = false }, { sneak = false, jump = true, punch = false }, { sneak = true, jump = false, punch = false }, -- Round 6 { sneak = false, jump = false, punch = false }, { sneak = true, jump = true, punch = false }, { sneak = false, jump = true, punch = false }, { sneak = true, jump = false, punch = false }, -- Round 7 { sneak = false, jump = false, punch = false }, { sneak = true, jump = true, punch = false }, { sneak = false, jump = true, punch = false }, { sneak = true, jump = false, punch = false }, -- Round 8 { sneak = false, jump = false, punch = false }, { sneak = true, jump = true, punch = false }, { sneak = false, jump = true, punch = false }, { sneak = true, jump = false, punch = false }, -- Round 9 { sneak = false, jump = false, punch = true }, { sneak = true, jump = true, punch = true }, { sneak = false, jump = true, punch = true }, { sneak = true, jump = false, punch = true }, -- Round 10 { sneak = false, jump = false, punch = true }, { sneak = true, jump = true, punch = true }, { sneak = false, jump = true, punch = true }, { sneak = true, jump = false, punch = true }, -- Round 11 { sneak = false, jump = false, punch = true }, { sneak = true, jump = true, punch = true }, { sneak = false, jump = true, punch = true }, { sneak = true, jump = false, punch = true }, -- Round 12 { sneak = false, jump = false, punch = true }, { sneak = true, jump = true, punch = true }, { sneak = false, jump = true, punch = true }, { sneak = true, jump = false, punch = true }, -- ===== EXTRA LOOP 1 (rounds 9–12 again) ===== { sneak = false, jump = false, punch = true }, { sneak = true, jump = true, punch = true }, { sneak = false, jump = true, punch = true }, { sneak = true, jump = false, punch = true }, { sneak = false, jump = false, punch = true }, } -- ===== GLOBAL STATE ===== _G.DRS_active = false _G.DRS_rotating = false _G.DRS_waitingForBeat = false _G.DRS_moveIndex = 1 _G.DRS_targetPoint = 1 _G.DRS_moving = false _G.DRS_waiting = false _G.DRS_waitUntil = 0 _G.DRS_pending = {} _G.DRS_actionPending = false _G.DRS_actionUntil = 0 _G.DRS_actionMoveIndex = nil _G.DRS_restartScheduled = false _G.DRS_restartTime = 0 _G.DRS_anchorPoint = nil _G.DRS_anchorUntil = 0 local estimatedPing = 0 local lastMoveStartTime = 0 local anchorCheckCounter = 0 local ANCHOR_CHECK_INTERVAL = 2 local function getTimeMs() return os.clock() * 1000 end local function resetMovement() player.input.setPressedForward(false) player.input.setPressedBack(false) player.input.setPressedLeft(false) player.input.setPressedRight(false) end local function resetActions() player.input.setPressedSneak(false) player.input.setPressedJump(false) pcall(function() player.input.setPressedAttack(false) end) end local function resetAll() resetMovement() resetActions() end local function fullReset() _G.DRS_active = false _G.DRS_rotating = false _G.DRS_waitingForBeat = false _G.DRS_moveIndex = 1 _G.DRS_targetPoint = 1 _G.DRS_moving = false _G.DRS_waiting = false _G.DRS_actionPending = false _G.DRS_pending = {} _G.DRS_restartScheduled = false _G.DRS_anchorPoint = nil resetAll() end local function startSmoothRotation(targetYaw, targetPitch) local rot = player.getRotation() _G.DRS_rotStartYaw = rot.yaw _G.DRS_rotStartPitch = rot.pitch _G.DRS_rotTargetYaw = targetYaw _G.DRS_rotTargetPitch = targetPitch _G.DRS_rotStartTime = getTimeMs() _G.DRS_rotating = true log("§bDRS §7>> §eRotating camera...") end local function startDanceSequence() fullReset() if player.getPing and not PERFORMANCE_MODE then estimatedPing = player.getPing() log("§bDRS §7>> §aPing: " .. estimatedPing .. "ms") end startSmoothRotation(180, 90) end local function scheduleRestart() if _G.DRS_restartScheduled then return end _G.DRS_restartScheduled = true _G.DRS_restartTime = getTimeMs() + FAIL_RESTART_DELAY_MS log("§bDRS §7>> §eFailed! Restarting...") end local function onFirstBeat() if not _G.DRS_waitingForBeat then return end _G.DRS_waitingForBeat = false local startDelay = BEAT_OFFSET_MS if startDelay > 0 then local startTime = getTimeMs() + startDelay table.insert(_G.DRS_pending, { time = startTime, action = "start_dance" }) else _G.DRS_active = true _G.DRS_moving = true _G.DRS_targetPoint = 1 _G.DRS_moveIndex = 1 lastMoveStartTime = getTimeMs() log("§bDRS §7>> §aFirst beat detected – dance started") end end local function steerToward(tx, tz) local pos = player.getPos() if not pos then return end local rot = player.getRotation() local yaw_rad = math.rad(rot.yaw) local dx = tx - pos.x local dz = tz - pos.z local fwd = dx * (-math.sin(yaw_rad)) + dz * math.cos(yaw_rad) local right = dx * (-math.cos(yaw_rad)) + dz * (-math.sin(yaw_rad)) player.input.setPressedForward(fwd > MOVE_DEAD) player.input.setPressedBack (fwd < -MOVE_DEAD) player.input.setPressedRight (right > MOVE_DEAD) player.input.setPressedLeft (right < -MOVE_DEAD) end local function arrivedAt(tx, tz) local pos = player.getPos() if not pos then return false end return math.abs(pos.x - tx) < TOLERANCE and math.abs(pos.z - tz) < TOLERANCE end local function applyMove(moveIdx) local m = MOVES[moveIdx] if not m then return end local now = getTimeMs() player.input.setPressedSneak(m.sneak) if m.jump then local pressTime = now + JUMP_DELAY_MS local releaseTime = pressTime + JUMP_HOLD_MS table.insert(_G.DRS_pending, { time = pressTime, action = "jump_press" }) table.insert(_G.DRS_pending, { time = releaseTime, action = "jump_release" }) end if m.punch then local pressTime = now + ATTACK_PRESS_MS local releaseTime = now + ATTACK_RELEASE_MS table.insert(_G.DRS_pending, { time = pressTime, action = "attack_press" }) table.insert(_G.DRS_pending, { time = releaseTime, action = "attack_release" }) if not PERFORMANCE_MODE then player.addMessage(string.format("§7Move %d: attack hold %.0f-%.0f ms", moveIdx, ATTACK_PRESS_MS, ATTACK_RELEASE_MS)) end end if not PERFORMANCE_MODE then player.addMessage(string.format("§7Move %d: sneak=%s jump=%s punch=%s", moveIdx, tostring(m.sneak), tostring(m.jump), tostring(m.punch))) end end registerClientTick(function() local now = getTimeMs() if _G.DRS_restartScheduled and now >= _G.DRS_restartTime then _G.DRS_restartScheduled = false startDanceSequence() return end if _G.DRS_rotating then local elapsed = now - _G.DRS_rotStartTime local t = math.min(1, elapsed / ROTATION_SMOOTH_MS) if t >= 1 then player.setRotation(_G.DRS_rotTargetYaw, _G.DRS_rotTargetPitch) _G.DRS_rotating = false log("§bDRS §7>> §aRotation done – waiting for first beat...") _G.DRS_waitingForBeat = true else local yaw = _G.DRS_rotStartYaw + (_G.DRS_rotTargetYaw - _G.DRS_rotStartYaw) * t local pitch = _G.DRS_rotStartPitch + (_G.DRS_rotTargetPitch - _G.DRS_rotStartPitch) * t player.setRotation(yaw, pitch) end return end if _G.DRS_waitingForBeat then return end if not _G.DRS_active then return end local pendingNew = {} for _, p in ipairs(_G.DRS_pending) do if now >= p.time then if p.action == "jump_press" then player.input.setPressedJump(true) elseif p.action == "jump_release" then player.input.setPressedJump(false) elseif p.action == "attack_press" then pcall(function() player.input.setPressedAttack(true) end) if not PERFORMANCE_MODE then player.addMessage("§bDRS §7>> §aAttack HOLD start") end elseif p.action == "attack_release" then pcall(function() player.input.setPressedAttack(false) end) if not PERFORMANCE_MODE then player.addMessage("§bDRS §7>> §cAttack HOLD stop") end elseif p.action == "start_dance" then _G.DRS_active = true _G.DRS_moving = true _G.DRS_targetPoint = 1 _G.DRS_moveIndex = 1 lastMoveStartTime = now log("§bDRS §7>> §aDance started after beat offset") end else table.insert(pendingNew, p) end end _G.DRS_pending = pendingNew local ANCHOR_TOLERANCE = TOLERANCE local ANCHOR_TOLERANCE_SQ = ANCHOR_TOLERANCE * ANCHOR_TOLERANCE local anchorActive = (_G.DRS_anchorPoint ~= nil and now < _G.DRS_anchorUntil) if anchorActive then anchorCheckCounter = anchorCheckCounter + 1 if anchorCheckCounter >= ANCHOR_CHECK_INTERVAL then anchorCheckCounter = 0 local pos = player.getPos() if pos then local dx = _G.DRS_anchorPoint.x - pos.x local dz = _G.DRS_anchorPoint.z - pos.z local distSq = dx*dx + dz*dz if distSq > ANCHOR_TOLERANCE_SQ then steerToward(_G.DRS_anchorPoint.x, _G.DRS_anchorPoint.z) else resetMovement() end end end else anchorCheckCounter = 0 end if _G.DRS_waiting then if not anchorActive then resetMovement() end if now >= _G.DRS_waitUntil then _G.DRS_waiting = false _G.DRS_anchorPoint = nil resetActions() _G.DRS_targetPoint = (_G.DRS_targetPoint % #POINTS) + 1 _G.DRS_moving = true lastMoveStartTime = now end return end if _G.DRS_actionPending then if not anchorActive then resetMovement() end if now >= _G.DRS_actionUntil then applyMove(_G.DRS_actionMoveIndex) _G.DRS_actionPending = false local arrivalDelay = now - lastMoveStartTime local lagCompensation = math.max(0, arrivalDelay - BASE_MOVE_MS) local adjustedMoveDelay = BASE_MOVE_MS - lagCompensation if adjustedMoveDelay < 500 then adjustedMoveDelay = 500 end _G.DRS_waiting = true _G.DRS_waitUntil = now + adjustedMoveDelay _G.DRS_moveIndex = _G.DRS_moveIndex + 1 if _G.DRS_moveIndex > #MOVES then _G.DRS_active = false resetAll() log("§bDRS §7>> §aDance complete!") end end return end if _G.DRS_moving then local target = POINTS[_G.DRS_targetPoint] if arrivedAt(target.x, target.z) then resetMovement() _G.DRS_moving = false _G.DRS_actionPending = true _G.DRS_actionUntil = now + ACTION_DELAY_MS _G.DRS_actionMoveIndex = _G.DRS_moveIndex _G.DRS_anchorPoint = { x = target.x, z = target.z } _G.DRS_anchorUntil = now + BASE_MOVE_MS else steerToward(target.x, target.z) end return end end) registerSoundPlay(function(info) local nameStr = tostring(info.name or info.id or info or "") if nameStr:find("entity.player.burp") then if _G.DRS_active or _G.DRS_rotating or _G.DRS_waitingForBeat then fullReset() scheduleRestart() end end if nameStr:find("block.note_block.bass") and _G.DRS_waitingForBeat then onFirstBeat() end end) registerCommand("dancer", function(_, args) if args[1] == "start" then if _G.DRS_active or _G.DRS_rotating or _G.DRS_restartScheduled or _G.DRS_waitingForBeat then log("§bDRS §7>> §eAlready running or waiting for beat.") else startDanceSequence() end elseif args[1] == "stop" then fullReset() _G.DRS_restartScheduled = false log("§bDRS §7>> §cStopped.") else log("§bDRS §7>> Use §e/dancer start §7or §e/dancer stop") end end) local mirrorverseDetected = false local autoStartTime = nil registerClientTick(function() local now = getTimeMs() if math.floor(now / 1000) % 1 == 0 then local lines = player.getScoreBoardLines() if lines then local inMirrorverse = false for _, l in ipairs(lines) do if l:find("Mirrorverse") then inMirrorverse = true break end end if inMirrorverse and not mirrorverseDetected then mirrorverseDetected = true log("§bDRS §7>> §aMirrorverse detected! Auto-start in 3 sec...") autoStartTime = now + 3000 elseif not inMirrorverse then mirrorverseDetected = false autoStartTime = nil end end end if autoStartTime and now >= autoStartTime then autoStartTime = nil if not _G.DRS_active and not _G.DRS_rotating and not _G.DRS_restartScheduled and not _G.DRS_waitingForBeat then startDanceSequence() end end end) local modeText = PERFORMANCE_MODE and "Performance mode ON (no messages)" or "Debug mode ON (shows messages)" player.addMessage("§bDRS §7>> " .. modeText .. ". Attack held " .. ATTACK_PRESS_MS .. "-" .. ATTACK_RELEASE_MS .. "ms after move-start.") player.addMessage("§bDRS §7>> Waiting for first bass sound. Use /dancer start")