231024 + webui stuff

This commit is contained in:
vvo
2023-11-06 03:56:30 +08:00
parent 0d357fdf07
commit 206212be2f
24 changed files with 6116 additions and 229 deletions
+40 -8
View File
@@ -1,10 +1,10 @@
# SOUND VOLTEX
**Plugin Version:** fork-6.0.2.1
**Plugin Version:** fork-6.0.2.3
**Supported game versions:** EXCEED GEAR
**Latest supported game datacode:** 2023091200
**Latest supported game datacode:** 2023102400
**Unsupported game versions:** Every other game, as they're untested.
@@ -12,14 +12,51 @@
**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.
- Most importantly, for everything to properly work:
- 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)
Changelog
===========
## fork-6.0.2.3
### New:
1. Main:
- Added ~~ARENA~~ MEGAMIX BATTLE ranked match season & ARENA STATION set 11.
- Added PREMIUM GENERATOR Fubuki set.
- Updated licensed songs list (Fubuki songs)
2. WebUI
- Updated ARENA Season statistics display in detail page. Displays rank, rank point meter, megamix rate (for ranked megamix,) ultimate rate (for ultimate players,) and arena power.
- Added achievements list page (work in progress)
- Added ability to set how many Valkyrie Generator tickets you have. These tickets are used to purchase valkyrie generator items.
- Added ability to change Skill Titles. Players can only switch to titles they own.
- (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.
### Fixes:
1. Game
- Fixed gibberish on Asphyxia card entry information data.
2. WebUI
- Fixed details page error for players with no skill course data.
- Fixed sorting of Valgene/Pregene item images.
3. Misc:
- 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
### New:
@@ -47,11 +84,6 @@ Changelog
1. Fixes WebUI resource update not adding video submonitor backgrounds. I 100% recommend updating your WebUI assets.
### Todo:
1. Figure out how to use image (png) files to appear in information/news popup.
2. Figure out how demoloop works.
3. More work/research on online matchmaking (globalMatch.) I can't seem to make clients establish a connection.
## fork-6.0.2.1
+2 -6
View File
@@ -1,10 +1,6 @@
@echo off
for /f %%a in ('dir "webui\asset\audio\*.s3p" /s /b') do (
echo "%%~fa"
s3p_extract %%~fa
ffmpeg -i "%%~fa.out\0.wma" -vn -ar 44100 -ac 2 -b:a 192k "%%~fa.out\..\0.mp3"
ffmpeg -i "%%~fa.out\1.wma" -vn -ar 44100 -ac 2 -b:a 192k "%%~fa.out\..\1.mp3"
rmdir /s /q "%%~fa.out"
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"
del %%~fa
)
@echo on
+142 -2
View File
@@ -40,7 +40,8 @@ export const EVENT6 = [
'S_PUC_EFFECT_ENABLE',
'PLAYER_RADAR_ENABLE',
'SINGLE_BATTLE_ENABLE',
// 'DEMOLOOP_INFORMATION',
'DEMOLOOP_INFORMATION\tdemo_info/230710_bpls3_streaming.png',
'CHARACTER_IGNORE_DISABLE\t122,123,131,139,140,143'
];
export const INFORMATION6 = {
@@ -69,7 +70,10 @@ export const LICENSED_SONGS6 = [
'1960', '1961', '1962', '2028', '2029', '1912', '1913', '2030',
// 230518 - 230912
'2031', '2032', '2033', '2034', '2035', '2036', '1905', '1882', '2058'
'2031', '2032', '2033', '2034', '2035', '2036', '1905', '1882', '2058',
// 231005
'2069', '2070', '2071', '2072', '2073'
]
export const STAMP_EVENTS6 = {
@@ -1516,6 +1520,133 @@ export const ARENA = {
param: 8,
}
]
},
'Season 11 (MEGAMIX BATTLE 2023/10/26~2023/11/13)': {
details: {
season: 11,
rule: 0,
rank_match_target: 2,
time_start: BigInt(Date.parse('26 Oct 2023 00:00:00 GMT')),
time_end: BigInt(Date.parse('31 Dec 2099 23:59:59 GMT')),
shop_start: BigInt(Date.parse('26 Oct 2023 00:00:00 GMT')),
shop_end: BigInt(Date.parse('31 Dec 2099 23:59:59 GMT')),
is_open: 1,
is_shop: 1
},
arena_items: [
{
catalog_id: 1,
catalog_type: 1,
price: 15000,
item_type: 11,
item_id: 104,
param: 1,
},
{
catalog_id: 1,
catalog_type: 1,
price: 8000,
item_type: 0,
item_id: 1742,
param: 23,
},
{
catalog_id: 1,
catalog_type: 1,
price: 8000,
item_type: 0,
item_id: 1745,
param: 23,
},
{
catalog_id: 1,
catalog_type: 1,
price: 8000,
item_type: 0,
item_id: 289,
param: 8,
},
{
catalog_id: 1,
catalog_type: 1,
price: 4000,
item_type: 0,
item_id: 241,
param: 8,
},
{
catalog_id: 1,
catalog_type: 1,
price: 4000,
item_type: 0,
item_id: 390,
param: 8,
},
{
catalog_id: 1,
catalog_type: 1,
price: 8000,
item_type: 0,
item_id: 510,
param: 8,
},
{
catalog_id: 1,
catalog_type: 1,
price: 8000,
item_type: 0,
item_id: 842,
param: 8,
},
{
catalog_id: 1,
catalog_type: 1,
price: 8000,
item_type: 0,
item_id: 281,
param: 8,
},
{
catalog_id: 1,
catalog_type: 1,
price: 8000,
item_type: 0,
item_id: 632,
param: 8,
},
{
catalog_id: 1,
catalog_type: 1,
price: 4000,
item_type: 0,
item_id: 37,
param: 8,
},
{
catalog_id: 1,
catalog_type: 1,
price: 4000,
item_type: 0,
item_id: 239,
param: 8,
},
{
catalog_id: 1,
catalog_type: 1,
price: 2000,
item_type: 0,
item_id: 111,
param: 8,
},
{
catalog_id: 1,
catalog_type: 1,
price: 2000,
item_type: 0,
item_id: 132,
param: 8,
}
]
}
}
@@ -1936,6 +2067,15 @@ export const PREGENE = [
'sysbg': [1, 2, 3]
},
probability: [0.01, 0.42, 0.84, 0.9]
},
{
id: 7,
items: {
'crew': [143],
'stamp': [249, 250, 251, 252, 253, 254, 255, 256, 257, 258],
'subbg': [369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381]
},
probability: [0.01, 0.39, 0.6]
}
]
+1 -1
View File
@@ -146,7 +146,7 @@ export const common: EPR = async (info, data, send) => {
' [c:e5f3ff,a3d5ff]SDVX Plugin ver 6.0.0\n \n \n'+
'\n\n [f:0][c:ff3333,ffffff]FREE SOFTWARE. BEWARE OF SCAMMERS.\n'+
'[c:ffffff,888888] If you bought this software, request refund immediately.\n \n \n[/ol]'+
'[br:10][c:00FFFF][sz:50]メリー。。。クリスマス、です。。。'+
'[br:10][c:00FFFF][sz:50]メリー。。。クリスマス、です。。。'+
'\n \n \n \n[sz:32][c:560000,FC0000]DO NOT STREAM OR DISTRIBUTE THIS GAME IN PUBLIC',
//'[img:test]',
'',
+12 -11
View File
@@ -174,13 +174,14 @@ export const globalMatch: EPR = async (info, data, send) => {
}
let loggip = entryData.gip.join(".")
let loglip = entryData.lip.join(".")
console.log("====================================")
console.log("[" + loggip + "] Searching for online match opponents")
console.log("[" + loggip + "] Removed " + await DB.Remove({collection:'matchmaker', timestamp: {$lt: Date.now() - 100000}}) + " expired match data.")
console.log("[" + loglip + " | " + loggip + "] Searching for online match opponents")
console.log("[" + loglip + " | " + loggip + "] Removed " + await DB.Remove({collection:'matchmaker', timestamp: {$lt: Date.now() - 100000}}) + " expired match data.")
if(entryData.p_rest < 1) {
console.log("[" + loggip + "] Room is full. Halting.")
console.log("[" + loglip + " | " + loggip + "] Room is full. Halting.")
return send.deny();
}
@@ -196,15 +197,15 @@ export const globalMatch: EPR = async (info, data, send) => {
// console.log(" claim: " + entryData.claim)
// console.log("entry_id: " + entryData.entry_id)
console.log("[" + loggip + "] Adding/updating your match data")
if(await DB.Count({collection: 'matchmaker', gip: entryData.gip}) === 0) {
console.log("[" + loglip + " | " + loggip + "] Adding/updating your match data")
if(await DB.Count({collection: 'matchmaker', lip: entryData.lip}) === 0) {
await DB.Upsert<Matchmaker>(
{ collection: 'matchmaker', gip: entryData.gip },
{ collection: 'matchmaker', gip: entryData.gip, lip: entryData.lip},
entryData
)
} else {
await DB.Upsert<Matchmaker>(
{ collection: 'matchmaker', gip: entryData.gip},
{ collection: 'matchmaker', gip: entryData.gip, lip: entryData.lip},
{ $set: {
c_ver: entryData.c_ver,
p_num: entryData.p_num,
@@ -218,8 +219,8 @@ export const globalMatch: EPR = async (info, data, send) => {
)
}
console.log("[" + loggip + "] Searching...")
let filteredDB = await DB.Find<Matchmaker>({collection: "matchmaker", entry_id: entryData.entry_id, filter: entryData.filter, $not: {gip: entryData.gip}})
console.log("[" + loglip + " | " + loggip + "] Searching...")
let filteredDB = await DB.Find<Matchmaker>({collection: "matchmaker", entry_id: entryData.entry_id, filter: entryData.filter, $not: {lip: entryData.lip}})
let opponents = filteredDB.length === 0 ? null : {
entry_id: K.ITEM('u32', entryData.entry_id),
@@ -230,11 +231,11 @@ export const globalMatch: EPR = async (info, data, send) => {
}))
}
if(opponents !== null) {
console.log("[" + loggip + "] Opponent/s found.")
console.log("[" + loglip + " | " + loggip + "] Opponent/s found.")
send.object(opponents)
}
else {
console.log("[" + loggip + "] No found opponents.")
console.log("[" + loglip + " | " + loggip + "] No found opponents.")
send.deny()
}
}
+27 -4
View File
@@ -6,6 +6,7 @@ import { Arena } from '../models/arena';
import { MusicRecord } from '../models/music_record';
import { CourseRecord } from '../models/course_record';
import { Profile } from '../models/profile';
import { ValgeneTicket } from '../models/valgene_ticket';
import { getVersion, IDToCode } from '../utils';
import { Mix } from '../models/mix';
import { ARENA, EVENT_SONGS6 } from '../data/exg';
@@ -597,6 +598,7 @@ export const save: EPR = async (info, data, send) => {
const earnedRP = are.number('earned_rank_point');
const earnedSP = are.number('earned_shop_point');
const earnedUR = are.number('earned_ultimate_rate');
const earnedMR = are.number('earned_megamix_rate');
const earnedLE = are.number('earned_live_energy');
const rankPlay = are.str('rank_play') == 'true' ? 1 : 0;
const ultimatePlay = are.str('ultimate_play') == 'true' ? 1 : 0;
@@ -609,6 +611,7 @@ export const save: EPR = async (info, data, send) => {
{
$inc: {
ultimateRate: _.isNil(earnedUR) ? 0 : earnedUR,
megamixRate: _.isNil(earnedMR) ? 0 : earnedMR,
shopPoint: _.isNil(earnedSP) ? 0 : earnedSP,
rankPoint: _.isNil(earnedRP) ? 0 : earnedRP,
liveEnergy: _.isNil(earnedLE) ? 0 : earnedLE,
@@ -704,7 +707,9 @@ export const load: EPR = async (info, data, send) => {
const items = await DB.Find<Item>(refid, { collection: 'item' });
const courses = await DB.Find<CourseRecord>(refid, { collection: 'course', version });
const params = await DB.Find<Param>(refid, { collection: 'param' });
const arena = await DB.FindOne<Arena>(refid, { collection: 'arena', season: Object.keys(ARENA).findIndex(data => data == U.GetConfig('arena_szn')) + 1 });
const arena = await DB.FindOne<Arena>(refid, { collection: 'arena', season: (U.GetConfig('arena_szn') !== "None") ? ARENA[U.GetConfig('arena_szn')]['details']['season'] : 0 });
const valgeneTicket = await DB.FindOne<ValgeneTicket>(refid, { collection: 'valgene_ticket' })
let time = new Date();
let tempHour = time.getHours();
let tempDate = time.getDate();
@@ -788,6 +793,7 @@ export const load: EPR = async (info, data, send) => {
automation: version == 5 ? SDVX_AUTOMATION_SONGS : [],
code: IDToCode(profile.id),
arena,
valgeneTicket,
...profile,
});
};
@@ -939,6 +945,7 @@ export const saveValgene: EPR = async (info, data, send) => {
console.log("Saving Valkyrie Generator Item")
const refid = $(data).str('refid');
const items = $(data).elements('item.info');
const useTicket = $(data).bool('use_ticket');
let itemsToAdd = []
for (const i of items) {
const type = i.number('type');
@@ -967,11 +974,27 @@ export const saveValgene: EPR = async (info, data, send) => {
);
}
return send.object({ result: K.ITEM('u8', 0) });
if(useTicket) {
await DB.Upsert<ValgeneTicket>(
refid,
{ collection: 'valgene_ticket' },
{ $inc: {ticketNum: -1} }
)
}
let valgeneTicket = await DB.FindOne<ValgeneTicket>(refid, { collection: 'valgene_ticket' })
let result = {
result: K.ITEM('s32', 1)
}
if(valgeneTicket !== null) {
result['ticket_num'] = K.ITEM('s32', valgeneTicket.ticketNum)
result['limit_date'] = K.ITEM('u64', BigInt(valgeneTicket.limitDate))
}
return send.object(result);
}
export const saveE: EPR = async (info, data, send) => {
console.log("save_e")
console.log("save_e - WIP")
return send.object({ result: K.ITEM('u8', 0) });
send.success();
}
+91 -37
View File
@@ -1,5 +1,7 @@
import { Profile } from '../models/profile';
import { MusicRecord } from '../models/music_record';
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';
@@ -22,6 +24,8 @@ export const updateProfile = async (data: {
stampRC?: string;
stampRD?: string;
sysBG?: string;
valgeneTicket?: string;
skilltitle?: string;
}) => {
if (data.refid == null) return;
@@ -106,7 +110,6 @@ export const updateProfile = async (data: {
}
if (data.sysBG && data.sysBG.length > 0) {
console.log(data.sysBG)
const validSysBG = parseInt(data.sysBG);
if (!_.isNaN(validSysBG)) update.sysBG = validSysBG;
}
@@ -116,6 +119,29 @@ export const updateProfile = async (data: {
{ collection: 'profile' },
{ $set: update }
);
if (parseInt(data.skilltitle) >= 0) {
await DB.Update<Skill>(
data.refid,
{ collection: 'skill' },
{ $set: {
name: parseInt(data.skilltitle)
}
}
);
}
if (parseInt(data.valgeneTicket) >= 0) {
await DB.Upsert<ValgeneTicket>(
data.refid,
{ collection: 'valgene_ticket' },
{ $set: {
ticketNum: parseInt(data.valgeneTicket),
limitDate: Date.parse('31 Dec 2099 23:59:59 GMT')
}
}
);
}
};
export const updateMix = async (data: {
@@ -353,7 +379,7 @@ export const copyResourcesFromGame = async (data: {}, send: WebUISend) => {
if(IO.Exists(U.GetConfig('sdvx_eg_root_dir') + "/data/graphics/submonitor_bg")) {
let subBGFiles = await IO.ReadDir(U.GetConfig('sdvx_eg_root_dir') + "/data/graphics/submonitor_bg")
for await (const subbg of subBGFiles) {
if (subbg.name.match(/(\.png|\.jpg|\.mp4)/g)) {
if (subbg.name.match(/^(subbg[_0-9]*)(\.png|\.jpg|\.mp4)/g)) {
let fileToWrite = await IO.ReadFile(U.GetConfig('sdvx_eg_root_dir') + "/data/graphics/submonitor_bg/" + subbg.name)
if(!IO.Exists('webui/asset/submonitor_bg/' + subbg.name.substring(0, (subbg.name.length - 4)) + ".png") && !IO.Exists('webui/asset/submonitor_bg/' + subbg.name.substring(0, (subbg.name.length - 4)) + ".jpg") && !IO.Exists('webui/asset/submonitor_bg/' + subbg.name.substring(0, (subbg.name.length - 4)) + ".mp4")) {
console.log("[subbg] copying " + subbg.name)
@@ -367,13 +393,13 @@ export const copyResourcesFromGame = async (data: {}, send: WebUISend) => {
let subbgType = 'normal'
let foundSubbg = resourceJsonData.subbg.findIndex(subbg => subbg.value === subbgId)
if(subbg.name.match(/(subbg_[0-9]+_[0-9]+)/g)) {
subbgName = subbg.name.match(/(subbg_[0-9]+)/g)[0]
subbgType = 'slideshow'
} else if(subbg.name.includes('.mp4')) subbgType = 'video'
console.log("[subbg] adding to json: " + subbgId + " - " + subbgName)
if(foundSubbg == -1) {
console.log("[subbg] adding " + subbgId + " - " + subbgName + " (" + subbgType + ")")
resourceJsonData.subbg.push({"value": subbgId, "type": subbgType, "name": subbgName})
} else {
resourceJsonData.subbg[foundSubbg] = {"value": subbgId, "type": subbgType, "name": subbgName}
@@ -394,16 +420,40 @@ export const copyResourcesFromGame = async (data: {}, send: WebUISend) => {
if (bgm.name.match(/(\.s3p)/g)) {
let folderName = bgm.name.match(/(custom|special)_([0-9]*)/g)[0]
if(folderName != '') {
let fileToWrite = await IO.ReadFile(U.GetConfig('sdvx_eg_root_dir') + "/data/sound/custom/" + bgm.name)
if(!IO.Exists('webui/asset/audio/' + folderName)) {
console.log("[bgm] copying " + bgm.name)
IO.WriteFile('webui/asset/audio/' + folderName + '/' + bgm.name, fileToWrite)
newBGMData.push(bgm.name)
console.log("[bgm] extracting audio files from " + bgm.name + ".")
// Thanks to mon/s3p_extract on GitHub.
let bufOffset = 4
let s3pBuffer = await IO.ReadFile(U.GetConfig('sdvx_eg_root_dir') + "/data/sound/custom/" + bgm.name, {flag: 'r'})
let fileMagic = s3pBuffer.toString('utf8', 0, 4)
let fileEntries = s3pBuffer.readInt32LE(bufOffset)
let entries = []
bufOffset += 4
for(let entryCtr = 0; entryCtr < fileEntries; entryCtr++) {
entries.push(
{
offset: s3pBuffer.readInt32LE(bufOffset),
length: s3pBuffer.readInt32LE(bufOffset + 4)
}
)
bufOffset += 8
}
let filename = 0
entries.forEach(entry => {
let magic = s3pBuffer.toString('utf8', entry.offset, entry.offset + 4)
let fileStart = s3pBuffer.readInt32LE(entry.offset + 4)
let arrayBuffer = s3pBuffer.buffer.slice(entry.offset, entry.offset + entry.length)
IO.WriteFile('webui/asset/audio/' + folderName + '/' + filename + '.wma', s3pBuffer.toString('binary', entry.offset + fileStart, entry.offset + entry.length), {encoding: 'binary'})
filename++
})
}
let bgmId = parseInt(bgm.name.match(/(?<=(custom|special)_)([0-9]*)/g)[0])
if(bgmId && resourceJsonData.bgm.find(bgm => bgm.value == bgmId) == undefined) {
console.log("[bgm] adding to json: " + bgmId + " - " + bgm.name)
newBGMData.push(bgm.name)
resourceJsonData.bgm.push({"value": bgmId, "name": bgm.name})
}
}
@@ -414,6 +464,30 @@ export const copyResourcesFromGame = async (data: {}, send: WebUISend) => {
runErrors.push('[BGM] Error reading BGM directory. Check your "Exceed Gear Data Directory" config.')
}
// Copying new chat stamps from gamedata
console.log("Copying new chat stamps from gamedata")
if(IO.Exists(U.GetConfig('sdvx_eg_root_dir') + "/data/others/chat_stamp.xml")) {
let chatStampData = U.parseXML(U.DecodeString(await IO.ReadFile(U.GetConfig('sdvx_eg_root_dir') + "/data/others/chat_stamp.xml"), "shift_jis"), false)
// console.log(JSON.stringify(chatStampData.chat_stamp_data))
for(const chatStamp of chatStampData.chat_stamp_data.info) {
if(resourceJsonData.stamp.find(stamp => stamp['value'] === chatStamp.id['@content'][0]) == undefined) {
let stampTitle = chatStamp.title['@content'] + " " + (parseInt(chatStamp.id['@content'][0]) % 4 !== 0 ? parseInt(chatStamp.id['@content'][0]) % 4 : 4)
console.log("[chat_stamp] " + chatStamp.id['@content'][0] + " - " + stampTitle)
resourceJsonData.stamp.push({"value": chatStamp.id['@content'][0], "name": stampTitle})
newChatStampData.push(chatStamp.id['@content'][0] + ": " + chatStamp.filename['@content'])
}
if(!IO.Exists('webui/asset/chat_stamp/' + chatStamp.filename['@content'] + '.png') && !IO.Exists('webui/asset/chat_stamp/' + chatStamp.filename['@content'] + '.png')) {
console.log("[chat_stamp] copying " + chatStamp.filename['@content'] + '.png')
let fileToWrite = await IO.ReadFile(U.GetConfig('sdvx_eg_root_dir') + "/data/graphics/chat_stamp/" + chatStamp.filename['@content'] + ".png")
IO.WriteFile('webui/asset/chat_stamp/' + chatStamp.filename['@content'] + '.png', fileToWrite)
}
}
resourceJsonData.stamp.sort(function(a, b){return a.value - b.value})
} else {
console.log('Error reading chat stamp xml file. Check your "Exceed Gear Data Directory" config.')
runErrors.push('[chat stamp] Error reading chat stamp xml file. Check your "Exceed Gear Data Directory" config.')
}
// Copying new valgene_item files from gamedata
console.log("Copying new valgene_item files from gamedata")
if(IO.Exists(U.GetConfig('sdvx_eg_root_dir') + "/data/graphics/valgene_item")) {
@@ -425,7 +499,8 @@ export const copyResourcesFromGame = async (data: {}, send: WebUISend) => {
console.log("[valgene_item] copying " + valgeneItem.name)
IO.WriteFile('webui/asset/valgene_item/' + valgeneItem.name, fileToWrite)
newValgeneItemFiles.push(valgeneItem.name)
}
}
}
}
} else {
@@ -434,14 +509,16 @@ export const copyResourcesFromGame = async (data: {}, send: WebUISend) => {
}
// Copying new akanames from gamedata
console.log("Copying new akanames from gamedata")
console.log("Copying new appeal titles from gamedata")
// resourceJsonData.akaname = []
if(IO.Exists(U.GetConfig('sdvx_eg_root_dir') + "/data/others/akaname_parts.xml")) {
let akanameData = U.parseXML(U.DecodeString(await IO.ReadFile(U.GetConfig('sdvx_eg_root_dir') + "/data/others/akaname_parts.xml"), "shift_jis"), false)
for(const akaname of akanameData.akaname_parts.part) {
if(resourceJsonData.akaname.find(aka => aka.value === akaname['@attr'].id) == undefined) {
console.log("[akaname] adding " + akaname['@attr'].id + " - " + akaname.word['@content'] != undefined ? akaname.word['@content'] : '')
resourceJsonData.akaname.push({"value": akaname['@attr'].id, "name": akaname.word['@content'] != undefined ? akaname.word['@content'] : '' })
newAkanames.push(akaname['@attr'].id + ": " + akaname.word['@content'])
if(resourceJsonData.akaname.find(aka => aka.value === akaname['@attr'].id) === undefined) {
let akanameFmtd = ('@content' in akaname.word) ? akaname.word['@content'].replace(/(\[[A-z0-9:,\/\]]*)/g,'') : ''
console.log("[appeal title] adding " + akaname['@attr'].id + " - " + akanameFmtd)
resourceJsonData.akaname.push({"value": akaname['@attr'].id, "name": akanameFmtd})
newAkanames.push(akaname['@attr'].id + ": " + akanameFmtd )
}
}
resourceJsonData.akaname.sort(function(a, b){return parseInt(a.value) - parseInt(b.value)})
@@ -472,29 +549,6 @@ export const copyResourcesFromGame = async (data: {}, send: WebUISend) => {
runErrors.push('[appeal card] Error reading appeal card xml file. Check your "Exceed Gear Data Directory" config.')
}
// Copying new chat stamps from gamedata
console.log("Copying new chat stamps from gamedata")
if(IO.Exists(U.GetConfig('sdvx_eg_root_dir') + "/data/others/chat_stamp.xml")) {
let chatStampData = U.parseXML(U.DecodeString(await IO.ReadFile(U.GetConfig('sdvx_eg_root_dir') + "/data/others/chat_stamp.xml"), "shift_jis"), false)
// console.log(JSON.stringify(chatStampData.chat_stamp_data))
for(const chatStamp of chatStampData.chat_stamp_data.info) {
if(resourceJsonData.stamp.find(stamp => stamp['value'] === chatStamp.id['@content'][0]) == undefined) {
console.log("[chat_stamp] adding to json: " + chatStamp.id['@content'][0] + " - " + chatStamp.filename['@content'])
resourceJsonData.stamp.push({"value": chatStamp.id['@content'][0], "name": chatStamp.filename['@content']})
newChatStampData.push(chatStamp.id['@content'][0] + ": " + chatStamp.filename['@content'])
}
if(!IO.Exists('webui/asset/chat_stamp/' + chatStamp.filename['@content'] + '.png') && !IO.Exists('webui/asset/chat_stamp/' + chatStamp.filename['@content'] + '.png')) {
console.log("[chat_stamp] copying " + chatStamp.filename['@content'] + '.png')
let fileToWrite = await IO.ReadFile(U.GetConfig('sdvx_eg_root_dir') + "/data/graphics/chat_stamp/" + chatStamp.filename['@content'] + ".png")
IO.WriteFile('webui/asset/chat_stamp/' + chatStamp.filename['@content'] + '.png', fileToWrite)
}
}
resourceJsonData.stamp.sort(function(a, b){return a.value - b.value})
} else {
console.log('Error reading chat stamp xml file. Check your "Exceed Gear Data Directory" config.')
runErrors.push('[chat stamp] Error reading chat stamp xml file. Check your "Exceed Gear Data Directory" config.')
}
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))
send.json(
+1
View File
@@ -5,6 +5,7 @@ export interface Arena {
rank_point: number;
shop_point: number;
ultimate_rate: number;
megamix_rate: number;
rank_play_cnt: number;
ultimate_play_cnt: number;
}
+16
View File
@@ -0,0 +1,16 @@
export interface Matchmaker {
collection: 'matchmaker';
timestamp: number,
c_ver: number,
p_num: number,
p_rest: number,
filter: number,
mid: number,
sec: number,
port: number,
gip: number[],
lip: number[],
claim: number,
entry_id: number
}
+6
View File
@@ -0,0 +1,6 @@
export interface ValgeneTicket {
collection: 'valgene_ticket';
ticketNum: number;
limitDate: number;
}
+7 -1
View File
@@ -35,7 +35,7 @@ game
if bplSupport
support_team_id(__type="s32") #{bplSupport}
ea_shop
packet_booster(__type="s32") 1
if version < 5
@@ -138,5 +138,11 @@ game
shop_point(__type="s32") #{arena.shopPoint}
ultimate_rate(__type="s32") #{arena.ultimateRate}
ultimate_rank_num(__type="s32") #{arena.ultimateRankNum !== undefined ? arena.ultimateRankNum : 0}
megamix_rate(__type="s32") #{arena.megamixRate !== undefined ? arena.megamixRate : 0}
rank_play_cnt(__type="s32") #{arena.rankCount}
ultimate_play_cnt(__type="s32") #{arena.ultimateCount}
if valgeneTicket
valgene_ticket
ticket_num(__type="s32") #{valgeneTicket.ticketNum}
limit_date(__type="u64") #{valgeneTicket.limitDate}
@@ -0,0 +1,106 @@
var achobt = []
var achdata = []
var aptitlelist = []
$(document).ready(async function() {
achobt = JSON.parse(document.getElementById("data-pass").innerText);
achobt.sort(function(a, b){return a['id'] - b['id']});
achdata = await $.getJSON( "static/asset/json/achievements.json", function(data) {
return data
})
aptitlelist = await $.getJSON( "static/asset/json/data.json", function(data) {
return data
})
aptitlelist = aptitlelist['akaname']
await populateAch(1);
$('#ach-filter').change(async function() {
// $('.ach-list').empty()
await populateAch(parseInt($('#ach-filter').val()));
})
})
async function populateAch(listType) {
let achListFinal = []
achdata['achievements'].forEach(ach => {
let achFound = achobt.find(obt => ach['id'] === obt['id'])
let reward = ''
if(ach['rid'] !== -1) {
if(ach['rtype'] === 'pcb') {
reward = ach['rid'] + " PCB"
} else if(ach['rtype'] === 'aptitle') {
reward = "Appeal Title \"" + aptitlelist.find(e => parseInt(e['value']) === ach['rid'])['name'] + "\""
}
} else {
reward = '-----'
}
if(listType === 1) {
if(achFound !== undefined) {
achListFinal.push(
{
'id': ach['id'],
'title': ach['title'],
'reward': reward
}
)
}
} else if(listType === 2) {
if(achFound === undefined) {
achListFinal.push(
{
'id': ach['id'],
'title': ach['title'],
'reward': reward
}
)
}
} else if(listType === 3) {
achListFinal.push(
{
'id': ach['id'],
'title': ach['title'],
'reward': reward,
'comp': (achFound === undefined) ? 'Incomplete' : 'Complete'
}
)
}
})
$('#achlist').DataTable().clear().destroy()
$('#achlist').DataTable({
data: achListFinal,
columns: (listType === 3) ? [
{ data: 'id' },
{ data: 'title' },
{ data: 'comp' },
{ data: 'reward' }
] : [
{ data: 'id' },
{ data: 'title' },
{ data: 'reward' }
],
pageLength: 100,
columnDefs: [
{
targets: 0,
width: "10px"
}
],
responsive: {
details: {
display: $.fn.dataTable.Responsive.display.modal({
header: function(row) {
var data = row.data();
return 'Details for achievement #' + data.id;
}
})
}
}
});
if(listType === 3) $($('thead tr').children()[2]).show()
else $($('thead tr').children()[2]).hide()
}
+149 -83
View File
@@ -74,7 +74,7 @@ function getMedal(clear) {
function getAppealCard(appeal) {
var result = appeal_db["appeal_card_data"]["card"].filter(object => object["@id"] == appeal);
return "static/asset/ap_card/" + result[0]["info"]["texture"] + ".jpg"
return "static/asset/ap_card/" + ((result.length > 0) ? result[0]["info"]["texture"] : 'ap_06_0001') + ".jpg"
}
function getSongLevel(musicid, type) {
@@ -639,7 +639,6 @@ $('#version_select').change(function() {
$('#skillLV').fadeIn(200);
});
function getPlayerSkill(version) {
// console.log(getPlayerMaxVersion())
if (skill_data.length == 0) return 0;
@@ -656,17 +655,111 @@ function getVersionSelect() {
return versionDATA;
}
function displayArenaSeasonData(season) {
let sznData = arena_data.find(e => e.season === parseInt(season))
if(sznData !== undefined) {
let rankInfo = getArenaRank(sznData.rankPoint)
$('.arena-details').append(
$('<div class="tile is-parent is-7">').append(
$('<article class="tile is-child arena-details-child-left">').append(
// $('<img>', {
// src: 'static/asset/arena_icon/' + rankInfo[0] + ".png"
// })
$('<h1 style="font-size:100px">' + ((rankInfo[0] === 'none') ? 'n/a' : rankInfo[0].toUpperCase()) + "</h1>")
)
)
).append(
$('<div class="tile is-parent is-5" style="position:relative">').append(
$('<article class="tile is-child arena-details-child-right">').append(
$('<p class="title" style="font-family: testfont">Arena Power</p>').append(
$('<div class="content">' + sznData.shopPoint + ' AP </div>')
)
).append(
(sznData.megamixRate !== (0 || undefined)) ? $('<p class="title" style="font-family: testfont">Megamix Rate</p>').append(
$('<div class="content">' + sznData.megamixRate + '</div>')
) : $("<p></p>")
)
)
)
if(sznData.rankPoint >= 23600) {
$('.arena-details-child-right').append(
$('<p class="title" style="font-family: testfont">Rank Point</p>').append(
$('<div class="content">' + sznData.rankPoint + ' points</div>')
)
)
}
if(sznData.rankPoint !== 0 && sznData.rankPoint < 27800) {
$('.arena-details-child-left').append(
$('<meter id="rank-point-mtr" style="width:80%" min="' + rankInfo[1] + '"max="' + ((rankInfo[2] !== undefined) ? rankInfo[2].point : rankInfo[1]) + '" value="' + sznData.rankPoint + '"></meter>')
).append(
$('<h5 style="font-family: testfont">' + sznData.rankPoint + ' pts (' + (rankInfo[2].point - sznData.rankPoint) + ' pts to ' + rankInfo[2].rank.toUpperCase() + ')</h5>')
)
} else if(rankInfo[0] !== 'none'){
$('.arena-details-child-left').append(
$('<h5 style="font-family:testfont">Ultimate rate: ' + sznData.ultimateRate + '</h5>')
).append(
)
}
}
}
function getArenaRank(rp) {
let arenaRanksList = [
{ rank: 'none', point: 0 },
{ rank: 'd4', point: 1 },
{ rank: 'd3', point: 600 },
{ rank: 'd2', point: 1600 },
{ rank: 'd1', point: 2600 },
{ rank: 'c4', point: 3600 },
{ rank: 'c3', point: 4700 },
{ rank: 'c2', point: 5800 },
{ rank: 'c1', point: 6900 },
{ rank: 'b4', point: 8000 },
{ rank: 'b3', point: 9200 },
{ rank: 'b2', point: 10400 },
{ rank: 'b1', point: 11600 },
{ rank: 'a4', point: 12800 },
{ rank: 'a3', point: 14100 },
{ rank: 'a2', point: 15400 },
{ rank: 'a1', point: 16700 },
{ rank: 's4', point: 18000 },
{ rank: 's3', point: 19400 },
{ rank: 's2', point: 20800 },
{ rank: 's1', point: 22200 },
{ rank: 'u4', point: 23600 },
{ rank: 'u3', point: 25000 },
{ rank: 'u2', point: 26400 },
{ rank: 'u1', point: 27800 }
]
let prevRank = ''
let rankIndex = 0
let rankPointMin = 0
let rankPointNext = 0
arenaRanksList.forEach(rank => {
if(rp >= rank.point) {
prevRank = rank.rank
rankPointMin = rank.point
rankNext = arenaRanksList[rankIndex + 1]
}
rankIndex++;
})
return [prevRank, rankPointMin, rankNext]
}
$(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);
xrecord_data = JSON.parse(document.getElementById("xrecord-pass").innerText);
arena_data = JSON.parse(document.getElementById("arena-pass").innerText);
skill_data.sort(function(a, b) {
return b.version - a.version;
})
// console.log(score_db);
return b.version - a.version;
})
// console.log(score_db);
// $('#test').append(
// $('<div>').append(
@@ -692,31 +785,29 @@ $(document).ready(function() {
})
).then(function() {
var currentVF = calculateVolforce();
var maxVer = parseInt(skill_data[0]["version"])
var maxVer = skill_data.length > 0 ? parseInt(skill_data[0]["version"]) : 0
var versionInfo = getVersionSelect();
console.log(versionInfo);
for (var i = 0; i < versionInfo.length; i++) {
console.log(versionInfo[i])
if(versionInfo.length <= 0) {
$('#version_select').append(
$('<option>', {
value: versionInfo[i],
text: versionText[versionInfo[i]],
value: 0,
text: 'No data found',
})
)
$('#version_select').attr('disabled', 'disabled')
} else {
for (var i = 0; i < versionInfo.length; i++) {
console.log(versionInfo[i])
$('#version_select').append(
$('<option>', {
value: versionInfo[i],
text: versionText[versionInfo[i]],
})
)
}
}
var lm = vm = 0;
if(xrecord_data != null) {
lm = xrecord_data['lm'];
vm = xrecord_data['vm'];
}
var arenaPower = [];
arena_data.forEach(arena_sszn_data => {
arenaPower.push([arena_sszn_data.season, arena_sszn_data.shopPoint])
})
arenaPower.sort((a, b) => a[0] - b[0])
$('#test').append(
$('<div class="card is-inlineblocked">').append(
$('<div class="card-header">').append(
@@ -827,64 +918,29 @@ $(document).ready(function() {
$('<span class="icon">').append(
$('<i class="mdi mdi-pulse">')
)
).append("Arena")
).append("Arena Stats")
)
).append(
$('<div class="card-content">').append(
$('<div class="tile is-ancestor">').append(
$('<div class="tile is-parent">').append(
$('<article class="tile is-child box">').append(
$('<p class="title">').append(
"Arena Power"
).append(
$('<div class="content" id=arena-power-data>')
).css('font-family', "testfont")
$('<div class="tile is-child field">').append(
$('<div class="control">').append(
$('<div class="select">').append(
$('<select id="arena-szn-sel">')
)
)
)
)
).css('vertical-align', 'middle')
).append(
$('<div class="tile is-ancestor is-centered">').append(
$('<div class="tile is-parent arena-details">')
)
)
)
).append(
$('<div class="card is-inlineblocked">').append(
$('<div class="card-header">').append(
$('<p class="card-header-title">').append(
$('<span class="icon">').append(
$('<i class="mdi mdi-pulse">')
)
).append("X-record")
)
).append(
$('<div class="card-content">').append(
$('<div class="tile is-ancestor">').append(
$('<div class="tile is-parent">').append(
$('<article class="tile is-child box">').append(
$('<p class="title">').append(
"LM"
).append(
$('<div class="content">').append(
lm
)
).css('font-family', "testfont")
)
)
).append(
$('<div class="tile is-parent">').append(
$('<article class="tile is-child box">').append(
$('<p class="title">').append(
"VM"
).append(
$('<div class="content">').append(
vm
)
).css('font-family', "testfont")
)
)
).css('vertical-align', 'middle')
)
)
)
.append(
$('<div class="card">').append(
$('<div class="card-header">').append(
@@ -950,24 +1006,34 @@ $(document).ready(function() {
)
)
arenaPower.forEach(ap => {
console.log('yes' + ap)
$('#arena-power-data').append(
$('<article class="tile is-child box">').append(
$('<p class="title">').append(
"Season " + ap[0]
).append(
$('<div class="content">').append(
ap[1]
)
)
)
arena_data = arena_data.sort(function(a,b) { return a['season'] - b['season'] } )
if(arena_data.length <= 0) {
$('#arena-szn-sel').append(
$('<option>', {
value: 0,
text: 'No available arena data.',
})
)
})
$('#arena-szn-sel').attr('disabled', 'disabled')
} else {
arena_data.forEach(are => {
$('#arena-szn-sel').append(
$('<option>', {
value: are['season'],
text: 'Season: ' + are['season'],
})
)
})
}
$('#arena-szn-sel').change(function() {
$('.arena-details').empty()
displayArenaSeasonData($('#arena-szn-sel').val())
});
setUpStatistics();
setCMpD();
displayArenaSeasonData($('#arena-szn-sel').val())
$('.dots').fadeOut(400, function() {
+6 -30
View File
@@ -75,61 +75,37 @@ async function loadItems(itemSet, gene_edition, items_crew, items_stamp, items_s
if('crew' in geneItems.items) {
$('.item_banners').append('<div style="padding: 5px"><h3>Nemsys Crew</h3></div>')
$('.item_banners').append('<div class=crew-items style="text-align: center; background-color: #3a3a3a; padding: 20px; border-radius: 6px;"></div><br>')
loadImages(geneItems.items['crew'].sort(function(a, b) {
if(a.id < b.id) { return -1; }
if(a.id > b.id) { return 1; }
return 0;
}), 'crew', items_crew)
loadImages(geneItems.items['crew'].sort(function(a, b){return parseInt(a.id) - parseInt(b.id)}), 'crew', items_crew)
}
if('stamp' in geneItems.items) {
$('.item_banners').append('<div style="padding: 5px"><h3>Appeal Stamp</h3></div>')
$('.item_banners').append('<div class=stamp-items style="text-align: center; background-color: #3a3a3a; padding: 20px; border-radius: 6px;"></div><br>')
loadImages(geneItems.items['stamp'].sort(function(a, b) {
if(a.id < b.id) { return -1; }
if(a.id > b.id) { return 1; }
return 0;
}), 'stamp', items_stamp)
loadImages(geneItems.items['stamp'].sort(function(a, b){return parseInt(a.id) - parseInt(b.id)}), 'stamp', items_stamp)
}
if('subbg' in geneItems.items) {
$('.item_banners').append('<div style="padding: 5px"><h3>Submonitor BG</h3></div>')
$('.item_banners').append('<div class=bg-items style="text-align: center; background-color: #3a3a3a; padding: 20px; border-radius: 6px;"></div><br>')
loadImages(geneItems.items['subbg'].sort(function(a, b) {
if(a.id < b.id) { return -1; }
if(a.id > b.id) { return 1; }
return 0;
}), 'bg', items_subbg)
loadImages(geneItems.items['subbg'].sort(function(a, b){return parseInt(a.id) - parseInt(b.id)}), 'bg', items_subbg)
}
if('bgm' in geneItems.items) {
$('.item_banners').append('<div style="padding: 5px"><h3>BGM</h3></div>')
$('.item_banners').append('<div class=bgm-items style="text-align: center; background-color: #3a3a3a; padding: 20px; border-radius: 6px;"></div><br>')
loadImages(geneItems.items['bgm'].sort(function(a, b) {
if(a.id < b.id) { return -1; }
if(a.id > b.id) { return 1; }
return 0;
}), 'bgm', items_bgm)
loadImages(geneItems.items['bgm'].sort(function(a, b){return parseInt(a.id) - parseInt(b.id)}), 'bgm', items_bgm)
}
if('nemsys' in geneItems.items) {
$('.item_banners').append('<div style="padding: 5px"><h3>Nemsys</h3></div>')
$('.item_banners').append('<div class=nemsys-items style="text-align: center; background-color: #3a3a3a; padding: 20px; border-radius: 6px;"></div><br>')
loadImages(geneItems.items['nemsys'].sort(function(a, b) {
if(a.id < b.id) { return -1; }
if(a.id > b.id) { return 1; }
return 0;
}), 'nemsys', items_nemsys)
loadImages(geneItems.items['nemsys'].sort(function(a, b){return parseInt(a.id) - parseInt(b.id)}), 'nemsys', items_nemsys)
}
if('sysbg' in geneItems.items) {
$('.item_banners').append('<div style="padding: 5px"><h3>System BG</h3></div>')
$('.item_banners').append('<div class=sysbg-items style="text-align: center; background-color: #3a3a3a; padding: 20px; border-radius: 6px;"></div><br>')
loadImages(geneItems.items['sysbg'].sort(function(a, b) {
if(a.id < b.id) { return -1; }
if(a.id > b.id) { return 1; }
return 0;
}), 'sysbg', items_sysbg)
loadImages(geneItems.items['sysbg'].sort(function(a, b){return parseInt(a.id) - parseInt(b.id)}), 'sysbg', items_sysbg)
}
}
+19 -1
View File
@@ -208,6 +208,9 @@ $(document).ready(function() {
items_bgm = JSON.parse(document.getElementById("data-pass-bgm").innerText);
items_nemsys = JSON.parse(document.getElementById("data-pass-nemsys").innerText);
items_sysbg = JSON.parse(document.getElementById("data-pass-sysbg").innerText);
valgene_ticket = JSON.parse(document.getElementById("data-pass-valgeneticket").innerText);
courses = JSON.parse(document.getElementById("data-pass-courses").innerText);
skill = JSON.parse(document.getElementById("data-pass-skill").innerText);
unlock_all = (document.getElementById("data-pass-unlock-all").innerText === 'true');
$.getJSON("static/asset/json/customize_data_ext.json", function(json) {
@@ -230,6 +233,18 @@ $(document).ready(function() {
}
}
$('[name="sysBG"]').val(profile_data["sysBG"] ? profile_data["sysBG"] : 0);
for (var i in json["skilltitle"]) {
let foundCourses = courses.filter(c => c.cid === json["skilltitle"][i].id && c.clear >= 2)
if(foundCourses.length > 0) {
$('[name="skilltitle"]').append($('<option>', {
value: json["skilltitle"][i].id,
text: json["skilltitle"][i].name,
}));
}
}
if(skill.length > 0) $('[name="skilltitle"]').val(skill[0]["name"]);
else $('[name="skilltitle"]').attr('disabled')
});
$.getJSON("static/asset/json/data.json", function(json) {
@@ -239,7 +254,7 @@ $(document).ready(function() {
//console.log(profile_data);
for (var i in json["nemsys"]) {
if(unlock_all || (json["nemsys"][i].value === 0 || items_nemsys.find(x => x.id === json["nemsys"][i].value))) {
if(![8, 9, 10, 11].includes(json["nemsys"][i].value) && (unlock_all || (json["nemsys"][i].value === 0 || items_nemsys.find(x => x.id === json["nemsys"][i].value)))) {
$('#nemsys_select').append($('<option>', {
value: json["nemsys"][i].value,
text: json["nemsys"][i].name,
@@ -305,6 +320,9 @@ $(document).ready(function() {
}
$('[name="akaname"]').val(profile_data["akaname"]);
let ticketNum = (valgene_ticket !== null) ? valgene_ticket.ticketNum : 0
$('[name="valgeneTicket"]').val(ticketNum)
for (var i in json["stamp"]) {
if(unlock_all || (json["stamp"][i].value === 0 || items_stamp.find(x => x.id === json["stamp"][i].value))) {
$('[name="stampA"]').append($('<option>', {
+32 -29
View File
@@ -12,6 +12,37 @@ function getInfDifficulty(inf_ver) {
return "XCD"
}
}
function populateSongsList(music_data) {
$('#songslist').DataTable({
data: music_data,
columns: [
{ data: 'mid' },
{ data: 'songname' },
{ data: 'releasedate' },
{ data: 'nov', },
{ data: 'adv' },
{ data: 'exh' },
{ data: 'mxm' },
{ data: 'oth' }
],
columnDefs: [
],
responsive: {
details: {
display: $.fn.dataTable.Responsive.display.modal({
header: function(row) {
var data = row.data();
return 'Details for ' + data.songname;
}
})
}
},
});
}
$(document).ready(function() {
$.getJSON("static/asset/json/music_db.json", function(json) {
const translate_table = {
@@ -79,35 +110,7 @@ $(document).ready(function() {
music_data.push(temp_data);
}
$('#songslist').DataTable({
data: music_data,
columns: [
{ data: 'mid' },
{ data: 'songname' },
{ data: 'releasedate' },
{ data: 'nov', },
{ data: 'adv' },
{ data: 'exh' },
{ data: 'mxm' },
{ data: 'oth' }
],
columnDefs: [
],
responsive: {
details: {
display: $.fn.dataTable.Responsive.display.modal({
header: function(row) {
var data = row.data();
return 'Details for ' + data.songname;
}
})
}
},
});
populateSongsList(music_data);
});
File diff suppressed because it is too large Load Diff
@@ -54,5 +54,83 @@
"id": 3,
"name": "Gravity Wars"
}
],
"skilltitle": [
{
"id": 1,
"name": "岳翔 (Lv01)"
},
{
"id": 2,
"name": "流星 (Lv02)"
},
{
"id": 3,
"name": "月衝 (Lv03)"
},
{
"id": 4,
"name": "瞬光 (Lv04)"
},
{
"id": 5,
"name": "天極 (Lv05)"
},
{
"id": 6,
"name": "烈風 (Lv06)"
},
{
"id": 7,
"name": "雷電 (Lv07)"
},
{
"id": 8,
"name": "麗華 (Lv08)"
},
{
"id": 9,
"name": "魔騎士 (Lv09)"
},
{
"id": 10,
"name": "剛力羅 (Lv10)"
},
{
"id": 11,
"name": "或帝滅斗 (Lv11)"
},
{
"id": 12,
"name": "暴龍天 (Lv∞)"
},
{
"id": 13,
"name": "BMK2021 (BEMANI MASTER KOREA 2021)"
},
{
"id": 14,
"name": "天晴 (10th Anniversary)"
},
{
"id": 15,
"name": "詠鰤琉 (New Life Support)"
},
{
"id": 16,
"name": "Red Bull (Red Bull 5G 2022)"
},
{
"id": 17,
"name": "U.S.O. (Spring Volte Festival 2023)"
},
{
"id": 18,
"name": "完喰 (KAC 2023 Challenge Round A)"
},
{
"id": 19,
"name": "夢吹 (KAC 2023 Challenge Round B)"
}
]
}
+1 -1
View File
@@ -185,7 +185,7 @@
},
{
"id": "bpls3songs",
"type": "gift",
"type": "cross_online",
"enabled": true,
"name": "BEMANI PRO LEAGUE -SEASON 3- Triple Tribe",
"desc": "Crossover event between SOUND VOLTEX EXCEED GEAR, DanceDanceRevolution A3, and beatmania IIDX 30 RESIDENT where you would earn TD, TB and TS points which can be used to unlock songs through the participating games.<br>However, since it's difficult to replicate such crossover event in Asphyxia, you can just toggle the corresponding SOUND VOLTEX songs' option to automatically unlock them on your next login.",
@@ -2,7 +2,7 @@
"pregene": [
{
"id": 1,
"name": "Premium Generator(この素晴らしい世界に祝福を!)- KonoSuba",
"name": "Premium Generator(この素晴らしい世界に祝福を!)",
"items": {
"crew": [131],
"stamp": [69, 70, 71, 72, 73, 74, 75, 76, 77, 78],
@@ -54,6 +54,15 @@
"subbg": [359, 360, 361, 362, 363, 364, 365, 366, 367, 368],
"sysbg": [1, 2, 3]
}
},
{
"id": 7,
"name": "Premium Generator(白上フブキ)",
"items": {
"crew": [143],
"stamp": [249, 250, 251, 252, 253, 254, 255, 256, 257, 258],
"subbg": [369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381]
}
}
],
"valgene":[
+4 -5
View File
@@ -2,7 +2,6 @@
profile: DB.FindOne(refid, { collection: 'profile' })
score_data: DB.Find(refid, { collection: 'music' })
skill_data: DB.Find(refid,{collection: 'skill'})
xrecord_data: DB.FindOne(refid,{collection: 'x-record'})
arena_data: DB.Find(refid,{collection: 'arena'})
-
@@ -20,9 +19,10 @@ div
.card-content
.field
label.label Skill Version Select
.control
.select
select(name="version_select" id="version_select")
.ver-select
.control
.select
select(name="version_select" id="version_select")
div(style="width:100%;text-align:center;vertical-align:middle;")
div(class="dots is-centered" )
div
@@ -33,6 +33,5 @@ div
div(hidden id='data-pass') !{JSON.stringify(profile)}
div(hidden id='score-pass') !{JSON.stringify(score_data)}
div(hidden id='skill-pass') !{JSON.stringify(skill_data)}
div(hidden id='xrecord-pass') !{JSON.stringify(xrecord_data)}
div(hidden id='arena-pass') !{JSON.stringify(arena_data)}
script(src="static/asset/js/detail.js")
+28 -6
View File
@@ -3,15 +3,21 @@
items_crew: DB.Find(refid, {$or:[{collection:"item",type:11,id:117}, {collection:"item",type:11,id:119}, {collection:"item",type:11,id:120}, {collection:"item",type:11,id:121}, {collection:"item",type:11,id:124}, {collection:"item",type:11,id:129}]})
items_stamp: DB.Find(refid, { collection:"item",type:17 })
items_stamp: DB.Find(refid, { collection:"item", type:17 })
items_subbg: DB.Find(refid, { collection:"item",type:18 })
items_subbg: DB.Find(refid, { collection:"item", type:18 })
items_bgm: DB.Find(refid, { collection:"item",type:19 })
items_bgm: DB.Find(refid, { collection:"item", type:19 })
items_nemsys: DB.Find(refid, { collection:"item",type:20 })
items_nemsys: DB.Find(refid, { collection:"item", type:20 })
items_sysbg: DB.Find(refid, { collection:"item",type:21 })
items_sysbg: DB.Find(refid, { collection: "item", type:21 })
valgene_tickets: DB.FindOne(refid, { collection: "valgene_ticket" })
courses: DB.Find(refid, {collection: "course"})
skill: DB.Find(refid, {collection: "skill"})
unlock_all: U.GetConfig('unlock_all_valk_items')
@@ -51,7 +57,14 @@ div
.control
input.input(type="number" step=1 name="appeal", placeholder=profile.appeal)
.field
label.label Akaname
label.label Skill Title
span.icon.has-tooltip-right(data-tooltip="Changes the title displayed on your skill plate.")
i.mdi.mdi-help-circle
.control.is-expanded
.select.is-fullwidth
select(name="skilltitle" id="skilltitle_select")
.field
label.label Appeal Title
span.icon.has-tooltip-right(data-tooltip="Custom is set as ID 50000, if you want to use custom, please make sure you add the entry to the xml file.")
i.mdi.mdi-help-circle
.control.is-expanded
@@ -64,6 +77,12 @@ div
.control.is-expanded
.select.is-fullwidth
select(name="bplSupport" id="bplsupport_select")
.field
label.label Valgene Tickets
span.icon.has-tooltip-right(data-tooltip="Number of tickets you can use to buy Valkyrie Generator Items, instead of PASELI or credits.")
i.mdi.mdi-help-circle
.control.is-expanded
input.input(type="number" name="valgeneTicket" id="valgeneticket_select")
br
div(style="font-size:26px;font-weight:bold;vertical-align:top; overflow-wrap: break-word;word-break: break-all;") EXCEED GEAR VALKYRIE GENERATOR CUSTOMIZATION
.tile.is-ancestor
@@ -242,6 +261,9 @@ div(hidden id='data-pass-subbg') !{JSON.stringify(items_subbg)}
div(hidden id='data-pass-bgm') !{JSON.stringify(items_bgm)}
div(hidden id='data-pass-nemsys') !{JSON.stringify(items_nemsys)}
div(hidden id='data-pass-sysbg') !{JSON.stringify(items_sysbg)}
div(hidden id='data-pass-valgeneticket') !{JSON.stringify(valgene_tickets)}
div(hidden id='data-pass-courses') !{JSON.stringify(courses)}
div(hidden id='data-pass-skill') !{JSON.stringify(skill)}
div(hidden id='data-pass-unlock-all') !{unlock_all}
script(src="static/asset/js/preview.js")
script(src="https://vjs.zencdn.net/8.5.2/video.min.js")
@@ -0,0 +1,39 @@
//DATA//
achievements: DB.Find(refid, { collection: 'item', type: 10 })
-
//const padded = _.padStart(achievements.id.toString(), 8);
//const sdvxid = `${padded.slice(0, 4)}-${padded.slice(4)}`;
link(rel="stylesheet" href="static/asset/css/datatables.css")
div
.card
.card-header
p.card-header-title
span.icon
i.mdi.mdi-account-edit
| Achievements
.card-content
.ach-filter
p() Filter
.field
.control
.select
select(id="ach-filter")
option(value=1) Complete
option(value=2) Incomplete
option(value=3) All
br
.ach-list
table.table(id="achlist" style="width:100%")
thead
tr
th #
th Achievement
th Status
th Reward
tbody
div(hidden id='data-pass') !{JSON.stringify(achievements)}
script(src="static/asset/js/achievements.js")
script(src="static/asset/js/datatables.js")
+2 -3
View File
@@ -12,10 +12,9 @@ div
br
p.card-header-bgm-guide
h5() BGM asset guide
p() This feature pulls BGM files from the data, however they are in unplayable s3p format. For BGM preview to work, we need to extract the audio files from the s3p, and convert it to mp3.
p() For Windows, there is a bgm_convert.bat script in the SDVX plugin root directory but it requires 2 things:
p() This feature pulls BGM files from the data, however they are in the WMA file format, which is unsupported. For BGM preview to work, they have to be converted to MP3 format.
p() To convert these files to MP3, you can use ffmpeg. If you have ffmpeg already installed, there is a bgm_convert.bat script in the SDVX plugin directory that can automate the conversion to mp3.
ul
li() <a href="https://github.com/mon/s3p_extract/releases/latest">s3p_extract</a> - download the .exe file from the latest release and put in the same directory as the bat script
li() <a href="https://www.gyan.dev/ffmpeg/builds/">ffmpeg</a> - download and extract ffmpeg.exe and put it in the same directory as the bat script (or put ffmpeg.exe in PATH environment variable)
.card
.card-header