- ddr special logic seems to be working in solation
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
This commit is contained in:
@@ -3,27 +3,35 @@
|
|||||||
--- Stops current music.
|
--- Stops current music.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.music_stop() music() end
|
function Audio.music_stop() music() end
|
||||||
|
|
||||||
--- Plays main menu music.
|
--- Plays main menu music.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.music_play_mainmenu() end
|
function Audio.music_play_mainmenu() end
|
||||||
|
|
||||||
--- Plays waking up music.
|
--- Plays waking up music.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.music_play_wakingup() end
|
function Audio.music_play_wakingup() end
|
||||||
|
|
||||||
--- Plays room morning music.
|
--- Plays room morning music.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.music_play_room_morning() end
|
function Audio.music_play_room_morning() end
|
||||||
|
|
||||||
--- Plays room street 1 music.
|
--- Plays room street 1 music.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.music_play_room_street_1() end
|
function Audio.music_play_room_street_1() end
|
||||||
|
|
||||||
--- Plays room street 2 music.
|
--- Plays room street 2 music.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.music_play_room_street_2() end
|
function Audio.music_play_room_street_2() end
|
||||||
|
|
||||||
--- Plays room music.
|
--- Plays room music.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.music_play_room_() end
|
function Audio.music_play_room_() end
|
||||||
|
|
||||||
--- Plays room work music.
|
--- Plays room work music.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.music_play_room_work() music(0) end
|
function Audio.music_play_room_work() music(0) end
|
||||||
|
|
||||||
--- Plays activity work music.
|
--- Plays activity work music.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.music_play_activity_work() music(1) end
|
function Audio.music_play_activity_work() music(1) end
|
||||||
@@ -31,18 +39,28 @@ function Audio.music_play_activity_work() music(1) end
|
|||||||
--- Plays select sound effect.
|
--- Plays select sound effect.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.sfx_select() sfx(17, 'C-7', 30) end
|
function Audio.sfx_select() sfx(17, 'C-7', 30) end
|
||||||
|
|
||||||
--- Plays deselect sound effect.
|
--- Plays deselect sound effect.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.sfx_deselect() sfx(18, 'C-7', 30) end
|
function Audio.sfx_deselect() sfx(18, 'C-7', 30) end
|
||||||
|
|
||||||
--- Plays beep sound effect.
|
--- Plays beep sound effect.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.sfx_beep() sfx(19, 'C-6', 30) end
|
function Audio.sfx_beep() sfx(19, 'C-6', 30) end
|
||||||
|
|
||||||
--- Plays success sound effect.
|
--- Plays success sound effect.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.sfx_success() sfx(16, 'C-7', 60) end
|
function Audio.sfx_success() sfx(16, 'C-7', 60) end
|
||||||
|
|
||||||
--- Plays bloop sound effect.
|
--- Plays bloop sound effect.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.sfx_bloop() sfx(21, 'C-3', 60) end
|
function Audio.sfx_bloop() sfx(21, 'C-3', 60) end
|
||||||
|
|
||||||
--- Plays alarm sound effect.
|
--- Plays alarm sound effect.
|
||||||
--- @within Audio
|
--- @within Audio
|
||||||
function Audio.sfx_alarm() sfx(61) end
|
function Audio.sfx_alarm() sfx(61) end
|
||||||
|
|
||||||
|
--- Plays sound effect for arrow hit
|
||||||
|
--- @within Audio
|
||||||
|
--- @param note string The note for the sound to play
|
||||||
|
function Audio.sfx_arrowhit(note) sfx(56, note) end
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ Decision.register({
|
|||||||
Util.go_to_screen_by_id("work")
|
Util.go_to_screen_by_id("work")
|
||||||
MinigameDDRWindow.start("game", nil, {
|
MinigameDDRWindow.start("game", nil, {
|
||||||
on_win = function()
|
on_win = function()
|
||||||
if (Context.minigame_ddr.special_condition_met and Context.ascension.level == 1) then
|
if (Context.minigame_ddr.special_mode_condition and Context.ascension.level == 1) then
|
||||||
Context.should_ascend = true
|
Context.should_ascend = true
|
||||||
Context.minigame_ddr.special_condition_met = false
|
Context.minigame_ddr.special_mode_condition = false
|
||||||
end
|
end
|
||||||
Meter.show()
|
Meter.show()
|
||||||
Util.go_to_screen_by_id("office")
|
Util.go_to_screen_by_id("office")
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
Decision.register({
|
Decision.register({
|
||||||
id = "play_ddr",
|
id = "play_ddr",
|
||||||
label = "Play DDR (Random)",
|
label = "Play DDR (Random)",
|
||||||
handle = function() Meter.hide() MinigameDDRWindow.start("game", nil) end,
|
handle = function()
|
||||||
|
Meter.hide()
|
||||||
|
MinigameDDRWindow.start("game", nil)
|
||||||
|
end,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
--- Draws a unified win message overlay.
|
--- Draws a unified win message overlay.
|
||||||
--- @within Minigame
|
--- @within Minigame
|
||||||
function Minigame.draw_win_overlay()
|
function Minigame.draw_win_overlay(win_text)
|
||||||
local text = "SUCCESS"
|
local text = win_text or "SUCCESS"
|
||||||
local tw = #text * 6
|
local tw = #text * 6
|
||||||
local th = 6
|
local th = 6
|
||||||
local padding = 4
|
local padding = 4
|
||||||
|
|||||||
@@ -40,3 +40,30 @@ function Util.contains(t, value)
|
|||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Deep copies tables
|
||||||
|
--- @within Util
|
||||||
|
--- @param orig any The value to deep copy.
|
||||||
|
--- @param seen any Used for recursive calls to handle loops
|
||||||
|
--- @return any any The copied object
|
||||||
|
function Util.deepcopy(orig, seen)
|
||||||
|
if type(orig) ~= "table" then
|
||||||
|
return orig
|
||||||
|
end
|
||||||
|
|
||||||
|
if seen and seen[orig] then
|
||||||
|
return seen[orig] -- handle cycles / shared refs
|
||||||
|
end
|
||||||
|
|
||||||
|
local copy = {}
|
||||||
|
seen = seen or {}
|
||||||
|
seen[orig] = copy
|
||||||
|
|
||||||
|
for k, v in pairs(orig) do
|
||||||
|
local new_k = Util.deepcopy(k, seen)
|
||||||
|
local new_v = Util.deepcopy(v, seen)
|
||||||
|
copy[new_k] = new_v
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable(copy, getmetatable(orig))
|
||||||
|
end
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ end
|
|||||||
function MenuWindow.ddr_test()
|
function MenuWindow.ddr_test()
|
||||||
AudioTestWindow.init()
|
AudioTestWindow.init()
|
||||||
GameWindow.set_state("minigame_ddr")
|
GameWindow.set_state("minigame_ddr")
|
||||||
MinigameDDRWindow.start("menu", "generated")
|
MinigameDDRWindow.start("menu", "generated", { special_mode = "only_nothing" })
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Refreshes menu items.
|
--- Refreshes menu items.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ function MinigameDDRWindow.init_context()
|
|||||||
local total_width = (4 * arrow_size) + (3 * arrow_spacing)
|
local total_width = (4 * arrow_size) + (3 * arrow_spacing)
|
||||||
local start_x = (Config.screen.width - total_width) / 2
|
local start_x = (Config.screen.width - total_width) / 2
|
||||||
return {
|
return {
|
||||||
special_type = "normal", -- "normal", "only_special", "only_left", "only_nothing"
|
special_mode = "normal", -- "normal", "only_special", "only_left", "only_nothing"
|
||||||
bar_fill = 0,
|
bar_fill = 0,
|
||||||
max_fill = 100,
|
max_fill = 100,
|
||||||
fill_per_hit = 10,
|
fill_per_hit = 10,
|
||||||
@@ -39,14 +39,90 @@ function MinigameDDRWindow.init_context()
|
|||||||
current_song = nil,
|
current_song = nil,
|
||||||
pattern_index = 1,
|
pattern_index = 1,
|
||||||
use_pattern = false,
|
use_pattern = false,
|
||||||
|
generated_length = 60,
|
||||||
return_window = nil,
|
return_window = nil,
|
||||||
win_timer = 0,
|
win_timer = 0,
|
||||||
on_win = nil,
|
on_win = nil,
|
||||||
special_condition_met = false,
|
|
||||||
total_misses = 0,
|
total_misses = 0,
|
||||||
|
special_mode_condition = true,
|
||||||
|
special_mode_counter = 0
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function MinigameDDRWindow.prepareSong(song, generated_length, special_mode)
|
||||||
|
local current_song = Util.deepcopy(song)
|
||||||
|
|
||||||
|
|
||||||
|
if current_song.generated then
|
||||||
|
local pattern = musicator_generate_pattern(generated_length, current_song.bpm, current_song.spd * 4)
|
||||||
|
current_song.pattern = pattern
|
||||||
|
current_song.end_frame = pattern[#pattern].frame
|
||||||
|
|
||||||
|
if special_mode == "only_special" then
|
||||||
|
local cntr = 1
|
||||||
|
for i, v in ipairs(current_song.pattern) do
|
||||||
|
current_song.pattern[i].special = (i % 5 == 0)
|
||||||
|
end
|
||||||
|
elseif special_mode == "" then
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return current_song
|
||||||
|
end
|
||||||
|
|
||||||
|
function MinigameDDRWindow.on_arrow_hit_special(arrow, game_context)
|
||||||
|
local special_mode = game_context.special_mode
|
||||||
|
|
||||||
|
if special_mode == "normal" then
|
||||||
|
Audio.sfx_arrowhit(arrow.note)
|
||||||
|
elseif special_mode == "only_special" then
|
||||||
|
if arrow.special then
|
||||||
|
Audio.sfx_arrowhit(arrow.note)
|
||||||
|
game_context.special_mode_counter = game_context.special_mode_counter + 1
|
||||||
|
else
|
||||||
|
if game_context.special_mode_condition then Audio.sfx_bloop() end
|
||||||
|
game_context.special_mode_condition = false
|
||||||
|
end
|
||||||
|
elseif special_mode == "only_left" then
|
||||||
|
if arrow.dir == "left" then
|
||||||
|
Audio.sfx_arrowhit(arrow.note)
|
||||||
|
game_context.special_mode_counter = game_context.special_mode_counter + 1
|
||||||
|
else
|
||||||
|
if game_context.special_mode_condition then Audio.sfx_bloop() end
|
||||||
|
game_context.special_mode_condition = false
|
||||||
|
end
|
||||||
|
elseif special_mode == "only_nothing" then
|
||||||
|
if game_context.special_mode_condition then Audio.sfx_bloop() end
|
||||||
|
game_context.special_mode_condition = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function MinigameDDRWindow.on_end(game_context)
|
||||||
|
game_context.win_timer = Config.timing.minigame_win_duration
|
||||||
|
|
||||||
|
local num_special = 0
|
||||||
|
for i,v in ipairs(game_context.current_song.pattern) do
|
||||||
|
if game_context.special_mode == "only_left" then
|
||||||
|
num_special = num_special + ((v.dir == "left" and 1) or 0)
|
||||||
|
else
|
||||||
|
num_special = num_special + ((v.special and 1) or 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local was_ok = true
|
||||||
|
if game_context.special_mode == "normal" then
|
||||||
|
was_ok = game_context.special_mode_counter == num_special
|
||||||
|
elseif game_context.special_mode == "only_special" then
|
||||||
|
was_ok = game_context.special_mode_counter == num_special
|
||||||
|
elseif game_context.special_mode == "only_left" then
|
||||||
|
was_ok = game_context.special_mode_counter == num_special
|
||||||
|
elseif game_context.special_mode == "only_nothing" then
|
||||||
|
-- nothing to do here :D
|
||||||
|
end
|
||||||
|
|
||||||
|
game_context.special_mode_condition = game_context.special_mode_condition and was_ok
|
||||||
|
end
|
||||||
|
|
||||||
--- Initializes DDR minigame state.
|
--- Initializes DDR minigame state.
|
||||||
--- @within MinigameDDRWindow
|
--- @within MinigameDDRWindow
|
||||||
--- @param params table Optional parameters for configuration.<br/>
|
--- @param params table Optional parameters for configuration.<br/>
|
||||||
@@ -73,17 +149,16 @@ function MinigameDDRWindow.start(return_window, song_key, params)
|
|||||||
Context.minigame_ddr.return_window = return_window or "game"
|
Context.minigame_ddr.return_window = return_window or "game"
|
||||||
Context.minigame_ddr.debug_song_key = song_key
|
Context.minigame_ddr.debug_song_key = song_key
|
||||||
if song_key and Songs and Songs[song_key] then
|
if song_key and Songs and Songs[song_key] then
|
||||||
local current_song = Songs[song_key]
|
|
||||||
Context.minigame_ddr.current_song = current_song
|
|
||||||
Context.minigame_ddr.use_pattern = true
|
Context.minigame_ddr.use_pattern = true
|
||||||
Context.minigame_ddr.pattern_index = 1
|
Context.minigame_ddr.pattern_index = 1
|
||||||
Context.minigame_ddr.debug_status = "Pattern loaded: " .. song_key
|
Context.minigame_ddr.debug_status = "Pattern loaded: " .. song_key
|
||||||
|
|
||||||
if current_song.generated then
|
Context.minigame_ddr.current_song = MinigameDDRWindow.prepareSong(
|
||||||
local pattern = musicator_generate_pattern(30, current_song.bpm, current_song.spd * 3)
|
Songs[song_key],
|
||||||
current_song.pattern = pattern
|
Context.minigame_ddr.generated_length,
|
||||||
current_song.end_frame = pattern[#pattern].frame
|
Context.minigame_ddr.special_mode
|
||||||
end
|
)
|
||||||
|
|
||||||
else
|
else
|
||||||
Context.minigame_ddr.use_pattern = false
|
Context.minigame_ddr.use_pattern = false
|
||||||
if song_key then
|
if song_key then
|
||||||
@@ -117,7 +192,7 @@ end
|
|||||||
--- Spawns an arrow in a specific direction.
|
--- Spawns an arrow in a specific direction.
|
||||||
--- @within MinigameDDRWindow
|
--- @within MinigameDDRWindow
|
||||||
--- @param direction string The direction of the arrow ("left", "down", "up", "right").
|
--- @param direction string The direction of the arrow ("left", "down", "up", "right").
|
||||||
local function spawn_arrow_dir(direction, note)
|
local function spawn_arrow_dir(direction, note, special)
|
||||||
local mg = Context.minigame_ddr
|
local mg = Context.minigame_ddr
|
||||||
for _, target in ipairs(mg.target_arrows) do
|
for _, target in ipairs(mg.target_arrows) do
|
||||||
if target.dir == direction then
|
if target.dir == direction then
|
||||||
@@ -125,7 +200,8 @@ local function spawn_arrow_dir(direction, note)
|
|||||||
dir = direction,
|
dir = direction,
|
||||||
x = target.x,
|
x = target.x,
|
||||||
y = mg.bar_y + mg.bar_height + 10,
|
y = mg.bar_y + mg.bar_height + 10,
|
||||||
note = note
|
note = note,
|
||||||
|
special = special
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@@ -183,7 +259,6 @@ function MinigameDDRWindow.update()
|
|||||||
if mg.win_timer > 0 then
|
if mg.win_timer > 0 then
|
||||||
mg.win_timer = mg.win_timer - 1
|
mg.win_timer = mg.win_timer - 1
|
||||||
if mg.win_timer == 0 then
|
if mg.win_timer == 0 then
|
||||||
mg.special_condition_met = (mg.total_misses == 0)
|
|
||||||
Audio.music_stop()
|
Audio.music_stop()
|
||||||
Meter.on_minigame_complete()
|
Meter.on_minigame_complete()
|
||||||
if mg.on_win then
|
if mg.on_win then
|
||||||
@@ -197,7 +272,7 @@ function MinigameDDRWindow.update()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if mg.bar_fill >= mg.max_fill then
|
if mg.bar_fill >= mg.max_fill then
|
||||||
mg.win_timer = Config.timing.minigame_win_duration
|
MinigameDDRWindow.on_end(mg)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -205,7 +280,7 @@ function MinigameDDRWindow.update()
|
|||||||
|
|
||||||
if mg.use_pattern and mg.current_song and mg.current_song.end_frame then
|
if mg.use_pattern and mg.current_song and mg.current_song.end_frame then
|
||||||
if mg.frame_counter > mg.current_song.end_frame and #mg.arrows == 0 then
|
if mg.frame_counter > mg.current_song.end_frame and #mg.arrows == 0 then
|
||||||
mg.win_timer = Config.timing.minigame_win_duration
|
MinigameDDRWindow.on_end(mg)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -216,7 +291,7 @@ function MinigameDDRWindow.update()
|
|||||||
local spawn_entry = pattern[mg.pattern_index]
|
local spawn_entry = pattern[mg.pattern_index]
|
||||||
|
|
||||||
if mg.frame_counter >= spawn_entry.frame then
|
if mg.frame_counter >= spawn_entry.frame then
|
||||||
spawn_arrow_dir(spawn_entry.dir, spawn_entry.note)
|
spawn_arrow_dir(spawn_entry.dir, spawn_entry.note, spawn_entry.special)
|
||||||
mg.pattern_index = mg.pattern_index + 1
|
mg.pattern_index = mg.pattern_index + 1
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
@@ -275,7 +350,7 @@ function MinigameDDRWindow.update()
|
|||||||
local hit = false
|
local hit = false
|
||||||
for i, arrow in ipairs(mg.arrows) do
|
for i, arrow in ipairs(mg.arrows) do
|
||||||
if arrow.dir == dir and check_hit(arrow) then
|
if arrow.dir == dir and check_hit(arrow) then
|
||||||
sfx(56, arrow.note)
|
MinigameDDRWindow.on_arrow_hit_special(arrow, mg)
|
||||||
|
|
||||||
mg.bar_fill = mg.bar_fill + mg.fill_per_hit
|
mg.bar_fill = mg.bar_fill + mg.fill_per_hit
|
||||||
if mg.bar_fill > mg.max_fill then
|
if mg.bar_fill > mg.max_fill then
|
||||||
@@ -337,7 +412,8 @@ function MinigameDDRWindow.draw()
|
|||||||
end
|
end
|
||||||
if mg.arrows then
|
if mg.arrows then
|
||||||
for _, arrow in ipairs(mg.arrows) do
|
for _, arrow in ipairs(mg.arrows) do
|
||||||
draw_arrow(arrow.x, arrow.y, arrow.dir, Config.colors.blue)
|
local arrow_color = arrow.special and Config.colors.white or Config.colors.blue
|
||||||
|
draw_arrow(arrow.x, arrow.y, arrow.dir, arrow_color)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Print.text_center("Hit the arrows!", Config.screen.width / 2, mg.bar_y + mg.bar_height + 10, Config.colors.light_grey)
|
Print.text_center("Hit the arrows!", Config.screen.width / 2, mg.bar_y + mg.bar_height + 10, Config.colors.light_grey)
|
||||||
@@ -365,6 +441,10 @@ function MinigameDDRWindow.draw()
|
|||||||
Print.text_center("RANDOM MODE", Config.screen.width / 2, debug_y, Config.colors.blue)
|
Print.text_center("RANDOM MODE", Config.screen.width / 2, debug_y, Config.colors.blue)
|
||||||
end
|
end
|
||||||
if mg.win_timer > 0 then
|
if mg.win_timer > 0 then
|
||||||
|
if mg.special_mode_condition then
|
||||||
|
Minigame.draw_win_overlay("SUCCESS...?")
|
||||||
|
else
|
||||||
Minigame.draw_win_overlay()
|
Minigame.draw_win_overlay()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user