3 Commits
Author SHA1 Message Date
vvo 39d517ba5a doubles rank up fix 2024-06-20 16:24:48 +08:00
vvo 97a9e65682 mdx: flare unlock event 2024-06-20 16:24:38 +08:00
vvo c9c59e0872 mdx-240613 (experimental) 2024-06-20 16:24:27 +08:00
8 changed files with 957 additions and 17 deletions
+57 -10
View File
@@ -1,18 +1,65 @@
# Dance Dance Revolution
# DanceDanceRevolution
![Version](https://img.shields.io/badge/Version-v1.0.0-brightgreen?style=for-the-badge)
**Plugin Version:** fork-mdx-3.0.0b
---
**Supported game versions:** WORLD (2024061300)
Supported version
**Unsupported game versions:** Everything below A20 is unsupported. A20 untested. A3 unsupported.
- Dance Dance Revolution A20
- Dance Dance Revolution A
**Required Asphyxia Core version** [1.50c](https://github.com/asphyxia-core/asphyxia-core.github.io/releases/tag/v1.50)
---
**Notes:**
- This is a highly experimental messily-written plugin for MDX-2024061300 and things **WILL** break, please do not use any of your personal save data on this plugin. Use this for experimental & development purposes only. I am not responsible for any problems with your savedata.
- 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.
- Please back up your save data to prevent unwanted issues, especially while using this experimental plugin.
- Please please please feel free to open PRs!
Changelogs
**v1.0.0**
Changelog
===========
## fork-mdx-3.0.0b
- Initial release
### New:
1. Main:
- Flare skill song unlock event.... on Doubles.
- Fixes crashes on Flare Skill rank up.... on Doubles (again, just tested until Mercury.)
- Event list updated
- ghostdata saving and loading (WIP, idk what ghost is)
## 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:
1. Main:
- 2024061300 support (DDR World)
- DDR profile registration for new and existing Asphyxia profiles
- For Asphyxia profiles with no prior DDR A20/A3 profiles registered.
- Transfer from A3 not supported (yet?)
- Profile saving and loading (probably incomplete)
- Score saving and loading (probably incomplete)
### To do:
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 from A3 to World (?)
4. Update re-rated song difficulties
5. WebUI Profile page
6. More work on score_str
7. Rival load
+1
View File
@@ -0,0 +1 @@
*.xml
+32
View File
@@ -0,0 +1,32 @@
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 }, { id: 28, no: 1, sid: 38667, type: 81 },
{ id: 29, no: 1, sid: 38667, type: 82 }, { id: 30, no: 1, sid: 38667, type: 83 }, { id: 31, no: 1, sid: 38661, type: 81 }, { id: 32, no: 1, sid: 38661, type: 82 },
{ id: 33, no: 1, sid: 38661, type: 83 }, { id: 34, no: 1, sid: 38668, type: 81 }, { id: 35, no: 1, sid: 38668, type: 82 }, { id: 36, no: 1, sid: 38668, type: 83 },
{ id: 37, no: 1, sid: 38665, type: 81 }, { id: 38, no: 1, sid: 38665, type: 82 }, { id: 39, no: 1, sid: 38665, type: 83 }, { id: 40, no: 1, sid: 38665, type: 84 },
{ id: 41, no: 1, sid: 38669, type: 81 }, { id: 42, no: 1, sid: 38669, type: 82 }, { id: 43, no: 1, sid: 38669, type: 83 }, { id: 44, no: 1, sid: 38669, type: 84 },
{ id: 45, no: 1, sid: 38659, type: 81 }, { id: 46, no: 1, sid: 38659, type: 82 }, { id: 47, no: 1, sid: 38659, type: 83 }, { id: 48, no: 1, sid: 38659, type: 84 }
]
+555
View File
@@ -0,0 +1,555 @@
import { Profile } from "../models/profile";
import { ProfileWorld, ScoreWorld, EventWorld, GhostWorld } 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<ScoreWorld>(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<ScoreWorld>(refid, {
collection: "score3",
songId,
style,
difficulty
}, {
$set: {
rank,
clearKind,
score,
exScore,
maxCombo,
flareForce
}
});
await DB.Upsert<GhostWorld>(refid, {
collection: "ghost3",
songId,
difficulty
}, {
$set: {
ghostSize,
ghost
}
});
}
export const playerdatanew: EPR = async (info, data, send) => {
const refid = $(data).str("data.refid");
console.log('playerdatanew')
console.log("----------------------")
let ddrCode = _.random(1, 99999999)
await DB.Upsert<ProfileWorld>(refid, { collection: "profile3" }, {
collection: "profile3",
ddrCode: ddrCode
})
return send.object({
result: K.ITEM("s32", 0),
refid: K.ITEM("str", refid),
ddrcode: K.ITEM("s32", ddrCode),
istakeover: K.ITEM('bool', false)
})
}
export const playerdatasave: EPR = async (info, data, send) => {
const refid = $(data).str("data.refid");
if(!refid.startsWith("X000")) {
if($(data).number("data.savekind") === 1) {
await DB.Upsert<ProfileWorld>(refid, { collection: "profile3" }, {
collection: "profile3",
ddrCode: $(data).number('data.common.ddrcode'),
dancerName: $(data).str('data.common.dancername'),
area: $(data).number('data.common.area'),
extraStar: $(data).number('data.common.extrastar'),
playCount: 0,
weight: 0,
todayCal: $(data).number('data.common.today_cal'),
isDispWeight: true,
prePlayableNum: 0,
opHispeed: $(data).number('data.option.hispeed'),
opGauge: $(data).number('data.option.gauge'),
opFastSlow: $(data).number('data.option.fastslow'),
opGuideline: $(data).number('data.option.guideline'),
opStepZone: $(data).number('data.option.stepzone'),
opTimingDisp: $(data).number('data.option.timing_disp'),
opVisibility: $(data).number('data.option.visibility'),
opVisibleTime: $(data).number('data.option.visible_time'),
opLane: $(data).number('data.option.lane'),
opLaneHiddenPos: $(data).number('data.option.lane_hiddenpos'),
opLaneSuddenPos: $(data).number('data.option.lane_suddenpos'),
opLaneHidSudPos: $(data).number('data.option.lane_hidsudpos'),
opLaneFilter: $(data).number('data.option.lane_filter'),
opScrollDirection: $(data).number('data.option.scroll_direction'),
opScrollMoving: $(data).number('data.option.scroll_moving'),
opArrowPriority: $(data).number('data.option.arrow_priority'),
opArrowPlacement: $(data).number('data.option.arrow_placement'),
opArrowColor: $(data).number('data.option.arrow_color'),
opArrowDesign: $(data).number('data.option.arrow_design'),
opCutTiming: $(data).number('data.option.cut_timing'),
opCutFreeze: $(data).number('data.option.cut_freeze'),
opCutJump: $(data).number('data.option.cut_jump'),
lpMode: $(data).number('data.lastplay.mode'),
lpFolder: $(data).number('data.lastplay.folder'),
lpMcode: $(data).number('data.lastplay.mcode'),
lpStyle: $(data).number('data.lastplay.style'),
lpDifficulty: $(data).number('data.lastplay.difficulty'),
lpWindowMain: $(data).number('data.lastplay.window_main'),
lpWindowSub: $(data).number('data.lastplay.window_sub'),
lpTarget: $(data).number('data.lastplay.target'),
lpTabMain: $(data).number('data.lastplay.tab_main'),
lpTabSub: $(data).number('data.lastplay.tab_sub'),
fsTitle: $(data).number('data.filtersort.title'),
fsVersion: $(data).number('data.filtersort.version'),
fsGenre: $(data).number('data.filtersort.genre'),
fsBpm: $(data).number('data.filtersort.bpm'),
fsEvent: $(data).number('data.filtersort.event'),
fsLevel: $(data).number('data.filtersort.level'),
fsFlareRank: $(data).number('data.filtersort.flare_rank'),
fsClearRank: $(data).number('data.filtersort.clear_rank'),
fsFlareSkillTarget: $(data).number('data.filtersort.flare_skill_target'),
fsRivalFlareSkill: $(data).number('data.filtersort.rival_flare_skill'),
fsRivalScoreRank: $(data).number('data.filtersort.rival_score_rank'),
fsSortType: $(data).number('data.filtersort.sort_type'),
fsOrderType: $(data).number('data.filtersort.order_type'),
cgTipsBasic: $(data).number('data.checkguide.tips_basic'),
cgTipsOption: $(data).number('data.checkguide.tips_option'),
cgTipsEvent: $(data).number('data.checkguide.tips_event'),
cgTipsGimmick: $(data).number('data.checkguide.tips_gimmick'),
cgTipsAdvance: $(data).number('data.checkguide.tips_advance'),
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<ProfileWorld>(refid, {collection: "profile3"})
await DB.Upsert<ProfileWorld>(refid, { collection: "profile3" }, {
collection: "profile3",
ddrCode: $(data).number('data.common.ddrcode'),
dancerName: $(data).str('data.common.dancername'),
area: $(data).number('data.common.area'),
extraStar: $(data).number('data.common.extrastar'),
playCount: profile.playCount += 1,
weight: 0,
todayCal: $(data).number('data.common.today_cal'),
isDispWeight: true,
prePlayableNum: 0,
opHispeed: $(data).number('data.option.hispeed'),
opGauge: $(data).number('data.option.gauge'),
opFastSlow: $(data).number('data.option.fastslow'),
opGuideline: $(data).number('data.option.guideline'),
opStepZone: $(data).number('data.option.stepzone'),
opTimingDisp: $(data).number('data.option.timing_disp'),
opVisibility: $(data).number('data.option.visibility'),
opVisibleTime: $(data).number('data.option.visible_time'),
opLane: $(data).number('data.option.lane'),
opLaneHiddenPos: $(data).number('data.option.lane_hiddenpos'),
opLaneSuddenPos: $(data).number('data.option.lane_suddenpos'),
opLaneHidSudPos: $(data).number('data.option.lane_hidsudpos'),
opLaneFilter: $(data).number('data.option.lane_filter'),
opScrollDirection: $(data).number('data.option.scroll_direction'),
opScrollMoving: $(data).number('data.option.scroll_moving'),
opArrowPriority: $(data).number('data.option.arrow_priority'),
opArrowPlacement: $(data).number('data.option.arrow_placement'),
opArrowColor: $(data).number('data.option.arrow_color'),
opArrowDesign: $(data).number('data.option.arrow_design'),
opCutTiming: $(data).number('data.option.cut_timing'),
opCutFreeze: $(data).number('data.option.cut_freeze'),
opCutJump: $(data).number('data.option.cut_jump'),
lpMode: $(data).number('data.lastplay.mode'),
lpFolder: $(data).number('data.lastplay.folder'),
lpMcode: $(data).number('data.lastplay.mcode'),
lpStyle: $(data).number('data.lastplay.style'),
lpDifficulty: $(data).number('data.lastplay.difficulty'),
lpWindowMain: $(data).number('data.lastplay.window_main'),
lpWindowSub: $(data).number('data.lastplay.window_sub'),
lpTarget: $(data).number('data.lastplay.target'),
lpTabMain: $(data).number('data.lastplay.tab_main'),
lpTabSub: $(data).number('data.lastplay.tab_sub'),
fsTitle: $(data).number('data.filtersort.title'),
fsVersion: $(data).number('data.filtersort.version'),
fsGenre: $(data).number('data.filtersort.genre'),
fsBpm: $(data).number('data.filtersort.bpm'),
fsEvent: $(data).number('data.filtersort.event'),
fsLevel: $(data).number('data.filtersort.level'),
fsFlareRank: $(data).number('data.filtersort.flare_rank'),
fsClearRank: $(data).number('data.filtersort.clear_rank'),
fsFlareSkillTarget: $(data).number('data.filtersort.flare_skill_target'),
fsRivalFlareSkill: $(data).number('data.filtersort.rival_flare_skill'),
fsRivalScoreRank: $(data).number('data.filtersort.rival_score_rank'),
fsSortType: $(data).number('data.filtersort.sort_type'),
fsOrderType: $(data).number('data.filtersort.order_type'),
cgTipsBasic: $(data).number('data.checkguide.tips_basic'),
cgTipsOption: $(data).number('data.checkguide.tips_option'),
cgTipsEvent: $(data).number('data.checkguide.tips_event'),
cgTipsGimmick: $(data).number('data.checkguide.tips_gimmick'),
cgTipsAdvance: $(data).number('data.checkguide.tips_advance'),
cgGuideScene: $(data).number('data.checkguide.guide_scene')
})
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')
await DB.Upsert<EventWorld>(refid, { collection: "event3", eventId: eid }, {
collection: "event3",
eventId: eid,
eventNo: eno,
eventType: etype,
compTime: ctime,
saveData: sdata
})
}
}
}
return send.object({
result: K.ITEM("s32", 0)
})
}
return send.object({
result: K.ITEM("s32", 1)
})
};
export const playerdataload: EPR = async (info, data, send) => {
const refid = $(data).str("data.refid");
const profile = await DB.FindOne<ProfileWorld>(refid, { collection: "profile3" });
if (!profile || refid.startsWith("X000")) {
return send.object({
result: K.ITEM("s32", 0),
refid: K.ITEM("str", refid),
gamesession: K.ITEM('s64', BigInt(1)),
servertime: K.ITEM("u64", BigInt(getDate())),
is_locked: K.ITEM('bool', false),
common: {
ddrcode: K.ITEM("s32", 0),
dancername: K.ITEM("str", ''),
is_new: K.ITEM('bool', true),
is_registering: K.ITEM('bool', false),
area: K.ITEM("s32", 0),
extrastar: K.ITEM("s32", 0),
playcount: K.ITEM("s32", 0),
weight: K.ITEM("s32", 0),
today_cal: K.ITEM("u64", BigInt(0)),
is_disp_weight: K.ITEM("bool", false),
is_takeover: K.ITEM('bool', false),
pre_playable_num: K.ITEM("s32", 0)
},
option: {
hispeed: K.ITEM("s32", 0),
gauge: K.ITEM("s32", 0),
fastslow: K.ITEM("s32", 0),
guideline: K.ITEM("s32", 0),
stepzone: K.ITEM("s32", 0),
timing_disp: K.ITEM("s32", 0),
visibility: K.ITEM("s32", 0),
visible_time: K.ITEM("s32", 0),
lane: K.ITEM("s32", 0),
lane_hiddenpos: K.ITEM("s32", 0),
lane_suddenpos: K.ITEM("s32", 0),
lane_hidsudpos: K.ITEM("s32", 0),
lane_filter: K.ITEM("s32", 0),
scroll_direction: K.ITEM("s32", 0),
scroll_moving: K.ITEM("s32", 0),
arrow_priority: K.ITEM("s32", 0),
arrow_placement: K.ITEM("s32", 0),
arrow_color: K.ITEM("s32", 0),
arrow_design: K.ITEM("s32", 0),
cut_timing: K.ITEM("s32", 0),
cut_freeze: K.ITEM("s32", 0),
cut_jump: K.ITEM("s32", 0)
},
lastplay: {
mode: K.ITEM("s32", 0),
folder: K.ITEM("s32", 0),
mcode: K.ITEM("s32", 0),
style: K.ITEM("s32", 0),
difficulty: K.ITEM("s32", 0),
window_main: K.ITEM("s32", 0),
window_sub: K.ITEM("s32", 0),
target: K.ITEM("s32", 0),
tab_main: K.ITEM("s32", 0),
tab_sub: K.ITEM("s32", 0)
},
filtersort: {
title: K.ITEM("u64", BigInt(0)),
version: K.ITEM("u64", BigInt(0)),
genre: K.ITEM("u64", BigInt(0)),
bpm: K.ITEM("u64", BigInt(0)),
event: K.ITEM("u64", BigInt(0)),
level: K.ITEM("u64", BigInt(0)),
flare_rank: K.ITEM("u64", BigInt(0)),
clear_rank: K.ITEM("u64", BigInt(0)),
flare_skill_target: K.ITEM("u64", BigInt(0)),
rival_flare_skill: K.ITEM("u64", BigInt(0)),
rival_score_rank: K.ITEM("u64", BigInt(0)),
sort_type: K.ITEM("u64", BigInt(0)),
order_type: K.ITEM("s32", 0),
},
checkguide: {
tips_basic: K.ITEM("u64", BigInt(0)),
tips_option: K.ITEM("u64", BigInt(0)),
tips_event: K.ITEM("u64", BigInt(0)),
tips_gimmick: K.ITEM("u64", BigInt(0)),
tips_advance: K.ITEM("u64", BigInt(0)),
guide_scene: K.ITEM("u64", BigInt(0)),
},
rival: [
{
slot: K.ITEM("s32", 0),
rivalcode: K.ITEM("s32", 0)
}
],
score: [
{
mcode: K.ITEM("s32", 0),
score_single: {
score_str: K.ITEM("str", "")
},
score_double: {
score_str: K.ITEM("str", "")
}
}
],
event: {
event_str: K.ITEM("str", "")
}
})
}
else {
const scores = await DB.Find<ScoreWorld>(refid, { collection: "score3" });
let scoreFin = []
if(scores) {
for(const scoreData of scores) {
let mcodeIndex = scoreFin.findIndex(x => $(x).number('mcode') === scoreData.songId)
if(mcodeIndex < 0) {
let scr = {}
scr['mcode'] = K.ITEM('s32', scoreData.songId)
scr['score_single'] = []
scr['score_double'] = []
/*
difficulty,idk,grade,clearkind,score,idk either,flaredisp,flarepoints
needs more work, 9 vals
*/
scr[(scoreData.style === 0) ? 'score_single' : 'score_double'] = [
{
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.exScore + ',' + scoreData.flareForce + ',' + scoreData.flareForce)
})
}
}
}
let eventFin = []
for(const event of EVENTS_WORLD) {
let eventData = await DB.FindOne<EventWorld>(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'))
})
}
return send.object({
result: K.ITEM("s32", 0),
refid: K.ITEM("str", refid),
gamesession: K.ITEM('s64', BigInt(1)),
servertime: K.ITEM("u64", BigInt(getDate())),
is_locked: K.ITEM('bool', false),
common: {
ddrcode: K.ITEM("s32", profile.ddrCode),
dancername: K.ITEM("str", profile.dancerName),
is_new: K.ITEM('bool', false),
is_registering: K.ITEM('bool', false),
is_takeover: K.ITEM('bool', false),
area: K.ITEM("s32", profile.area),
extrastar: K.ITEM("s32", profile.extraStar),
playcount: K.ITEM("s32", profile.playCount),
weight: K.ITEM("s32", profile.weight),
today_cal: K.ITEM("u64", BigInt(profile.todayCal)),
is_disp_weight: K.ITEM("bool", profile.isDispWeight),
pre_playable_num: K.ITEM("s32", profile.prePlayableNum)
},
option: {
hispeed: K.ITEM("s32", profile.opHispeed),
gauge: K.ITEM("s32", profile.opGauge),
fastslow: K.ITEM("s32", profile.opFastSlow),
guideline: K.ITEM("s32", profile.opGuideline),
stepzone: K.ITEM("s32", profile.opStepZone),
timing_disp: K.ITEM("s32", profile.opTimingDisp),
visibility: K.ITEM("s32", profile.opVisibility),
visible_time: K.ITEM("s32", profile.opVisibleTime),
lane: K.ITEM("s32", profile.opLane),
lane_hiddenpos: K.ITEM("s32", profile.opLaneHiddenPos),
lane_suddenpos: K.ITEM("s32", profile.opLaneSuddenPos),
lane_hidsudpos: K.ITEM("s32", profile.opLaneHidSudPos),
lane_filter: K.ITEM("s32", profile.opLaneFilter),
scroll_direction: K.ITEM("s32", profile.opScrollDirection),
scroll_moving: K.ITEM("s32", profile.opScrollMoving),
arrow_priority: K.ITEM("s32", profile.opArrowPriority),
arrow_placement: K.ITEM("s32", profile.opArrowPlacement),
arrow_color: K.ITEM("s32", profile.opArrowColor),
arrow_design: K.ITEM("s32", profile.opArrowDesign),
cut_timing: K.ITEM("s32", profile.opCutTiming),
cut_freeze: K.ITEM("s32", profile.opCutFreeze),
cut_jump: K.ITEM("s32", profile.opCutJump)
},
lastplay: {
mode: K.ITEM("s32", profile.lpMode),
folder: K.ITEM("s32", profile.lpFolder),
mcode: K.ITEM("s32", profile.lpMcode),
style: K.ITEM("s32", profile.lpStyle),
difficulty: K.ITEM("s32", profile.lpDifficulty),
window_main: K.ITEM("s32", profile.lpWindowMain),
window_sub: K.ITEM("s32", profile.lpWindowSub),
target: K.ITEM("s32", profile.lpTarget),
tab_main: K.ITEM("s32", profile.lpTabMain),
tab_sub: K.ITEM("s32", profile.lpTabSub)
},
filtersort: {
title: K.ITEM("u64", BigInt(profile.fsTitle)),
version: K.ITEM("u64", BigInt(profile.fsVersion)),
genre: K.ITEM("u64", BigInt(profile.fsGenre)),
bpm: K.ITEM("u64", BigInt(profile.fsBpm)),
event: K.ITEM("u64", BigInt(profile.fsEvent)),
level: K.ITEM("u64", BigInt(profile.fsLevel)),
flare_rank: K.ITEM("u64", BigInt(profile.fsFlareRank)),
clear_rank: K.ITEM("u64", BigInt(profile.fsClearRank)),
flare_skill_target: K.ITEM("u64", BigInt(profile.fsFlareSkillTarget)),
rival_flare_skill: K.ITEM("u64", BigInt(profile.fsRivalFlareSkill)),
rival_score_rank: K.ITEM("u64", BigInt(profile.fsRivalScoreRank)),
sort_type: K.ITEM("u64", BigInt(profile.fsSortType)),
order_type: K.ITEM("s32", profile.fsOrderType),
},
checkguide: {
tips_basic: K.ITEM("u64", BigInt(profile.cgTipsBasic)),
tips_option: K.ITEM("u64", BigInt(profile.cgTipsOption)),
tips_event: K.ITEM("u64", BigInt(profile.cgTipsEvent)),
tips_gimmick: K.ITEM("u64", BigInt(profile.cgTipsGimmick)),
tips_advance: K.ITEM("u64", BigInt(profile.cgTipsAdvance)),
guide_scene: K.ITEM("u64", BigInt(profile.cgGuideScene)),
},
rival: [],
score: scoreFin,
event: eventFin
});
}
};
export const musicdataload: EPR = async (info, data, send) => {
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())),
music: musicList
});
};
export const rivaldataload: EPR = async (info, data, send) => {
return send.object({
result: K.ITEM("s32", 0),
record: []
});
};
export const ghostdataload: EPR = async (info, data, send) => {
// i quite frankly dk what this is for lol i don't play ddr
const refid = $(data).str("data.refid");
const ghostId = $(data).number("data.ghostid");
let ghostData = await DB.FindOne<GhostWorld>(refid, {collection: 'ghost3', songId: ghostId})
if(ghostData) {
return send.object({
result: K.ITEM("s32", 0),
ghostsize: K.ITEM("s32", ghostData.ghostSize),
ghost: K.ITEM("str", ghostData.ghost)
});
}
return send.object({ result: K.ITEM("s32", 0) });
};
export const taboowordcheck: EPR = async (info, data, send) => {
// Automatically accept word
return send.object({
result: K.ITEM("s32", 0),
is_taboo: K.ITEM("bool", false)
});
};
export const minidump: EPR = async (info, data, send) => {
console.log($(data).str('minidump'))
return send.object({ result: K.ITEM('s32', 0) })
};
function getDate(): number {
let time = new Date();
let tempDate = time.getDate();
const currentTime = parseInt((time.getTime()/100000) as unknown as string)*100;
return currentTime
}
+41 -5
View File
@@ -2,11 +2,14 @@ import { convcardnumber, eventLog } from "./handlers/common";
import { usergamedata } from "./handlers/usergamedata";
import { usergamedata_recv } from "./handlers/usergamedata_recv";
import { usergamedata_send } from "./handlers/usergamedata_send";
import { musicdataload, playerdatanew, playerdatasave, playerdataload, rivaldataload, ghostdataload, taboowordcheck, minidump } from "./handlers/ddrworld";
import { CommonOffset, OptionOffset, Profile } from "./models/profile";
export function register() {
R.GameCode("MDX");
R.Unhandled(undefined);
R.Config("save_option", {
name: "Save option",
desc: "Gets the previously set options as they are.",
@@ -14,12 +17,45 @@ export function register() {
type: "boolean"
});
R.Route("playerdata.usergamedata_advanced", usergamedata);
R.Route("playerdata.usergamedata_recv", usergamedata_recv);
R.Route("playerdata.usergamedata_send", usergamedata_send);
const RoutePlayerData = (method: string, handler: EPR | boolean) => {
R.Route(`playerdata.${method}`, handler);
R.Route(`playerdata_2.${method}`, handler);
};
R.Route("system.convcardnumber", convcardnumber);
R.Route("eventlog.write", eventLog);
const RoutePlayData = (method: string, handler: EPR | boolean) => {
R.Route(`playdata_3.${method}`, handler);
};
const WordCheck = (method: string, handler: EPR | boolean) => {
R.Route(`wordcheck_3.${method}`, handler);
}
const RouteSystem = (method: string, handler: EPR | boolean) => {
R.Route(`system.${method}`, handler);
R.Route(`system_2.${method}`, handler);
R.Route(`system_3.${method}`, handler);
};
const RouteEventLog = (method: string, handler: EPR | boolean) => {
R.Route(`eventlog.${method}`, handler);
R.Route(`eventlog_2.${method}`, handler);
R.Route(`eventlog_3.${method}`, handler);
};
RoutePlayerData('usergamedata_advanced', usergamedata);
RoutePlayerData('usergamedata_recv', usergamedata_recv);
RoutePlayerData('usergamedata_send', usergamedata_send);
RoutePlayData('musicdata_load', musicdataload);
RoutePlayData('playerdata_new', playerdatanew);
RoutePlayData('playerdata_load', playerdataload);
RoutePlayData('playerdata_save', playerdatasave);
RoutePlayData('rivaldata_load', rivaldataload);
RoutePlayData('ghostdata_load', ghostdataload);
RouteSystem("convcardnumber", convcardnumber);
RouteSystem("minidump", minidump);
RouteEventLog("write", eventLog);
WordCheck('tabooword_check', taboowordcheck)
R.WebUIEvent("updateName", async ({ refid, name }) => {
let strdata: Profile | string[] = await DB.FindOne<Profile>(refid, { collection: "profile" });
+136
View File
@@ -0,0 +1,136 @@
import { Difficulty, Rank, ClearKind } from '../models/score'
export interface RivalWorld {
collection: "rival3";
slot: number;
rivalCode: number;
}
export interface ScoreWorld {
collection: "score3";
songId: number;
style: number;
difficulty: Difficulty;
rank: Rank;
clearKind: ClearKind;
score: number;
exScore: number;
maxCombo: number;
flareForce: number;
}
export interface GhostWorld {
collection: "ghost3"
songId: number;
difficulty: number;
ghostSize: number;
ghost: string;
}
export interface EventWorld {
collection: "event3";
eventId: number;
eventNo: number;
eventType: number;
compTime: number;
saveData: number;
}
export interface ProfileWorld {
collection: "profile3";
ddrCode: number;
dancerName: string;
area: number;
extraStar: number;
playCount: number;
weight: number;
todayCal: number;
isDispWeight: boolean;
prePlayableNum: number;
opHispeed: number;
opGauge: number;
opFastSlow: number;
opGuideline: number;
opStepZone: number;
opTimingDisp: number;
opVisibility: number;
opVisibleTime: number;
opLane: number;
opLaneHiddenPos: number;
opLaneSuddenPos: number;
opLaneHidSudPos: number;
opLaneFilter: number;
opScrollDirection: number;
opScrollMoving: number;
opArrowPriority: number;
opArrowPlacement: number;
opArrowColor: number;
opArrowDesign: number;
opCutTiming: number;
opCutFreeze: number;
opCutJump: number;
lpMode: number;
lpFolder: number;
lpMcode: number;
lpStyle: number;
lpDifficulty: number;
lpWindowMain: number;
lpWindowSub: number;
lpTarget: number;
lpTabMain: number;
lpTabSub: number;
fsTitle: number;
fsVersion: number;
fsGenre: number;
fsBpm: number;
fsEvent: number;
fsLevel: number;
fsFlareRank: number;
fsClearRank: number;
fsFlareSkillTarget: number;
fsRivalFlareSkill: number;
fsRivalScoreRank: number;
fsSortType: number;
fsOrderType: number;
cgTipsBasic: number;
cgTipsOption: number;
cgTipsEvent: number;
cgTipsGimmick: number;
cgTipsAdvance: number;
cgGuideScene: number;
singleGrade?: number;
doubleGrade?: number;
events?: {};
usergamedata?: {
COMMON?: {
strdata?: string;
bindata?: string;
};
OPTION?: {
strdata?: string;
bindata?: string;
};
LAST?: {
strdata?: string;
bindata?: string;
};
RIVAL?: {
strdata?: string;
bindata?: string;
};
};
}
+1 -1
View File
@@ -33,7 +33,7 @@ export enum ClearKind {
NONE = 6,
GOOD_COMBO,
GREAT_COMBO,
PERPECT_COMBO,
PERFECT_COMBO,
MARVELOUS_COMBO
}
+134 -1
View File
@@ -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")