From df4a678946e2599ddee247667925e6ca325c3794 Mon Sep 17 00:00:00 2001
From: vvo <>
Date: Wed, 15 Nov 2023 20:10:27 +0800
Subject: [PATCH] webui stuff
---
sdvx@asphyxia/README.md | 97 +++---
sdvx@asphyxia/bgm_convert.bat | 3 +-
sdvx@asphyxia/bgm_convert.sh | 1 +
sdvx@asphyxia/data/exg.ts | 4 +-
sdvx@asphyxia/data/webui.ts | 74 +++++
sdvx@asphyxia/handlers/webui.ts | 138 +++++++-
sdvx@asphyxia/webui/asset/js/detail.js | 110 ++++---
sdvx@asphyxia/webui/asset/js/generator.js | 7 +-
.../webui/asset/js/pngjs/bitmapper.js | 267 ++++++++++++++++
.../webui/asset/js/pngjs/bitpacker.js | 158 ++++++++++
.../webui/asset/js/pngjs/chunkstream.js | 189 +++++++++++
.../webui/asset/js/pngjs/constants.js | 32 ++
sdvx@asphyxia/webui/asset/js/pngjs/crc.js | 40 +++
.../webui/asset/js/pngjs/filter-pack.js | 171 ++++++++++
.../asset/js/pngjs/filter-parse-async.js | 24 ++
.../webui/asset/js/pngjs/filter-parse-sync.js | 21 ++
.../webui/asset/js/pngjs/filter-parse.js | 177 +++++++++++
.../webui/asset/js/pngjs/format-normaliser.js | 93 ++++++
.../webui/asset/js/pngjs/interlace.js | 95 ++++++
.../webui/asset/js/pngjs/packer-async.js | 50 +++
.../webui/asset/js/pngjs/packer-sync.js | 56 ++++
sdvx@asphyxia/webui/asset/js/pngjs/packer.js | 129 ++++++++
.../webui/asset/js/pngjs/paeth-predictor.js | 16 +
.../webui/asset/js/pngjs/parser-async.js | 169 ++++++++++
.../webui/asset/js/pngjs/parser-sync.js | 112 +++++++
sdvx@asphyxia/webui/asset/js/pngjs/parser.js | 295 ++++++++++++++++++
.../webui/asset/js/pngjs/png-sync.js | 12 +
sdvx@asphyxia/webui/asset/js/pngjs/png.js | 194 ++++++++++++
.../webui/asset/js/pngjs/sync-inflate.js | 168 ++++++++++
.../webui/asset/js/pngjs/sync-reader.js | 45 +++
sdvx@asphyxia/webui/asset/js/preview.js | 2 +-
.../webui/asset/js/updateResources.js | 16 +-
.../webui/asset/json/customize_data_ext.json | 57 ++--
.../webui/asset/json/valgene_data.json | 7 +
sdvx@asphyxia/webui/profile_--detail.pug | 2 +
sdvx@asphyxia/webui/update webui assets.pug | 25 +-
36 files changed, 2913 insertions(+), 143 deletions(-)
create mode 100644 sdvx@asphyxia/bgm_convert.sh
create mode 100644 sdvx@asphyxia/data/webui.ts
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/bitmapper.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/bitpacker.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/chunkstream.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/constants.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/crc.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/filter-pack.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/filter-parse-async.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/filter-parse-sync.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/filter-parse.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/format-normaliser.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/interlace.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/packer-async.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/packer-sync.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/packer.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/paeth-predictor.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/parser-async.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/parser-sync.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/parser.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/png-sync.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/png.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/sync-inflate.js
create mode 100644 sdvx@asphyxia/webui/asset/js/pngjs/sync-reader.js
diff --git a/sdvx@asphyxia/README.md b/sdvx@asphyxia/README.md
index 418d66a..454a4e7 100644
--- a/sdvx@asphyxia/README.md
+++ b/sdvx@asphyxia/README.md
@@ -1,26 +1,52 @@
# SOUND VOLTEX
-**Plugin Version:** fork-6.0.2.3
+**Plugin Version:** fork-6.0.2.4
-**Supported game versions:** EXCEED GEAR
-
-**Latest supported game datacode:** 2023102400
+**Supported game versions:** EXCEED GEAR (2023102400)
**Unsupported game versions:** Every other game, as they're untested.
**Required Asphyxia Core version** [1.50c](https://github.com/asphyxia-core/asphyxia-core.github.io/releases/tag/v1.50)
**Notes:**
-- This fork enables a few of the features that are added in the later updates of Exceed Gear. However, I still highly recommend using the official stable version of the plugin.
-- Before using this plugin:
- - run the [WebUI Asset Update](/plugin/sdvx@asphyxia/update%20webui%20assets). Do this every data update.
- - go to [Unlocking Events](/plugin/sdvx@asphyxia/unlocking%20events) and click "Apply" at least once. Check out the many options available while you're there.
- - also adjust the plugin settings at the WebUI dashboard to your liking.
-- Don't expect stability, there might be some bugs. Please back up your save data to prevent unwanted issues (just in case)
+- Please be aware that this plugin and the savefile it produces are incompatible with the official plugin, or any other forks. Please be cautious of using other plugins' savefiles with this fork of the plugin, or using this fork's savefile with other plugins.
+- Before using this plugin, run the [WebUI Asset Update](/plugin/sdvx@asphyxia/update%20webui%20assets). Do this every data and plugin update.
+- Please back up your save data to prevent unwanted issues (just in case)
Changelog
===========
+## fork-6.0.2.4
+
+### New:
+
+1. Main:
+ - Updated EG course data (isNew flags)
+2. WebUI:
+ - Profile details
+ - Added display of skill frames (normal or god.) Asset update required.
+ - frame might misalign a bit depending on window size, sorry
+ - Added display of arena rank image. Asset update required.
+ - Added display of your currently selected skill title.
+ - Changed how Megamix rate and Ultimate rate is displayed in arena stats.
+ - Asset update
+ - Added ability to extract images/textures from .ifs files, with file information provided (seen on data/webui.ts.) Used to extract arena/skill course-related textures. Will probably utilize more in the future. Only ifs files used in latest data are supported.
+ - Massive thanks to [mon's ifstools](https://github.com/mon/ifstools), the code where this feature is largely based on.
+ - Added [pngjs library files](https://github.com/pngjs/pngjs) to handle PNG file creation. Couldn't find a more elegant way but this will do for now.
+ - Added course_data.json update using the course data in exg.ts.
+3. Other:
+ - Added bgm_convert.sh file for Linux
+ - Updated bgm_convert.bat
+
+### Fixes:
+1. WebUI
+ - Fixed Japan-exclusive warning not displaying for some Premium Generator sets.
+
+### Todo:
+1. Figure out how to use image (png) files to appear in information/news popup.
+2. More work on online matchmaking (globalMatch.) I can't seem to make clients establish a connection.
+
+
## fork-6.0.2.3
### New:
@@ -37,7 +63,7 @@ Changelog
- (Update webui resources) Added code to extract wma audio from .s3p files. Largely based on [mon's s3p_extract](https://github.com/mon/s3p_extract) code.
3. Others:
- DEMOLOOP_INFORMATION implementation (attract mode announcements images)
- - Updated bgm_convert batch script to remove the need for s3p_extract.
+ - Updated bgm\_convert batch script to remove the need for s3p\_extract.
### Fixes:
@@ -50,12 +76,6 @@ Changelog
- Updated BPL Triple Tribe event category from 'gift' to 'event_online.'
- Added missing matchmaker model file.
-### Todo:
-1. Figure out how to extract textures from .ifs files in TS/JS.
-2. ~~Figure out how to extract audio files from .s3p files in TS/JS~~ Figure out how to convert wma audio to mp3 in JS/TS.
-3. Figure out how to use image (png) files to appear in information/news popup.
-4. More work/research on online matchmaking (globalMatch.) I can't seem to make clients establish a connection.
-
## fork-6.0.2.2
@@ -84,46 +104,3 @@ Changelog
1. Fixes WebUI resource update not adding video submonitor backgrounds. I 100% recommend updating your WebUI assets.
-
-## fork-6.0.2.1
-
-### Fixes:
-
-1. Fixed missing Megamix songs (extend string param getting cut off)
-
-
-## fork-6.0.2.0
-
-### New:
-
-1. Support for EG 2023091200
-2. Added Arena Station 8, 9 and 10.
-3. Added Valkyrie Generator Vol. 12
-4. Added Premium Generator
- - Re:Zero Set 1
- - Re:Zero Set 2
- - Vol. 3
-5. Enabled HEXADIVER 8 and 9
-6. Added option for BPL Team Supporter banner
-7. Added support for System Backgrounds
-8. Added event data:
- - BPL S3 Triple Tribe songs unlock toggle (suspicions, etc.)
- - KAC 2023 song unlock toggle (パーフェクトイーター)
- - KAC 2023 song stamp event (for 累乗のカルマ)
- - KAC 2023 song stamp event (for Stylus & QQ)
-9. Updated licensed songs and valk-exclusive songs list
-10. Skill Analyzer God Mode implementation.
- - Special courses (Red Bull courses, etc.) do not have God Mode courses.
-11. Added and fixed Skill Analyzer course data:
- - Sets 6 and 7
- - BMK2021 courses
- - Spring 2023 courses
- - KAC 2023 Qualifier course sets 1 & 2
-12. Megamix Battle song list update
-
-### Fixes:
-
-1. Reduced songNum value from 3000 to 2100. Potential fix for some users with "unlock all songs" enabled who are experiencing request timeouts resulting in missing features and songs.
-2. Fixed bug in stamp select data.
-3. Fixed bug for when common.ts or profiles.ts is looking for a specific event key but it is undefined.
-3. Skill Analyzer: skill level requirement for Lv.11 and ∞. Song input/unlock status must be met as well, or just use the unlock all songs option in the WebUI.
diff --git a/sdvx@asphyxia/bgm_convert.bat b/sdvx@asphyxia/bgm_convert.bat
index b70e3ac..89fec8d 100644
--- a/sdvx@asphyxia/bgm_convert.bat
+++ b/sdvx@asphyxia/bgm_convert.bat
@@ -1,6 +1,7 @@
@echo off
for /f %%a in ('dir "webui\asset\audio\" /b /s /a-d ^| findstr ".wma"') do (
- ffmpeg -i "%%~fa" -vn -ar 44100 -ac 2 -b:a 192k "%%~dpa%%~na.mp3"
+ echo Converting %%~fa
+ ffmpeg -loglevel error -y -i "%%~fa" -vn -ar 44100 -ac 2 -b:a 192k "%%~dpa%%~na.mp3"
del %%~fa
)
@echo on
\ No newline at end of file
diff --git a/sdvx@asphyxia/bgm_convert.sh b/sdvx@asphyxia/bgm_convert.sh
new file mode 100644
index 0000000..e1ac959
--- /dev/null
+++ b/sdvx@asphyxia/bgm_convert.sh
@@ -0,0 +1 @@
+find . -type f -name "*.wma" -exec bash -c 'echo "Converting $1" && ffmpeg -loglevel error -y -i $1 -vn -ar 44100 -ac 2 -b:a 192k ${1%.wma}.mp3 && rm $1' bash {} \;
diff --git a/sdvx@asphyxia/data/exg.ts b/sdvx@asphyxia/data/exg.ts
index 6d8cbbc..314f2ae 100644
--- a/sdvx@asphyxia/data/exg.ts
+++ b/sdvx@asphyxia/data/exg.ts
@@ -5187,7 +5187,7 @@ export const COURSES6 = [
{
id: 14,
name: 'SKILL ANALYZER 第6回',
- isNew: 1,
+ isNew: 0,
hasGod: 1,
courses: [
{
@@ -5602,7 +5602,7 @@ export const COURSES6 = [
{
id: 16,
name: 'KAC(2023)予選コース',
- isNew: 1,
+ isNew: 0,
courses: [
{
id: 1,
diff --git a/sdvx@asphyxia/data/webui.ts b/sdvx@asphyxia/data/webui.ts
new file mode 100644
index 0000000..467a529
--- /dev/null
+++ b/sdvx@asphyxia/data/webui.ts
@@ -0,0 +1,74 @@
+export const textureslist = [
+ {
+ 'file': '/data/graphics/ver06/arena_rank.ifs',
+ 'asset_folder': 'arena_rank',
+ 'md5': '0311d56e5db4fe276aaab4435cb52354',
+ 'textures': [
+ ['glow.png', 2890640, 16288, [2, 570, 2, 106], [0, 572, 0, 108]],
+ ['mixstar.png', 2712288, 48206, [2, 542, 110, 650], [0, 544, 108, 652]],
+ ['u1.png', 457712, 149908, [574, 1114, 2, 542], [572, 1116, 0, 544]],
+ ['u2.png', 153136, 152586, [1118, 1658, 2, 542], [1116, 1660, 0, 544]],
+ ['u3.png', 0, 153136, [546, 1086, 546, 1086], [544, 1088, 544, 1088]],
+ ['u4.png', 305728, 151974, [1090, 1630, 546, 1086], [1088, 1632, 544, 1088]],
+ ['u.png', 607632, 147016, [2, 542, 654, 1194], [0, 544, 652, 1196]],
+ ['s1.png', 1067584, 102100, [546, 1086, 1090, 1630], [544, 1088, 1088, 1632]],
+ ['s2.png', 860160, 103886, [1090, 1630, 1090, 1630], [1088, 1632, 1088, 1632]],
+ ['s3.png', 754656, 105494, [2, 542, 1198, 1738], [0, 544, 1196, 1740]],
+ ['s4.png', 964048, 103534, [1662, 2202, 2, 542], [1660, 2204, 0, 544]],
+ ['a1.png', 1856768, 93336, [2206, 2746, 2, 542], [2204, 2748, 0, 544]],
+ ['a2.png', 1666144, 96328, [2750, 3290, 2, 542], [2748, 3292, 0, 544]],
+ ['a3.png', 1568784, 97346, [3294, 3834, 2, 542], [3292, 3836, 0, 544]],
+ ['a4.png', 1762480, 94284, [1634, 2174, 546, 1086], [1632, 2176, 544, 1088]],
+ ['b1.png', 2484560, 86781, [2178, 2718, 546, 1086], [2176, 2720, 544, 1088]],
+ ['b2.png', 2220768, 88790, [2722, 3262, 546, 1086], [2720, 3264, 544, 1088]],
+ ['b3.png', 2041344, 90088, [3266, 3806, 546, 1086], [3264, 3808, 544, 1088]],
+ ['b4.png', 2309568, 87663, [1634, 2174, 1090, 1630], [1632, 2176, 1088, 1632]],
+ ['c1.png', 1470944, 97837, [2178, 2718, 1090, 1630], [2176, 2720, 1088, 1632]],
+ ['c2.png', 1271488, 100109, [2722, 3262, 1090, 1630], [2720, 3264, 1088, 1632]],
+ ['c3.png', 1169696, 101777, [3266, 3806, 1090, 1630], [3264, 3808, 1088, 1632]],
+ ['c4.png', 1371600, 99342, [546, 1086, 1634, 2174], [544, 1088, 1632, 2176]],
+ ['d1.png', 2571344, 85426, [1090, 1630, 1634, 2174], [1088, 1632, 1632, 2176]],
+ ['d2.png', 2131440, 89314, [1634, 2174, 1634, 2174], [1632, 2176, 1632, 2176]],
+ ['d3.png', 1950112, 91226, [2178, 2718, 1634, 2174], [2176, 2720, 1632, 2176]],
+ ['d4.png', 2397232, 87321, [2722, 3262, 1634, 2174], [2720, 3264, 1632, 2176]],
+ ['none.png', 2656784, 55490, [3266, 3806, 1634, 2174], [3264, 3808, 1632, 2176]],
+ ['fudawinstat.png', 2922368, 9846, [2, 514, 1742, 1826], [0, 516, 1740, 1828]]
+ ]
+ },
+ {
+ 'file': '/data/graphics/ver06/psd_level.ifs',
+ 'asset_folder': 'difficulty',
+ 'md5': '26ef89b4550cac6156fa78ef4e59e8c3',
+ 'textures': [
+ ['level_small_xcd.png', 193824, 2181, [710, 922, 2, 50], [708, 924, 0, 52]]
+ ]
+ },
+ {
+ 'file': '/data/graphics/ver06/psd_skill.ifs',
+ 'asset_folder': 'skill_lv',
+ 'md5': '9a5684960c0d86cd18f1c64f6e13c98b',
+ 'textures': [
+ ['skill_frame_normal_sp.png', 549552, 45470, [2, 602, 242, 582], [0, 604, 240, 584]],
+ ['skill_frame_normal_silver.png', 884448, 32373, [2, 602, 586, 926], [0, 604, 584, 928]],
+ ['skill_frame_normal_gold.png', 850288, 34158, [610, 1210, 2, 342], [608, 1212, 0, 344]],
+ ['skill_frame_god_sp_none.png', 595024, 40145, [1214, 1814, 2, 342], [1212, 1816, 0, 344]],
+ ['skill_frame_god_sp.png', 195312, 80745, [606, 1206, 346, 686], [604, 1208, 344, 688]],
+ ['skill_frame_god_silver.png', 346064, 53343, [1210, 1810, 346, 686], [1208, 1812, 344, 688]],
+ ['skill_frame_god_gold.png', 276064, 69987, [606, 1206, 690, 1030], [604, 1208, 688, 1032]],
+ ['skill_none.png', 1227792, 10209, [2, 454, 930, 1058], [0, 456, 928, 1060]],
+ ['skill_12.png', 1012656, 20206, [458, 910, 1034, 1162], [456, 912, 1032, 1164]],
+ ['skill_11.png', 1050144, 14880, [914, 1366, 1034, 1162], [912, 1368, 1032, 1164]],
+ ['skill_10.png', 1156848, 12906, [1370, 1822, 1034, 1162], [1368, 1824, 1032, 1164]],
+ ['skill_09.png', 1169760, 12873, [2, 454, 1062, 1190], [0, 456, 1060, 1192]],
+ ['skill_08.png', 1091424, 13181, [458, 910, 1166, 1294], [456, 912, 1164, 1296]],
+ ['skill_07.png', 1065024, 13193, [914, 1366, 1166, 1294], [912, 1368, 1164, 1296]],
+ ['skill_06.png', 1078224, 13189, [1370, 1822, 1166, 1294], [1368, 1824, 1164, 1296]],
+ ['skill_05.png', 1104608, 13144, [2, 454, 1194, 1322], [0, 456, 1192, 1324]],
+ ['skill_04.png', 1182640, 12353, [458, 910, 1298, 1426], [456, 912, 1296, 1428]],
+ ['skill_03.png', 1117760, 13079, [914, 1366, 1298, 1426], [912, 1368, 1296, 1428]],
+ ['skill_02.png', 1130848, 13045, [1370, 1822, 1298, 1426], [1368, 1824, 1296, 1428]],
+ ['skill_01.png', 1143904, 12943, [2, 454, 1326, 1454], [0, 456, 1324, 1456]],
+ ['skill_00.png', 1217568, 10211, [458, 910, 1430, 1558], [456, 912, 1428, 1560]]
+ ]
+ }
+]
diff --git a/sdvx@asphyxia/handlers/webui.ts b/sdvx@asphyxia/handlers/webui.ts
index 5e96c7c..e448f3f 100644
--- a/sdvx@asphyxia/handlers/webui.ts
+++ b/sdvx@asphyxia/handlers/webui.ts
@@ -4,7 +4,10 @@ import { ValgeneTicket } from '../models/valgene_ticket';
import { Skill } from '../models/skill';
import { getVersion, IDToCode, GetCounter } from '../utils';
import { Mix } from '../models/mix';
-import { PREGENE } from '../data/exg';
+import { PREGENE, COURSES6} from '../data/exg';
+import { textureslist } from '../data/webui'
+import * as fs from 'fs';
+import { PNG } from '../webui/asset/js/pngjs/png.js';
export const updateProfile = async (data: {
refid: string;
@@ -363,7 +366,7 @@ export const copyResourcesFromGame = async (data: {}, send: WebUISend) => {
if(nemsys.name.match(/([0-9]+)/g) != undefined) {
let nemsysId = parseInt(nemsys.name.match(/([0-9]+)/g)[0])
- if(nemsysId && resourceJsonData.nemsys.find(nem => nem.value == nemsysId) == undefined) {
+ if(nemsysId && ![8, 9, 10, 11].includes(nemsysId) && resourceJsonData.nemsys.find(nem => nem.value == nemsysId) == undefined) {
console.log("[nemsys] adding to json: " + nemsys.name)
resourceJsonData.nemsys.push({"value": nemsysId, "name": nemsys.name})
}
@@ -551,9 +554,140 @@ export const copyResourcesFromGame = async (data: {}, send: WebUISend) => {
await IO.WriteFile('webui/asset/json/data.json', JSON.stringify(resourceJsonData, null, 4))
await IO.WriteFile('webui/asset/json/appeal.json', JSON.stringify(apCardJsonData, null, 4))
+
+ // Extract textures from ifs files using pngjs. Massive thanks to https://github.com/mon/ifstools
+ console.log("Extracting textures from IFS files")
+ let ifsSuccess = []
+ for(let listIter = 0; listIter < textureslist.length; listIter++) {
+ let manifestJson = {}
+ let bufOffset = 0
+ let magic = '6CAD8F89'
+ console.log(textureslist[listIter]['file'] + ":")
+ let ifsBuffer = await IO.ReadFile(U.GetConfig('sdvx_eg_root_dir') + textureslist[listIter].file, {flag: 'r'})
+ if(!fs.existsSync('plugins/sdvx@asphyxia/webui/asset/' + textureslist[listIter].asset_folder)) {
+ fs.mkdirSync('plugins/sdvx@asphyxia/webui/asset/' + textureslist[listIter].asset_folder)
+ }
+ let header = Buffer.from(ifsBuffer.buffer.slice(0, 36))
+ let sig = header.readUInt32BE().toString(16).toUpperCase()
+ bufOffset += 4
+ if(sig === magic) {
+ bufOffset += 12
+ let manifest_end = ifsBuffer.readUInt32BE(bufOffset)
+ bufOffset += 4
+ let md5_hash = ifsBuffer.toString('hex', bufOffset, bufOffset + 16)
+ bufOffset += 16
+ if(md5_hash === textureslist[listIter].md5) {
+ for(let texIter = 0; texIter < textureslist[listIter]['textures'].length; texIter++) {
+ let tdFileName = textureslist[listIter]['textures'][texIter][0]
+ let tdOffset = parseInt(textureslist[listIter]['textures'][texIter][1].toString())
+ let tdSize = parseInt(textureslist[listIter]['textures'][texIter][2].toString())
+ let tdUvrect = textureslist[listIter]['textures'][texIter][3]
+ let tdImgRect = textureslist[listIter]['textures'][texIter][4]
+
+ let imgBufferHead = Buffer.from(ifsBuffer.buffer.slice(manifest_end + tdOffset, manifest_end + tdOffset + 8))
+ let imgBufferHeadOff = 0
+ let imgBuffer = Buffer.from(ifsBuffer.buffer.slice(manifest_end + tdOffset + 8, manifest_end + tdOffset + tdSize))
+ let imgBufferOff = 0
+ let imgUncompressedSize = imgBufferHead.readUInt32BE(imgBufferHeadOff)
+ imgBufferHeadOff += 4
+ let imgCompressedSize = imgBufferHead.readUInt32BE(imgBufferHeadOff)
+ imgBufferHeadOff += 4
+
+ // Decompression algorithm & code from ifstools/handlers/lz77.py
+ let decompressed = []
+ let contLoop = true
+ let diff, flag, w, position, length
+ while(contLoop) {
+ flag = imgBuffer.readUInt8(imgBufferOff)
+ imgBufferOff++
+ for(let i = 0; i < 8; i++){
+ if (((flag >> i) & 1) === 1) {
+ decompressed.push(imgBuffer.readUInt8(imgBufferOff))
+ imgBufferOff++
+ }
+ else {
+ w = imgBuffer.readUInt16BE(imgBufferOff)
+ imgBufferOff+=2
+ position = (w >> 4)
+ length = (w & 0x0F) + 3
+ if(position === 0) {
+ contLoop = false
+ break;
+ }
+ if(position > decompressed.length) {
+ diff = 0
+ diff = position - decompressed.length
+ diff = Math.min(diff, length)
+ for(let e2p = 0; e2p < diff; e2p++) {
+ decompressed.push(0)
+ }
+ length -= diff
+ }
+ if (-position+length < 0) {
+ decompressed.push(...decompressed.slice(decompressed.length + (-position), decompressed.length + (-position+length)))
+ }
+ else {
+ for(let loop = 0; loop < length; loop++) {
+ decompressed.push(decompressed[decompressed.length + (-position)])
+ }
+ }
+ }
+ }
+ }
+
+ // Swap red and blue data (RGBA -> BGRA)
+ if(decompressed.length === imgUncompressedSize) {
+ for(let decCtr = 0; decCtr < decompressed.length; decCtr += 4) {
+ decompressed[decCtr + 2] = [decompressed[decCtr], decompressed[decCtr] = decompressed[decCtr + 2]][0];
+ }
+
+ let pngf = new PNG({
+ width: Math.floor(tdImgRect[1]/2) - Math.floor(tdImgRect[0]/2),
+ height: Math.floor(tdImgRect[3]/2) - Math.floor(tdImgRect[2]/2),
+ bitDepth: 8,
+ colorType: 6,
+ inputHasAlpha: true
+ })
+
+ pngf.data = Buffer.from(decompressed)
+ const outputStream = await fs.createWriteStream('plugins/sdvx@asphyxia/webui/asset/' + textureslist[listIter].asset_folder + '/' + tdFileName);
+ await pngf.pack().pipe(outputStream);
+ console.log(' - ' + tdFileName + ' created successfully.');
+ ifsSuccess.push(textureslist[listIter].file + ' - ' + tdFileName)
+ } else {
+ console.log("Decompression mismatch.")
+ runErrors.push('[ifs] decompression mismatch for ' + textureslist[listIter]['file'] + '/' + tdFileName)
+ }
+ }
+ } else {
+ console.log('MD5 mismatch.')
+ runErrors.push('[ifs] MD5 mismatch - ' + textureslist[listIter].file)
+ }
+
+ } else {
+ console.log('IFS file unsupported/invalid.')
+ runErrors.push('[ifs] IFS file "' + textureslist[listIter].file + '" unsupported/invalid.')
+ }
+ }
+
+ console.log("Updating course_data.json")
+ let courseDataUpdateSuccess = false
+ let courseData = JSON.parse(U.DecodeString(await IO.ReadFile('webui/asset/json/course_data.json'), 'utf8'))
+ for(let cIter = 0; cIter < courseData.courseData.length; cIter++) {
+ if(courseData.courseData[cIter].version === 6) {
+ courseData.courseData[cIter].info = COURSES6
+ courseDataUpdateSuccess = true
+ }
+ }
+ if(courseDataUpdateSuccess === false) runErrors.push('[course_data] Update unsuccessful.')
+
+ await IO.WriteFile('webui/asset/json/course_data.json', JSON.stringify(courseData, null, 4))
+
send.json(
{
status: 'ok',
+ course: courseDataUpdateSuccess,
+ ifs: ifsSuccess,
akaname: newAkanames,
nemsys: newNemsysData,
apCard: newAPCardData,
diff --git a/sdvx@asphyxia/webui/asset/js/detail.js b/sdvx@asphyxia/webui/asset/js/detail.js
index dc9a467..563d93d 100644
--- a/sdvx@asphyxia/webui/asset/js/detail.js
+++ b/sdvx@asphyxia/webui/asset/js/detail.js
@@ -1,6 +1,6 @@
-var music_db, course_db, score_db, data_db, appeal_db;
+var music_db, course_db, score_db, data_db, appeal_db, skill_title_db;
var volforceArray = [];
-var profile_data, skill_data;
+var profile_data, skill_data, course_data;
var baseTBodyCMpD, baseTBodyCMpL, baseTBodyGpD, baseTBodyGpL, baseTBodyASpL;
var notFirst = false;
var versionText = ['', 'BOOTH', 'INFINTE INFECTION', 'GRAVITY WARS', 'HEAVENLY HAVEN', 'VIVIDWAVE', 'EXCEED GEAR']
@@ -24,7 +24,16 @@ function zeroPad(num, places) {
function getSkillAsset(skill) {
- return "static/asset/skill_lv/skill_" + zeroPad(skill, 2) + ".png";
+ return "static/asset/skill_lv/skill_" + ((skill === -1) ? 'none' : zeroPad(skill, 2)) + ".png";
+}
+
+function getSkillFrameAsset(frame) {
+ return "static/asset/skill_lv/skill_frame_" + frame + ".png";
+}
+
+function getSkillTitle() {
+ if(skill_data.length <= 0 || skill_data[0].name === (undefined || 0)) return ''
+ return skill_title_db.filter(e => e.id === skill_data[0].name)[0].name
}
function getGrade(grade) {
@@ -634,18 +643,47 @@ function setUpStatistics() {
$('#version_select').change(function() {
$('#skillLV').fadeOut(200, () => {
console.log("change version select");
- $('#skillLV').attr('src', getSkillAsset(getPlayerSkill($('#version_select').val())))
+ $('#skillLV').attr('src', getSkillAsset(getPlayerSkill($('#version_select').val())[0]))
});
$('#skillLV').fadeIn(200);
});
function getPlayerSkill(version) {
// console.log(getPlayerMaxVersion())
- if (skill_data.length == 0) return 0;
+ if (skill_data.length == 0) return [-1, 0];
var k = skill_data.filter(e => e.version == version)
- return parseInt(k[0].level);
+ let courseDataFil = course_data.filter(e => ![6,7,12,13,15,16].includes(e.sid) && e.cid === k[0].level && ((k[0].type !== undefined) ? k[0].type : 0) === ((e.stype !== undefined) ? e.stype : 0))
+ return [(courseDataFil.length > 0) ? k[0].level : -1, (k[0].type !== undefined) ? k[0].type : 0];
}
+function getPlayerCourse(version, playerSkill) {
+ if(version === 0) return 'none'
+ let skillFrame = ['normal', 'god']
+ let skillThrsh = [[130, 150, 160, 170], [150, 160, 170, 180]]
+ let skillThrshVal = (playerSkill[0] <= 9) ? 0 : playerSkill[0] - 9
+ var k = course_db.courseData.filter(e => e.version == version)[0].info
+ let sidCourses = []
+ k.forEach(kd => {
+ kd.courses.forEach(kdc => {
+ kdc['sid'] = kd.id
+ kdc['isNew'] = kd.isNew
+ sidCourses.push(kdc)
+ })
+ })
+ sidCourses = sidCourses.filter(e => ![6,7,12,13,15,16].includes(e.sid) && e.level === playerSkill[0])
+ let newCourses = sidCourses.filter(e => e.isNew === 1).map(a => a.sid)
+ let foundCourses = course_data.filter(e => e.cid === playerSkill[0] && ((e.stype !== undefined) ? e.stype : 0) === playerSkill[1] && e.clear >= 2)
+ let newCompleteCourses = foundCourses.filter(e => newCourses.includes(e.sid))
+ let thrshCourses = foundCourses.filter(e => Math.floor(e.rate/100) >= skillThrsh[playerSkill[1]][skillThrshVal])
+
+ if(sidCourses.length > 0 && thrshCourses.length === sidCourses.length) return skillFrame[playerSkill[1]] + '_sp'
+ if(sidCourses.length > 0 && foundCourses.length === sidCourses.length) return skillFrame[playerSkill[1]] + '_gold'
+ if(newCompleteCourses.length > 1) return skillFrame[playerSkill[1]] + '_silver'
+ if(foundCourses.length > 1 && playerSkill[1] === 1) return skillFrame[playerSkill[1]] + '_sp_none'
+ return 'none'
+}
+
+
function getVersionSelect() {
if (skill_data.length == 0) return [];
var versionDATA = [];
@@ -662,10 +700,10 @@ function displayArenaSeasonData(season) {
$('.arena-details').append(
$('
').append(
$('
').append(
- // $('
', {
- // src: 'static/asset/arena_icon/' + rankInfo[0] + ".png"
- // })
- $('' + ((rankInfo[0] === 'none') ? 'n/a' : rankInfo[0].toUpperCase()) + "
")
+ $('
', {
+ src: 'static/asset/arena_rank/' + rankInfo[0] + ".png"
+ })
+ // $('' + ((rankInfo[0] === 'none') ? 'n/a' : rankInfo[0].toUpperCase()) + "
")
)
)
).append(
@@ -674,10 +712,6 @@ function displayArenaSeasonData(season) {
$('Arena Power
').append(
$('' + sznData.shopPoint + ' AP
')
)
- ).append(
- (sznData.megamixRate !== (0 || undefined)) ? $('Megamix Rate
').append(
- $('' + sznData.megamixRate + '
')
- ) : $("")
)
)
)
@@ -695,12 +729,12 @@ function displayArenaSeasonData(season) {
$('')
).append(
$('' + sznData.rankPoint + ' pts (' + (rankInfo[2].point - sznData.rankPoint) + ' pts to ' + rankInfo[2].rank.toUpperCase() + ')
')
+ ).append(
+ (sznData.megamixRate !== (0 || undefined)) ? $('Megamix rate: ' + sznData.megamixRate + ' 
') : $('')
)
} else if(rankInfo[0] !== 'none'){
$('.arena-details-child-left').append(
- $('Ultimate rate: ' + sznData.ultimateRate + '
')
- ).append(
-
+ (sznData.megamixRate !== (0 || undefined)) ? $('Megamix rate: ' + sznData.megamixRate + ' 
') : $('Ultimate rate: ' + sznData.ultimateRate + '
')
)
}
}
@@ -754,6 +788,7 @@ $(document).ready(function() {
profile_data = JSON.parse(document.getElementById("data-pass").innerText);
score_db = JSON.parse(document.getElementById("score-pass").innerText);
skill_data = JSON.parse(document.getElementById("skill-pass").innerText);
+ course_data = JSON.parse(document.getElementById("course-pass").innerText);
arena_data = JSON.parse(document.getElementById("arena-pass").innerText);
skill_data.sort(function(a, b) {
@@ -782,7 +817,10 @@ $(document).ready(function() {
$.getJSON("static/asset/json/appeal.json", function(json) {
appeal_db = json;
//console.log(appeal_db);
- })
+ }),
+ $.getJSON("static/asset/json/customize_data_ext.json", function(json) {
+ skill_title_db = json.skilltitle;
+ }),
).then(function() {
var currentVF = calculateVolforce();
var maxVer = skill_data.length > 0 ? parseInt(skill_data[0]["version"]) : 0
@@ -809,7 +847,7 @@ $(document).ready(function() {
}
$('#test').append(
- $('').append(
+ $('
').append(
$('