diff --git a/ddr@asphyxia/README.md b/ddr@asphyxia/README.md index 3657178..958e422 100644 --- a/ddr@asphyxia/README.md +++ b/ddr@asphyxia/README.md @@ -1,6 +1,6 @@ # DanceDanceRevolution -**Plugin Version:** fork-mdx-3.0.0 +**Plugin Version:** fork-mdx-3.0.0a **Supported game versions:** WORLD (2024061300) @@ -17,6 +17,19 @@ Changelog =========== +## fork-mdx-3.0.0a + +### New: + +1. Main: + - Flare skill song unlock event + - Added event data (ddr@asphyxia/data/world.ts:EVENTS_WORLD) + - Fixes crashes on Flare Skill rank up (at least until Mercury, haven't tested higher than that yet.) + - musicdata_load + - Put your musicdb.xml on 'ddr@asphyxia/data' folder. Tested with A3 musicdb.xml + - Added musicdata for new WORLD songs (ddr@asphyxia/data/world.ts:SONGS_WORLD) + + ## fork-mdx-3.0.0 ### New: @@ -31,7 +44,7 @@ Changelog ### To do: -1. Make songs appear -2. Look for more missing features (I don't play DDR so idk what's missing lol) -3. Check bugs (on score loading, profile saving, etc.) -4. Transfer old save data to World (?) + +1. Look for more missing features (I don't play DDR so idk what's missing lol) +2. Check flare skill value consistency +3. Transfer old save data to World (?) diff --git a/ddr@asphyxia/data/.gitignore b/ddr@asphyxia/data/.gitignore new file mode 100644 index 0000000..6722cd9 --- /dev/null +++ b/ddr@asphyxia/data/.gitignore @@ -0,0 +1 @@ +*.xml diff --git a/ddr@asphyxia/data/world.ts b/ddr@asphyxia/data/world.ts new file mode 100644 index 0000000..60c2816 --- /dev/null +++ b/ddr@asphyxia/data/world.ts @@ -0,0 +1,107 @@ +export const SONGS_WORLD = [ + { + mcode: 38665, + limited_ary: [2, 2, 2, 2, 2, -1, 2, 2, 2, 2], + diffLv: [3, 6, 10, 13, 15, 0, 6, 10, 13, 15] + }, + { + mcode: 38661, + limited_ary: [2, 2, 2, 2, -1, -1, 2, 2, 2, -1], + diffLv: [3, 5, 9, 12, 0, 0, 5, 9, 12, 0] + }, + { + mcode: 38659, + limited_ary: [2, 2, 2, 2, 2, -1, 2, 2, 2, 2], + diffLv: [3, 7, 12, 14, 16, 0, 7, 12, 14, 16] + }, + { + mcode: 38669, + limited_ary: [2, 2, 2, 2, 2, -1, 2, 2, 2, 2], + diffLv: [3, 7, 11, 14, 15, 0, 7, 11, 14, 15] + }, + { + mcode: 38668, + limited_ary: [2, 2, 2, 2, -1, -1, 2, 2, 2, -1], + diffLv: [3, 6, 10, 13, 0, 0, 6, 10, 13, 0] + }, + { + mcode: 38667, + limited_ary: [2, 2, 2, 2, -1, -1, 2, 2, 2, -1], + diffLv: [3, 6, 9, 12, 0, 0, 6, 9, 12, 0] + }, + { + mcode: 38731, + limited_ary: [0, 0, 0, 0, -1, -1, 0, 0, 0, -1], + diffLv: [1, 3, 9, 13, 0, 0, 3, 9, 12, 0] + }, + { + mcode: 38722, + limited_ary: [0, 0, 0, 0, -1, -1, 0, 0, 0, -1], + diffLv: [2, 6, 10, 14, 0, 0, 6, 10, 14, 0] + }, + { + mcode: 38704, + limited_ary: [0, 0, 0, 0, -1, -1, 0, 0, 0, -1], + diffLv: [1, 4, 9, 12, 0, 0, 4, 9, 12, 0] + }, + { + mcode: 38724, + limited_ary: [0, 0, 0, 0, -1, -1, 0, 0, 0, -1], + diffLv: [3, 5, 9, 13, 0, 0, 4, 9, 13, 0] + }, + { + mcode: 38730, + limited_ary: [0, 0, 0, 0, -1, -1, 0, 0, 0, -1], + diffLv: [2, 4, 8, 13, 0, 0, 4, 8, 13, 0] + }, + { + mcode: 38723, + limited_ary: [0, 0, 0, 0, 0, -1, 0, 0, 0, 0], + diffLv: [2, 4, 9, 14, 12, 0, 5, 10, 14, 12] + }, + { + mcode: 38721, + limited_ary: [0, 0, 0, 0, -1, -1, 0, 0, 0, -1], + diffLv: [2, 4, 8, 12, 0, 0, 4, 8, 12, 0] + }, + { + mcode: 38706, + limited_ary: [0, 0, 0, 0, -1, -1, 0, 0, 0, -1], + diffLv: [1, 4, 9, 13, 0, 0, 4, 9, 13, 0] + }, + { + mcode: 38705, + limited_ary: [0, 0, 0, 0, -1, -1, 0, 0, 0, -1], + diffLv: [2, 6, 10, 13, 0, 0, 6, 10, 13, 0] + } +] + +export const EVENTS_WORLD = [ + { id: 1, no: 1, sid: 38667, type: 70 }, + { id: 2, no: 1, sid: 38667, type: 71 }, + { id: 3, no: 1, sid: 38667, type: 72 }, + { id: 4, no: 1, sid: 38667, type: 73 }, + { id: 5, no: 1, sid: 38661, type: 70 }, + { id: 6, no: 1, sid: 38661, type: 71 }, + { id: 7, no: 1, sid: 38661, type: 72 }, + { id: 8, no: 1, sid: 38661, type: 73 }, + { id: 9, no: 1, sid: 38668, type: 70 }, + { id: 10, no: 1, sid: 38668, type: 71 }, + { id: 11, no: 1, sid: 38668, type: 72 }, + { id: 12, no: 1, sid: 38668, type: 73 }, + { id: 13, no: 1, sid: 38665, type: 70 }, + { id: 14, no: 1, sid: 38665, type: 71 }, + { id: 15, no: 1, sid: 38665, type: 72 }, + { id: 16, no: 1, sid: 38665, type: 73 }, + { id: 17, no: 1, sid: 38665, type: 74 }, + { id: 18, no: 1, sid: 38669, type: 70 }, + { id: 19, no: 1, sid: 38669, type: 71 }, + { id: 20, no: 1, sid: 38669, type: 72 }, + { id: 21, no: 1, sid: 38669, type: 73 }, + { id: 22, no: 1, sid: 38669, type: 74 }, + { id: 23, no: 1, sid: 38659, type: 70 }, + { id: 24, no: 1, sid: 38659, type: 71 }, + { id: 25, no: 1, sid: 38659, type: 72 }, + { id: 26, no: 1, sid: 38659, type: 73 }, + { id: 27, no: 1, sid: 38659, type: 74 } +] \ No newline at end of file diff --git a/ddr@asphyxia/handlers/ddrworld.ts b/ddr@asphyxia/handlers/ddrworld.ts index 03a5071..aa3ef6a 100644 --- a/ddr@asphyxia/handlers/ddrworld.ts +++ b/ddr@asphyxia/handlers/ddrworld.ts @@ -1,5 +1,34 @@ import { Profile } from "../models/profile"; -import { ProfileWorld, ScoreWorld } from "../models/ddrworld"; +import { ProfileWorld, ScoreWorld, EventWorld } from "../models/ddrworld"; +import { SONGS_WORLD, EVENTS_WORLD } from "../data/world"; + +async function saveScores(refid: string, songId: number, style: number, difficulty: number, rank: number, clearKind: number, score: number, exScore: number, maxCombo: number, flareForce: number, ghostSize: number, ghost: string) { + let stepScore = await DB.Find(refid, {collection: "score3", songId: songId, style: style, difficulty: difficulty}) + if(stepScore.length > 0) { + rank = (rank < stepScore[0].rank) ? rank : stepScore[0].rank; + clearKind = (clearKind != 6 && clearKind > stepScore[0].clearKind) ? clearKind : stepScore[0].clearKind; + score = (score > stepScore[0].score) ? score : stepScore[0].score; + exScore = (exScore > stepScore[0].exScore) ? exScore : stepScore[0].exScore; + maxCombo = (maxCombo > stepScore[0].maxCombo) ? maxCombo : stepScore[0].maxCombo; + flareForce = (flareForce > stepScore[0].flareForce) ? flareForce : stepScore[0].flareForce; + } + + await DB.Upsert(refid, { + collection: "score3", + songId, + style, + difficulty + }, { + $set: { + rank, + clearKind, + score, + exScore, + maxCombo, + flareForce + } + }); +} export const playerdatanew: EPR = async (info, data, send) => { const refid = $(data).str("data.refid"); @@ -20,9 +49,6 @@ export const playerdatanew: EPR = async (info, data, send) => { export const playerdatasave: EPR = async (info, data, send) => { const refid = $(data).str("data.refid"); - console.log('playerdatasave') - console.log(JSON.stringify($(info))) - console.log(JSON.stringify($(data))) if(!refid.startsWith("X000")) { if($(data).number("data.savekind") === 1) { await DB.Upsert(refid, { collection: "profile3" }, { @@ -94,6 +120,20 @@ export const playerdatasave: EPR = async (info, data, send) => { cgGuideScene: $(data).number('data.checkguide.guide_scene') }) } + else if($(data).number("data.savekind") === 2) { + let songId = $(data).number("data.result.mcode"); + let style = $(data).number("data.result.style"); + let difficulty = $(data).number("data.result.difficulty"); + let rank = $(data).number("data.result.rank"); + let clearKind = $(data).number("data.result.clearkind"); + let score = $(data).number("data.result.score"); + let exScore = $(data).number("data.result.exscore"); + let maxCombo = $(data).number("data.result.maxcombo"); + let flareForce = $(data).number("data.result.flare_force"); + let ghostSize = $(data).number("data.result.ghostsize"); + let ghost = $(data).str("data.result.ghost"); + saveScores(refid, songId, style, difficulty, rank, clearKind, score, exScore, maxCombo, flareForce, ghostSize, ghost) + } else if($(data).number("data.savekind") === 3) { let profile = await DB.FindOne(refid, {collection: "profile3"}) await DB.Upsert(refid, { collection: "profile3" }, { @@ -165,55 +205,34 @@ export const playerdatasave: EPR = async (info, data, send) => { cgGuideScene: $(data).number('data.checkguide.guide_scene') }) - let scores = $(data).elements('data.result') - for(const scoreData of scores) { - const songId = scoreData.number("mcode"); - const style = scoreData.number("style"); - const difficulty = scoreData.number("difficulty"); - let rank = scoreData.number("rank"); - let clearKind = scoreData.number("clearkind"); - let score = scoreData.number("score"); - let exScore = scoreData.number("exscore"); - let maxCombo = scoreData.number("maxcombo"); - let flareForce = scoreData.number("flare_force"); - let ghostSize = scoreData.number("ghostsize"); - let ghost = scoreData.str("ghost"); + let eventData = $(data).elements('data.event') + if(eventData) { + for(const e of eventData) { + let eid = e.number('eventid') + let eno = e.number('eventno') + let etype = e.number('eventtype') + let ctime = getDate() + let sdata = e.number('savedata') - let stepScore = await DB.Find(refid, {collection: "score3", songId: songId, style: style, difficulty: difficulty}) - if(stepScore.length > 0) { - rank = (scoreData.number("rank") < stepScore[0].rank) ? scoreData.number("rank") : stepScore[0].rank; - clearKind = (scoreData.number("clearkind") != 6 && scoreData.number("clearkind") > stepScore[0].clearKind) ? scoreData.number("clearkind") : stepScore[0].clearKind; - score = (scoreData.number("score") > stepScore[0].score) ? scoreData.number("score") : stepScore[0].score; - exScore = (scoreData.number("exscore") > stepScore[0].exScore) ? scoreData.number("exscore") : stepScore[0].exScore; - maxCombo = (scoreData.number("maxcombo") > stepScore[0].maxCombo) ? scoreData.number("maxcombo") : stepScore[0].maxCombo; - flareForce = (scoreData.number("flare_force") > stepScore[0].flareForce) ? scoreData.number("flare_force") : stepScore[0].flareForce; + await DB.Upsert(refid, { collection: "event3", eventId: eid }, { + collection: "event3", + eventId: eid, + eventNo: eno, + eventType: etype, + compTime: ctime, + saveData: sdata + }) } - - await DB.Upsert(refid, { - collection: "score3", - songId, - style, - difficulty - }, { - $set: { - rank, - clearKind, - score, - exScore, - maxCombo, - flareForce - } - }); } } return send.object({ - result: K.ITEM('s32', 0) + result: K.ITEM("s32", 0) }) } return send.object({ - result: K.ITEM('s32', 1) + result: K.ITEM("s32", 1) }) }; @@ -240,19 +259,27 @@ export const playerdataload: EPR = async (info, data, send) => { */ scr[(scoreData.style === 0) ? 'score_single' : 'score_double'] = [ { - score_str: K.ITEM('str', scoreData.difficulty + ',1,' + scoreData.rank + ',' + scoreData.clearKind + ',' + scoreData.score + ',' + scoreData.maxCombo + ',' + scoreData.flareForce + ',' + scoreData.flareForce) + score_str: K.ITEM('str', scoreData.difficulty + ',1,' + scoreData.rank + ',' + scoreData.clearKind + ',' + scoreData.score + ',' + scoreData.exScore + ',' + scoreData.flareForce + ',' + scoreData.flareForce) } ] scoreFin.push(scr) } else { scoreFin[mcodeIndex][(scoreData.style === 0) ? 'score_single' : 'score_double'].push({ - score_str: K.ITEM('str', scoreData.difficulty + ',1,' + scoreData.rank + ',' + scoreData.clearKind + ',' + scoreData.score + ',' + scoreData.maxCombo + ',' + scoreData.flareForce + ',' + scoreData.flareForce) + score_str: K.ITEM('str', scoreData.difficulty + ',1,' + scoreData.rank + ',' + scoreData.clearKind + ',' + scoreData.score + ',' + scoreData.exScore + ',' + scoreData.flareForce + ',' + scoreData.flareForce) }) } } } + let eventFin = [] + for(const event of EVENTS_WORLD) { + let eventData = await DB.FindOne(refid, { collection: "event3", eventId: event.id, eventNo: event.no }); + eventFin.push({ + event_str: K.ITEM('str', event.id + ',' + event.type + ',' + event.no + ',0,' + event.sid + ',' + ((eventData) ? BigInt(eventData.compTime) : '0') + ',' + ((eventData) ? eventData.saveData : '0')) + }) + } + if(!profile) { if(profile_a3) { return send.object({ @@ -449,7 +476,7 @@ export const playerdataload: EPR = async (info, data, send) => { }, rival: [], score: scoreFin, - event: [] + event: eventFin }); } return send.object({ @@ -459,10 +486,32 @@ export const playerdataload: EPR = async (info, data, send) => { }; export const musicdataload: EPR = async (info, data, send) => { - console.log('musicdataload') - console.log("----------------------") - let musicList = [] + if(IO.Exists('data/musicdb.xml')) { + let mdb = U.parseXML(U.DecodeString(await IO.ReadFile('data/musicdb.xml'), "shift_jis"), false) + for(const music of mdb['mdb']['music']) { + let difficultyArr = $(music).numbers('diffLv') + let limited = ($(music).number('limited')) ? $(music).number('limited') : 0 + for(const [index, diff] of difficultyArr.entries()) { + limited = ($(music).numbers('limited_ary')) ? $(music).numbers('limited_ary')[index] : limited + limited = ((index % 5 === 4) && $(music).number('limited_cha')) ? $(music).number('limited_cha') : limited + musicList.push({ + music_str: K.ITEM('str', $(music).number('mcode') + ',' + ((index > 4) ? '1,' : '0,') + (index % 5) + ',' + limited + ',' + diff) + }) + } + } + } + + for(const music of SONGS_WORLD) { + for(const [index, diff] of music.diffLv.entries()) { + if(music.limited_ary[index] != -1) { + musicList.push({ + music_str: K.ITEM('str', music.mcode + ',' + ((index > 4) ? '1,' : '0,') + (index % 5) + ',' + music.limited_ary[index] + ',' + diff) + }) + } + } + } + return send.object({ result: K.ITEM("s32", 0), servertime: K.ITEM("u64", BigInt(getDate())), @@ -471,9 +520,10 @@ export const musicdataload: EPR = async (info, data, send) => { }; export const rivaldataload: EPR = async (info, data, send) => { - console.log('rivaldataload') - console.log("----------------------") - return send.deny(); + return send.object({ + result: K.ITEM("s32", 0), + record: [] + }); }; export const taboowordcheck: EPR = async (info, data, send) => { @@ -484,9 +534,9 @@ export const taboowordcheck: EPR = async (info, data, send) => { }); }; -function getDate(): BigInt { +function getDate(): number { let time = new Date(); let tempDate = time.getDate(); const currentTime = parseInt((time.getTime()/100000) as unknown as string)*100; - return BigInt(currentTime) + return currentTime } diff --git a/ddr@asphyxia/models/ddrworld.ts b/ddr@asphyxia/models/ddrworld.ts index 1646ba0..0df7f19 100644 --- a/ddr@asphyxia/models/ddrworld.ts +++ b/ddr@asphyxia/models/ddrworld.ts @@ -21,6 +21,16 @@ export interface ScoreWorld { flareForce: number; } +export interface EventWorld { + collection: "event3"; + + eventId: number; + eventNo: number; + eventType: number; + compTime: number; + saveData: number; +} + export interface ProfileWorld { collection: "profile3"; diff --git a/ddr@asphyxia/webui/profile_settings.pug b/ddr@asphyxia/webui/profile_settings.pug index 050bdae..1edb120 100644 --- a/ddr@asphyxia/webui/profile_settings.pug +++ b/ddr@asphyxia/webui/profile_settings.pug @@ -1,5 +1,6 @@ //DATA// profile: DB.FindOne(refid, { collection: "profile" }) + profile3: DB.FindOne(refid, { collection: "profile3" }) - const onOff = [ "Off", "On" ]; @@ -9,7 +10,7 @@ const filters = [ "Off", "Dark", "Darker", "Darkest" ]; const judgmentPrioritys = [ "Judgment priority", "Arrow priority" ]; -if (profile.usergamedata) +if profile - const common = profile.usergamedata.COMMON.strdata.split(","); const option = profile.usergamedata.OPTION.strdata.split(","); @@ -144,4 +145,136 @@ if (profile.usergamedata) p.control a.button.is-primary#change-display-timing Submit +else if profile3 + - + const name = profile3.dancerName; + const weight = profile3.weight; + const dispWeight = profile3.isDispWeight; + // const character = parseInt(common[4]); + const arrowSkin = profile3.arrowDesign; + const guideline = profile3.opGuideline; + // const filter = parseInt(option[12]); + const judgmentPriority = profile3.arrowPriority; + const displayTiming = profile3.opTimingDisp; + + div + .card + .card-header + p.card-header-title + span.icon + i.mdi.mdi-cog + | Profile (WIP) + + .card-content + .field.is-horizontal.has-addons + .field-label.is-normal + label.label Dancer Name + .field-body + p.control + input.input(type="text", id="dancer_name", pattern="[A-Z]{8}", maxlength=8, value=name) + //- p.control + //- a.button.is-primary#change-name Change + + //- .field.is-horizontal.has-addons + //- .field-label.is-normal + //- label.label Workout Weight + //- .field-body + //- p.control + //- input.input(type="number", id="weight_1", value=weight.split(".")[0]) + //- p.control + //- input.input(type="number", id="weight_2", value=weight.split(".")[1]) + //- p.control + //- a.button.is-primary#change-weight Change + + //- .field.is-horizontal.has-addons + //- .field-label.is-normal + //- label.label Workout Display Calories + //- .field-body + //- p.control + //- .select + //- select#display_calories + //- if (dispWeight === 1) + //- option(value=0) Off + //- option(value=1, selected) On + //- else + //- option(value=0, selected) Off + //- option(value=1) On + //- p.control + //- a.button.is-primary#change-display-calories Submit + + //- .field.is-horizontal.has-addons + //- .field-label.is-normal + //- label.label Arrow Skin + //- .field-body + //- p.control + //- .select + //- select#arrow_skin + //- each v, i in arrowSkins + //- if (arrowSkin === i) + //- option(value=i, selected) #{v} + //- else + //- option(value=i) #{v} + //- p.control + //- a.button.is-primary#change-arrow-skin Submit + + //- .field.is-horizontal.has-addons + //- .field-label.is-normal + //- label.label Guideline + //- .field-body + //- p.control + //- .select + //- select#guideline + //- each v, i in guidelines + //- if (guideline === i) + //- option(value=i, selected) #{v} + //- else + //- option(value=i) #{v} + //- p.control + //- a.button.is-primary#change-guideline Submit + + //- .field.is-horizontal.has-addons + //- .field-label.is-normal + //- label.label Filter concentration + //- .field-body + //- p.control + //- .select + //- select#filter + //- each v, i in filters + //- if (filter === i) + //- option(value=i, selected) #{v} + //- else + //- option(value=i) #{v} + //- p.control + //- a.button.is-primary#change-filter Submit + + //- .field.is-horizontal.has-addons + //- .field-label.is-normal + //- label.label Judgment display priority + //- .field-body + //- p.control + //- .select + //- select#judgment_priority + //- each v, i in judgmentPrioritys + //- if (judgmentPriority === i) + //- option(value=i, selected) #{v} + //- else + //- option(value=i) #{v} + //- p.control + //- a.button.is-primary#change-judgment-priority Submit + + //- .field.is-horizontal.has-addons + //- .field-label.is-normal + //- label.label Display Timing judgment + //- .field-body + //- p.control + //- .select + //- select#display_timing + //- each v, i in ["Off", "On"] + //- if (displayTiming === i) + //- option(value=i, selected) #{v} + //- else + //- option(value=i) #{v} + //- p.control + //- a.button.is-primary#change-display-timing Submit + script(src="static/js/profile_settings.js")