Skip to content

Commit 4476629

Browse files
committed
Added LLPractice beatmap support
1 parent f1af523 commit 4476629

6 files changed

+357
-1
lines changed

docs/How_To_Setup.md

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
#How To Setup
2+
3+
This page will guide you step-by-step how to run DEPLS2 for the first time. The key of getting DEPLS2 run is not hard, but not easy either.
4+
5+
##System Requirements
6+
7+
Before you proceed, make sure your device comply these requirements
8+
9+
* At least 1.3GHz dual core. More complex storyboard system requires more power and RAM
10+
11+
* At least 256MB of free RAM.
12+
13+
* OpenGL 2.1 (or OpenGLES 2 for Android) capable graphics card
14+
15+
* Windows: Windows Vista or above (sorry Windows XP users)
16+
17+
* Ubuntu: Ubuntu 14.04 - 16.10
18+
19+
* Mac OS X: Mac OS X v10.7 or above.
20+
21+
* Android: Android v2.3 or above.
22+
23+
* **iOS: Not supported!**
24+
25+
##Getting LOVE2D and run DEPLS
26+
27+
If your device comply with requirements above, then proceed. DEPLS2 requires LOVE2D v0.10.0 (or later) game framework. Below are steps to get LOVE2D installed.
28+
29+
###Windows
30+
31+
1. Clone this repository with git or download it as zip. Make sure you extract the zip.
32+
33+
2. Download LOVE2D [here](https://love2d.org/). Zip file is recommended.
34+
35+
3. Extract it somewhere and open command prompt in location where you extracted LOVE2D.
36+
37+
4. Now, type `lovec <DEPLS2 folder>`. If it works correctly, you'll see DEPLS2 main menu.
38+
39+
> `lovec` is available in LOVE2D v0.10.2 and later. It's not hard to create one for older version if you have VS command prompt. To create `lovec`, run `copy love.exe lovec.exe && editbin /SUBSYSTEM:CONSOLE lovec.exe` in VS command prompt.
40+
41+
###Ubuntu
42+
43+
1. Clone this repository with git or download it as zip. Make sure you extract the zip.
44+
45+
2. Add [this PPA](https://launchpad.net/~bartbes/+archive/love-stable) to your apt repository.
46+
47+
3. Type `sudo apt-get update` and `sudo apt-get install love`.
48+
49+
4. Type `love <DEPLS2 folder>`. If it works correctly, you'll see DEPLS2 main menu
50+
51+
###Mac OS X
52+
53+
*TODO: Add Mac OS X instructions*
54+
55+
###Android
56+
57+
1. Clone this repository or download zip. Push all files to somewhere in your phone in `DEPLS-DEPLS2` folder if you download it as ZIP, or simply push all files to your phone except `.git` folder (might be hidden).
58+
59+
2. Download LOVE2D APK from [LOVE2D](https://love2d.org/) website, or from Play Store.
60+
61+
3. Find DEPLS2 `main.lua` in your phone, and open it with LOVE2D
62+
63+
4. If it works, you'll see DEPLS2 main menu, but to play beatmaps, you have to specify it **in command-line**. Well, you can't pass the beatmap name in command-line because there is no such thing in Android, so special steps is required for Android. See below
64+
65+
##Determining DEPLS R/W directory
66+
67+
It's necessary so that you can add beatmaps. If you're under Windows, Ubuntu, or Mac OS X, look at the terminal output (in Windows, use `lovec` instead of `love`). It will write `R/W Directory: <DEPLS2 R/W directory>`. Example in Windows: `R/W Directory: C:/Users/User/AppData/Roaming/LOVE/DEPLS`.
68+
69+
If you're under Android, most of the time it's in `/sdcard/Android/data/org.love2d.android/files/save/DEPLS`. If you didn't see that folder, open a new issue specifying your device. It is because if you run it for the first time, DEPLS will create it's own R/W directory, and guaranteed to be created.
70+
71+
##Adding beatmaps
72+
73+
DEPLS2 supports these beatmap formats:
74+
75+
* DEPLS beatmap folder. It combines CBF format and raw SIF format. Additionaly with storyboard support.
76+
77+
* raw SIF beatmap, without score information. Stripped from SIF response data. This is beatmap format internally used by DEPLS, without any modification. The extension is `.json`
78+
79+
* yuyu live simulator beatmap, the one with `.txt` extension (not `.ssp` one)
80+
81+
* Custom Beatmap Festival project folder. CBF to SIF beatmap conversion will be done, and actually converts it to DEPLS beatmap folder.
82+
83+
* Specialized MIDI file. The extension is `.mid`
84+
85+
* LLPractice beatmap. The extension is `.llp` (make sure to rename it to prevent confusion)
86+
87+
* SIFTrain beatmap. The extension is `.rs`. **Currently disabled due to processing bug**. There's problem in SIFTrain beatmap which causes JSON parse error. This is SIFTrain fault, since DEPLS2 uses JSON library which comply with JSON standards. To fix it, open the beatmap with text editor and add double quote the value in the `music_file`.
88+
89+
DEPLS supports these audio formats
90+
91+
* Raw PCM in WAV container
92+
93+
* Vorbis in OGG container
94+
95+
* MPEG Audio Layer 3/MP3
96+
97+
DEPLS also uses that order to load audio files. So if you have `beatmap.ogg` and `beatmap.wav`, `beatmap.wav` will be loaded because it has higher priority.
98+
99+
Add the beatmap file/folder in `<DEPLS2 R/W directory>/beatmap` and the optionally the audio in `<DEPLS2 R/W directory>/audio`. The audio name must same with the beatmap name, or explictly specify the used audio in the command-line (discussed later).
100+
101+
##Starting beatmap
102+
103+
Note: Beatmap name and audio file is relative to `<DEPLS2 R/W dir>/beatmap/` and `<DEPLS2 R/W dir>/audio/` folder respectively. Specifying audio file argument is optional, and DEPLS will try to load audio in beatmap folder (if it's DEPLS/CBF beatmap folder) or in audio folder with the audio filename same as the beatmap name (and will try to load WAV or OGG audio).
104+
105+
###Android
106+
107+
In Android, write file named `command_line.txt` in DEPLS2 R/W directory with this contents
108+
109+
livesim
110+
<beatmap name without extension>
111+
<used audio with extension (optional)>
112+
113+
Then start DEPLS like the way described above.
114+
115+
###Desktop (Windows, Ubuntu, Mac OS X)
116+
117+
Start LOVE2D with this command-line arguments
118+
119+
love <DEPLS2 folder> livesim <beatmap name without extension> [audio filename with extension]
120+
121+
Note: in windows, use `lovec` instead of `love` to keep the terminal waits for love to exits.
122+
123+
##Example Beatmap
124+
125+
To run example beatmap, the beatmap name must be start with two colons then followed by the example beatmap ID. So it will be
126+
127+
love <DEPLS2 folder> livesim ::<id>
128+
129+
Here is example beatmap IDs:
130+
131+
1. [Daydream Warrior beatmap](https://www.youtube.com/watch?v=PpZqNjv0HUw)
132+
133+
2. [MOMENT RING beatmap](https://www.youtube.com/watch?v=u76q9x7lOzA)
134+
135+
As times goes on, I might add more exampe beatmaps.

docs/Storyborad.md

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
Lua Storyboard
2+
==============
3+
4+
Lua storyboard is simply a Lua script which controls how objects shown behind the simulator.
5+
Please note that Lua script running as Lua storyboard is sandboxed, which means most of `love`
6+
functions doesn't exist in here or modified to prevent alteration of the rendering state, and
7+
to prevent malicious Lua storyboard script writing anywhere.
8+
9+
Storyboard Functions
10+
====================
11+
12+
This function only exist on storyboard lua script.
13+
14+
*************************************************
15+
16+
### `void SetLiveOpacity (number opacity)`
17+
18+
Sets the Live Show! image opacity. This includes unit, header, notes, and more.
19+
20+
Parameters:
21+
22+
* `opacity` - The opacity, range from 0-255. 0 for invisible, 255 for opaque (fully visible)
23+
24+
Returns: *none*
25+
26+
*************************************************
27+
28+
### `void SetBackgroundDimOpacity(number opacity)`
29+
30+
Sets background blackness (but not entirely black)
31+
32+
Parameters:
33+
34+
* `opacity` - Background blackness, from 0-255. 0 for full black (approx. 190 blackness), 255 for full bright
35+
36+
Returns: *none*
37+
38+
*************************************************
39+
40+
### `number GetCurrentElapsedTime()`
41+
42+
Get current elapsed time in DEPLS.
43+
44+
Returns: Elapsed time, in milliseconds. Negative value means simulator is not started yet
45+
46+
*************************************************
47+
48+
### `number GetLiveSimulatorDelay()`
49+
50+
Get live simulator delay. Delay before live simulator is shown
51+
52+
Returns: Live simulator delay, in milliseconds
53+
54+
*************************************************
55+
56+
### `void SpawnCircleTapEffect(number pos [, number r = 255 [, number g = 255 [, number b = 255]]])`
57+
58+
Show circletap effect in the specificed idol position and with specificed color
59+
60+
Parameters:
61+
62+
* `pos` - The idol position. 1 is rightmost, 9 is leftmost
63+
64+
* `r` - Red color component of the circletap (defaults to 255)
65+
66+
* `g` - Green color component of the circletap (defaults to 255)
67+
68+
* `b` - Blue color component of the circletap (defaults to 255)
69+
70+
Returns: *none*
71+
72+
*************************************************
73+
74+
### `Video|nil LoadVideo(string path)`
75+
76+
Load video file. Directory is relative to current beatmap folder
77+
78+
Parameters:
79+
80+
* `path` - Video filename
81+
82+
Returns: love2d `Video` object or `nil` on failure
83+
84+
> For additional sandboxing and compatibility, this is synonym of `love.graphics.newVideo`
85+
86+
*************************************************
87+
88+
### `Image|nil LoadImage(string path)`
89+
90+
Load image. Directory is relative to current beatmap folder
91+
92+
Parameters:
93+
94+
* `path` - Image filename
95+
96+
Returns: love2d `Image` object or `nil` on failure
97+
98+
> For additional sandboxing and compatibility, this is synonym of `love.graphics.newImage`
99+
100+
*************************************************
101+
102+
### `string|nil ReadFile(string path)`
103+
104+
Reads the contents of file. Directory is relative to current beatmap folder
105+
106+
Parameters:
107+
108+
* `path` - File to get it's contents
109+
110+
Returns: The contents of the file, or `nil` on failure

llp2sif.lua

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
-- LLPractice to SIF beatmap converter
2+
3+
--! @brief Converts LLPractice beatmap to SIF beatmap
4+
--! @param llp The LLPractice JSON decoded data to table
5+
--! @returns SIF-compilant beatmap in table
6+
--! @note Modify `LLP_SIFT_DEFATTR` to change default attribute
7+
local llp2sif = function(llp)
8+
local DEPLS = _G.DEPLS
9+
local attribute = DEPLS.LoadConfig("LLP_SIFT_DEFATTR", 1) -- Smile is default
10+
local offset = (llp.offsettime or 0) / 1000 -- In seconds
11+
local sif_map = {}
12+
13+
for n, v in pairs(llp.lane) do
14+
for a, b in pairs(v) do
15+
local new_effect = 1
16+
local new_effect_val = 2
17+
18+
if b.longnote then
19+
new_effect = 3
20+
new_effect_val = (b.endtime - b.starttime) / 1000
21+
end
22+
23+
sif_map[#sif_map + 1] = {
24+
timing_sec = b.starttime / 1000,
25+
notes_attribute = attribute or 1,
26+
notes_level = 1,
27+
effect = new_effect,
28+
effect_value = new_effect_val,
29+
position = 9 - b.lane
30+
}
31+
end
32+
end
33+
34+
table.sort(sif_map, function(a, b) return a.timing_sec < b.timing_sec end)
35+
return sif_map
36+
end
37+
38+
return llp2sif

luastoryboard.lua

+2
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ local isolated_love = {
8888
timer = love.timer
8989
}
9090

91+
-- List of whitelisted libraries for storyboard
9192
local allowed_libs = {
9293
JSON = require("JSON"),
9394
List = require("List"),
@@ -126,6 +127,7 @@ function LuaStoryboard.Load(file)
126127
env.dofile = nil
127128
env.package = nil
128129
env.love = isolated_love
130+
env.file_get_contents = nil
129131
env.require = function(libname)
130132
if allowed_libs[libname] then
131133
return allowed_libs[libname]

note_loader.lua

+31-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ noteloader = function(path)
132132
-- SifSimu beatmap
133133
local sifsimu2sif = require("sifsimu2sif")
134134

135-
-- No longer creates additional JSON
136135
output.notes_list = sifsimu2sif(love.filesystem.getSaveDirectory().."/beatmap/"..path..".txt", love.filesystem.getSaveDirectory().."/beatmap/"..path..".json")
137136
elseif love.filesystem.isFile("beatmap/"..path..".mid") then
138137
-- MIDI beatmap
@@ -143,6 +142,37 @@ noteloader = function(path)
143142
f:close()
144143

145144
output.notes_list = ndata
145+
elseif love.filesystem.isFile("beatmap/"..path..".llp") then
146+
-- LLPractice beatmap
147+
local llp2sif = require("llp2sif")
148+
local ndata = JSON:decode(assert(love.filesystem.newFileData("beatmap/"..path..".llp")):getString())
149+
150+
output.notes_list = llp2sif(ndata)
151+
152+
if ndata.audiofile and #ndata.audiofile > 0 then
153+
output.song_file = DEPLS.LoadAudio("audio/"..ndata.audiofile..".wav")
154+
end
155+
elseif love.filesystem.isFile("beatmap/"..path..".rs") then
156+
-- SIFTrain beatmap
157+
error("SIFTrain beatmap format is currently disabled")
158+
159+
local rs2sif = require("rs2sif")
160+
local ndata = JSON:decode(assert(love.filesystem.newFileData("beatmap/"..path..".rs")):getString())
161+
162+
output.notes_list = rs2sif(ndata)
163+
164+
if ndata.music_file and #ndata.music_file > 0 then
165+
output.song_file = DEPLS.LoadAudio("audio/"..ndata.music_file..".wav")
166+
end
167+
168+
if ndata.rank_info then
169+
output.score = {
170+
ndata.rank_info[1].rank_max,
171+
ndata.rank_info[2].rank_max,
172+
ndata.rank_info[3].rank_max,
173+
ndata.rank_info[4].rank_max
174+
}
175+
end
146176
else
147177
-- Unsupported beatmap
148178
error("Cannot open beatmap \""..path.."\"")

rs2sif.lua

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
-- SIFTrain to SIF beatmap convert
2+
3+
local function hasbit(a, b)
4+
return a % (b * 2) >= b
5+
end
6+
7+
--! @brief Converts SIFTrain beatmap to SIF beatmap
8+
--! @param rs_map The SIFTrain JSON decoded data to table
9+
--! @returns SIF-compilant beatmap in table
10+
--! @note Modify `LLP_SIFT_DEFATTR` to change default attribute
11+
local function rs2sif(rs_map)
12+
local DEPLS = _G.DEPLS
13+
local attribute = DEPLS.LoadConfig("LLP_SIFT_DEFATTR", 1)
14+
local sif_map = {}
15+
16+
rs_map = rs_map.song_info[1].notes
17+
18+
for n, v in pairs(rs_map) do
19+
local new_effect = 1
20+
21+
if hasbit(v.effect, 3) then
22+
new_effect = 3
23+
elseif hasbit(v.effect, 4) then
24+
new_effect = 4
25+
end
26+
27+
table.insert(sif_map, {
28+
timing_sec = v.timing_sec,
29+
notes_attribute = attribute or 1,
30+
notes_level = 1,
31+
effect = new_effect,
32+
effect_value = v.effect_value,
33+
position = v.position
34+
})
35+
end
36+
37+
table.sort(sif_map, function(a, b) return a.timing_sec < b.timing_sec end)
38+
return sif_map
39+
end
40+
41+
return rs2sif

0 commit comments

Comments
 (0)