diff --git a/asphyxia-core.d.ts b/asphyxia-core.d.ts
index 7d1bda3..9d1f599 100644
--- a/asphyxia-core.d.ts
+++ b/asphyxia-core.d.ts
@@ -1,4 +1,5 @@
///
+///
declare type KNumberType =
| 's8'
@@ -657,6 +658,54 @@ declare namespace $ {
function STR(data: any, path: string, def?: string): string;
}
+/** @ignore */
+declare interface KITEM<
+ S extends
+ | KNumberType
+ | KBigIntType
+ | KNumberGroupType
+ | KBigIntGroupType
+ | 'str'
+ | 'bool'
+ | 'bin'
+ | 'ip4'
+> {
+ '@attr': {
+ __type: S;
+ };
+ '@content': S extends 'str'
+ ? string
+ : S extends 'bin'
+ ? Buffer
+ : S extends KNumberType | 'ip4' | 'bool'
+ ? [number]
+ : S extends KBigIntType
+ ? [bigint]
+ : S extends KNumberGroupType
+ ? number[]
+ : S extends KBigIntGroupType
+ ? bigint[]
+ : unknown;
+}
+
+/** @ignore */
+declare interface KARRAY {
+ '@attr': {
+ __count: number;
+ __type: S;
+ };
+ '@content': S extends KNumberType
+ ? number[]
+ : S extends KBigIntType
+ ? bigint[]
+ : unknown;
+}
+
+/** @ignore */
+declare interface KATTR {
+ '@attr': M;
+}
+
/**
* K stands for `Konstruct`
*
@@ -682,7 +731,7 @@ declare namespace K {
* @param attr Attribute map
* @param inner Inner tag/data
*/
- function ATTR(attr: KAttrMap, inner?: any): any;
+ function ATTR(attr: M, inner?: T): KATTR & T;
/**
* Example:
@@ -699,22 +748,30 @@ declare namespace K {
* @param content data of specified type
* @param attr attribute map in addition to **__type**
*/
- function ITEM(type: 'str', content: string, attr?: KAttrMap): any;
- function ITEM(type: 'bin', content: Buffer, attr?: KAttrMap): any;
- function ITEM(type: 'ip4', content: string, attr?: KAttrMap): any;
- function ITEM(type: 'bool', content: boolean, attr?: KAttrMap): any;
- function ITEM(type: KNumberType, content: number, attr?: KAttrMap): any;
- function ITEM(type: KBigIntType, content: bigint, attr?: KAttrMap): any;
- function ITEM(
- type: KNumberGroupType,
+ function ITEM(type: 'str', content: string, attr?: KAttrMap): KITEM<'str'>;
+ function ITEM(type: 'bin', content: Buffer, attr?: KAttrMap): KITEM<'bin'>;
+ function ITEM(type: 'ip4', content: string, attr?: KAttrMap): KITEM<'ip4'>;
+ function ITEM(type: 'bool', content: boolean, attr?: KAttrMap): KITEM<'bool'>;
+ function ITEM(
+ type: S,
+ content: number,
+ attr?: KAttrMap
+ ): KITEM;
+ function ITEM(
+ type: S,
+ content: bigint,
+ attr?: KAttrMap
+ ): KITEM;
+ function ITEM(
+ type: S,
content: number[],
attr?: KAttrMap
- ): any;
- function ITEM(
- type: KBigIntGroupType,
+ ): KITEM;
+ function ITEM(
+ type: S,
content: bigint[],
attr?: KAttrMap
- ): any;
+ ): KITEM;
/**
* Example:
@@ -731,9 +788,21 @@ declare namespace K {
* @param content array of data, ____count__ attribute will be automatically set to `content.length`
* @param attr attribute map in addition to **__type** and **__count**
*/
- function ARRAY(type: 'u8' | 's8', content: Buffer, attr?: KAttrMap): any;
- function ARRAY(type: KNumberType, content: number[], attr?: KAttrMap): any;
- function ARRAY(type: KBigIntType, content: bigint[], attr?: KAttrMap): any;
+ function ARRAY(
+ type: S,
+ content: Buffer,
+ attr?: KAttrMap
+ ): KARRAY;
+ function ARRAY(
+ type: S,
+ content: number[],
+ attr?: KAttrMap
+ ): KARRAY;
+ function ARRAY(
+ type: S,
+ content: bigint[],
+ attr?: KAttrMap
+ ): KARRAY;
}
/**
@@ -867,6 +936,8 @@ declare namespace U {
/** @ignore */
type Doc = { _id?: string } & T;
/** @ignore */
+type ProfileDoc = { _id?: string; __refid?: string } & T;
+/** @ignore */
type Query = {
[P in keyof T]?:
| T[P]
@@ -978,15 +1049,24 @@ type Update = Partial & {
*
* If you need to make rival/friend feature, we recommend you to get all profile data by passing null to `refid`.
* There will be 16 profiles maximum which is small enough to manage.
+ *
+ * All query and doc should not have any fields start with "__" with "__refid" being the only exception.
+ * However, "__refid" field will still be ignored while other "__" starting fields will cause an error to be thrown.
*/
declare namespace DB {
- function FindOne(refid: string | null, query: Query): Promise>;
+ function FindOne(
+ refid: string | null,
+ query: Query
+ ): Promise>;
function FindOne(query: Query): Promise>;
- function Find(refid: string | null, query: Query): Promise[]>;
+ function Find(
+ refid: string | null,
+ query: Query
+ ): Promise[]>;
function Find(query: Query): Promise[]>;
- function Insert(refid: string, doc: T): Promise>;
+ function Insert(refid: string, doc: T): Promise>;
function Insert(doc: T): Promise>;
function Remove(refid: string | null, query: Query): Promise;
@@ -998,7 +1078,7 @@ declare namespace DB {
update: Update
): Promise<{
updated: number;
- docs: Doc[];
+ docs: ProfileDoc[];
}>;
function Update(
query: Query,
@@ -1014,7 +1094,7 @@ declare namespace DB {
update: Update
): Promise<{
updated: number;
- docs: Doc[];
+ docs: ProfileDoc[];
upsert: boolean;
}>;
function Upsert(
@@ -1031,7 +1111,5 @@ declare namespace DB {
}
/** @ignore */
-declare namespace _ {}
-/** @ignore */
+// @ts-ignore
declare const _: any;
-///
diff --git a/sdvx@asphyxia/data/vvw.ts b/sdvx@asphyxia/data/vvw.ts
index e6b6fc7..45a6401 100644
--- a/sdvx@asphyxia/data/vvw.ts
+++ b/sdvx@asphyxia/data/vvw.ts
@@ -24,6 +24,7 @@ export const EVENT5 = [
'STANDARD_UNLOCK_ENABLE',
'PLAYERJUDGEADJ_ENABLE',
'MIXID_INPUT_ENABLE',
+ 'SERIALCODE_JAPAN',
'EVENTDATE_ONIGO',
'EVENTDATE_GOTT',
'GENERATOR_ABLE',
@@ -2588,7 +2589,18 @@ export const SDVX_AUTOMATION_SONGS = [
export const EXTENDS5 = [
{
id: 91,
- type: 14,
- params: [0, 1, 0, 0, 1, SDVX_AUTOMATION_SONGS.join(','), '', '', '', ''],
+ type: 17,
+ params: [
+ 0,
+ 1,
+ 0,
+ 0,
+ 1,
+ SDVX_AUTOMATION_SONGS.join(','),
+ '0',
+ '0',
+ '0',
+ '0',
+ ],
},
];
diff --git a/sdvx@asphyxia/handlers/common.ts b/sdvx@asphyxia/handlers/common.ts
index b371a5c..55cc402 100644
--- a/sdvx@asphyxia/handlers/common.ts
+++ b/sdvx@asphyxia/handlers/common.ts
@@ -1,5 +1,6 @@
import { EVENT4, COURSES4, EXTENDS4 } from '../data/hvn';
import { EVENT5, COURSES5, EXTENDS5 } from '../data/vvw';
+
export const common: EPR = async (info, data, send) => {
let events = [];
let courses = [];
diff --git a/sdvx@asphyxia/handlers/features.ts b/sdvx@asphyxia/handlers/features.ts
index e69de29..901a9ea 100644
--- a/sdvx@asphyxia/handlers/features.ts
+++ b/sdvx@asphyxia/handlers/features.ts
@@ -0,0 +1,126 @@
+import { Profile } from '../models/profile';
+import { MusicRecord } from '../models/music_record';
+import { IDToCode, GetCounter } from '../utils';
+import { Mix } from '../models/mix';
+
+export const hiscore: EPR = async (info, data, send) => {
+ const records = await DB.Find(null, { collection: 'music' });
+
+ const profiles = _.groupBy(
+ await DB.Find(null, { collection: 'profile' }),
+ '__refid'
+ );
+
+ send.object({
+ sc: {
+ d: _.map(
+ _.groupBy(records, r => {
+ return `${r.mid}:${r.type}`;
+ }),
+ r => _.maxBy(r, 'score')
+ ).map(r => ({
+ id: K.ITEM('u32', r.mid),
+ ty: K.ITEM('u32', r.type),
+ a_sq: K.ITEM('str', IDToCode(profiles[r.__refid][0].id)),
+ a_nm: K.ITEM('str', profiles[r.__refid][0].name),
+ a_sc: K.ITEM('u32', r.score),
+ l_sq: K.ITEM('str', IDToCode(profiles[r.__refid][0].id)),
+ l_nm: K.ITEM('str', profiles[r.__refid][0].name),
+ l_sc: K.ITEM('u32', r.score),
+ })),
+ },
+ });
+};
+
+export const rival: EPR = async (info, data, send) => {
+ const refid = $(data).str('refid');
+ if (!refid) return send.deny();
+
+ const rivals = (
+ await DB.Find(null, { collection: 'profile' })
+ ).filter(p => p.__refid != refid);
+
+ send.object({
+ rival: await Promise.all(
+ rivals.map(async (p, index) => {
+ return {
+ no: K.ITEM('s16', index),
+ seq: K.ITEM('str', IDToCode(p.id)),
+ name: K.ITEM('str', p.name),
+ music: (
+ await DB.Find(p.__refid, { collection: 'music' })
+ ).map(r => ({
+ param: K.ARRAY('u32', [r.mid, r.type, r.score, r.clear, r.grade]),
+ })),
+ };
+ })
+ ),
+ });
+};
+
+export const saveMix: EPR = async (info, data, send) => {
+ const refid = $(data).str('ref_id');
+ if (!refid) return send.deny();
+
+ const profile = await DB.FindOne(refid, { collection: 'profile' });
+ if (!profile) return send.deny();
+
+ const mix = $(data).element('automation');
+
+ const id = await GetCounter('mix');
+ let code = _.padStart(_.random(0, 999999999999).toString(), 12, '0');
+ while (await DB.FindOne(null, { code })) {
+ code = _.padStart(_.random(0, 999999999999).toString(), 12, '0');
+ }
+
+ const doc = await DB.Insert(refid, {
+ collection: 'mix',
+ id,
+ code,
+ name: mix.str('mix_name'),
+ creator: profile.name,
+ param: mix.str('generate_param'),
+ tag: mix.number('tag_bit'),
+ jacket: mix.number('jacket_id'),
+ });
+
+ send.object({
+ automation: {
+ mix_id: K.ITEM('s32', id),
+ mix_code: K.ITEM('str', doc.code),
+ seq: K.ITEM('str', doc.code),
+ mix_name: K.ITEM('str', doc.name),
+ player_name: K.ITEM('str', doc.creator),
+ generate_param: K.ITEM('str', doc.param),
+ distribution_date: K.ITEM('u32', 19990101),
+ jacket_id: K.ITEM('s32', doc.jacket),
+ tag_bit: K.ITEM('s32', doc.tag),
+ like_flg: K.ITEM('bool', 0),
+ },
+ });
+};
+
+export const loadMix: EPR = async (info, data, send) => {
+ const code = $(data).str('mix_code');
+
+ const mix = await DB.FindOne(null, { collection: 'mix', code });
+ if (!mix) {
+ send.object({ result: K.ITEM('s32', 1) });
+ return;
+ }
+
+ send.object({
+ automation: {
+ mix_id: K.ITEM('s32', mix.id),
+ mix_code: K.ITEM('str', mix.code),
+ seq: K.ITEM('str', mix.code),
+ mix_name: K.ITEM('str', mix.name),
+ player_name: K.ITEM('str', mix.creator),
+ generate_param: K.ITEM('str', mix.param),
+ distribution_date: K.ITEM('u32', 19990101),
+ jacket_id: K.ITEM('s32', mix.jacket),
+ tag_bit: K.ITEM('s32', mix.tag),
+ like_flg: K.ITEM('bool', 0),
+ },
+ });
+};
diff --git a/sdvx@asphyxia/handlers/profile.ts b/sdvx@asphyxia/handlers/profiles.ts
similarity index 51%
rename from sdvx@asphyxia/handlers/profile.ts
rename to sdvx@asphyxia/handlers/profiles.ts
index f2f5f74..bbcff62 100644
--- a/sdvx@asphyxia/handlers/profile.ts
+++ b/sdvx@asphyxia/handlers/profiles.ts
@@ -1,19 +1,35 @@
-import { Profile } from '../models/profile';
-import { VersionData } from '../models/version_data';
+import { Skill } from '../models/skill';
import { SDVX_AUTOMATION_SONGS } from '../data/vvw';
-import { CourseRecord } from '../models/course_record';
import { Item } from '../models/item';
import { Param } from '../models/param';
import { MusicRecord } from '../models/music_record';
+import { CourseRecord } from '../models/course_record';
+import { Profile } from '../models/profile';
+import { IDToCode } from '../utils';
+import { Mix } from '../models/mix';
function getVersion(info: EamuseInfo) {
- if (info.module == 'game_3') return 0;
if (info.method.startsWith('sv4')) return 4;
if (info.method.startsWith('sv5')) return 5;
return 0;
}
-export const loadScores: EPR = async (info, data, send) => {
+async function getAutomationMixes(params: Param[]) {
+ const mixids = params
+ .filter(p => p.id == 3)
+ .reduce((res, p) => _.union(res, p.param), []);
+ return await DB.Find(null, { collection: 'mix', id: { $in: mixids } });
+}
+
+function unlockNavigators(items: Partial- []) {
+ for (let i = 0; i < 300; ++i) items.push({ type: 11, id: i, param: 15 });
+
+ // 10 genesis card for MITSURU's voice
+ items.push({ type: 4, id: 599, param: 10 });
+ return items;
+}
+
+export const loadScore: EPR = async (info, data, send) => {
const refid = $(data).str('refid');
if (!refid) return send.deny();
@@ -45,23 +61,23 @@ export const loadScores: EPR = async (info, data, send) => {
});
};
-export const saveScores: EPR = async (info, data, send) => {
+export const saveScore: EPR = async (info, data, send) => {
const refid = $(data).str('refid');
if (!refid) return send.deny();
- const musicID = $(data).number('music_id');
- const musicType = $(data).number('music_type');
+ const mid = $(data).number('music_id');
+ const type = $(data).number('music_type');
- if (musicID == null || musicType == null) return send.deny();
+ if (_.isNil(mid) || _.isNil(type)) return send.deny();
const record = (await DB.FindOne(refid, {
collection: 'music',
- mid: musicID,
- type: musicType,
+ mid,
+ type,
})) || {
collection: 'music',
- mid: musicID,
- type: musicType,
+ mid,
+ type,
score: 0,
clear: 0,
grade: 0,
@@ -83,17 +99,44 @@ export const saveScores: EPR = async (info, data, send) => {
await DB.Upsert(
refid,
- {
- collection: 'music',
- mid: musicID,
- type: musicType,
- },
+ { collection: 'music', mid, type },
record
);
send.success();
};
+export const saveCourse: EPR = async (info, data, send) => {
+ const refid = $(data).str('refid');
+ if (!refid) return send.deny();
+
+ const version = getVersion(info);
+ if (version == 0) return send.deny();
+
+ const sid = $(data).number('ssnid');
+ const cid = $(data).number('crsid');
+
+ if (_.isNil(sid) || _.isNil(cid)) return send.deny();
+
+ await DB.Upsert(
+ refid,
+ { collection: 'course', sid, cid, version },
+ {
+ $max: {
+ score: $(data).number('sc', 0),
+ clear: $(data).number('ct', 0),
+ grade: $(data).number('gr', 0),
+ rate: $(data).number('ar', 0),
+ },
+ $inc: {
+ count: 1,
+ },
+ }
+ );
+
+ send.success();
+};
+
export const save: EPR = async (info, data, send) => {
const refid = $(data).str('refid');
if (!refid) return send.deny();
@@ -101,6 +144,7 @@ export const save: EPR = async (info, data, send) => {
const version = getVersion(info);
if (version == 0) return send.deny();
+ // Save Profile
await DB.Update(
refid,
{ collection: 'profile' },
@@ -133,16 +177,51 @@ export const save: EPR = async (info, data, send) => {
}
);
- await DB.Upsert(
+ // Save Items
+ const items = $(data).elements('item.info');
+
+ for (const i of items) {
+ const type = i.number('type');
+ const id = i.number('id');
+ const param = i.number('param');
+
+ if (_.isNil(type) || _.isNil(id) || _.isNil(param)) continue;
+
+ await DB.Upsert
- (
+ refid,
+ { collection: 'item', type, id },
+ { $set: { param } }
+ );
+ }
+
+ // Save Param
+ const params = $(data).elements('param.info');
+ for (const p of params) {
+ const type = p.number('type');
+ const id = p.number('id');
+ const param = p.numbers('param');
+
+ if (_.isNil(type) || _.isNil(id) || _.isNil(param)) continue;
+
+ await DB.Upsert(
+ refid,
+ { collection: 'param', type, id },
+ { $set: { param } }
+ );
+ }
+
+ // Save version specific data
+ await DB.Upsert(
+ refid,
{
- collection: 'version',
+ collection: 'skill',
version,
},
{
$set: {
- skillBase: $(data).number('skill_base_id'),
- skillLevel: $(data).number('skill_level'),
- skillName: $(data).number('skill_name_id'),
+ base: $(data).number('skill_base_id'),
+ level: $(data).number('skill_level'),
+ name: $(data).number('skill_name_id'),
},
}
);
@@ -166,22 +245,28 @@ export const load: EPR = async (info, data, send) => {
return;
}
- let versionData = await DB.FindOne(refid, {
- collection: 'version',
+ let skill = (await DB.FindOne(refid, {
+ collection: 'skill',
version,
- });
+ })) || { base: 0, name: 0, level: 0 };
const courses = await DB.Find(refid, { collection: 'course' });
const items = await DB.Find
- (refid, { collection: 'item' });
const params = await DB.Find(refid, { collection: 'param' });
+ const mixes = version == 5 ? await getAutomationMixes(params) : [];
+
send.pugFile('templates/load.pug', {
courses,
- items,
+ items: U.GetConfig('unlock_all_navigators')
+ ? unlockNavigators(items)
+ : items,
params,
- mixes: version == 5 ? SDVX_AUTOMATION_SONGS : [],
+ skill,
+ mixes,
+ automation: version == 5 ? SDVX_AUTOMATION_SONGS : [],
+ code: IDToCode(profile.id),
...profile,
- ...versionData,
});
};
@@ -190,11 +275,16 @@ export const create: EPR = async (info, data, send) => {
if (!refid) return send.deny();
const name = $(data).str('name', 'GUEST');
+ let id = _.random(0, 99999999);
+ while (await DB.FindOne(null, { collecttion: 'profile', id })) {
+ id = _.random(0, 99999999);
+ }
const profile: Profile = {
pluginVer: 1,
collection: 'profile',
+ id,
name,
appeal: 0,
akaname: 0,
@@ -221,3 +311,48 @@ export const create: EPR = async (info, data, send) => {
await DB.Upsert(refid, { collection: 'profile' }, profile);
send.object({ result: K.ITEM('u8', 0) });
};
+
+export const buy: EPR = async (info, data, send) => {
+ const refid = $(data).str('refid');
+ if (!refid) return send.deny();
+
+ const growth = {
+ blocks: $(data).number('earned_gamecoin_block', 0),
+ packets: $(data).number('earned_gamecoin_packet', 0),
+ };
+
+ const currency = $(data).bool('currency_type') ? 'blocks' : 'packets';
+
+ const cost = _.sum($(data).numbers('item.price', []));
+ const balanceChange = growth[currency] - cost;
+
+ const updated = await DB.Update(
+ refid,
+ { collection: 'profile', [currency]: { $gte: -balanceChange } },
+ { $inc: { [currency]: balanceChange } }
+ );
+
+ if (updated.updated) {
+ const items = _.zipWith(
+ $(data).numbers('item.item_type', []),
+ $(data).numbers('item.item_id', []),
+ $(data).numbers('item.param', []),
+ (type, id, param) => ({ type, id, param })
+ );
+
+ for (const item of items) {
+ await DB.Upsert
- (
+ refid,
+ { collection: 'item', type: item.type, id: item.id },
+ { $set: { param: item.param } }
+ );
+ }
+
+ send.object({
+ gamecoin_packet: K.ITEM('u32', updated.docs[0].packets),
+ gamecoin_block: K.ITEM('u32', updated.docs[0].blocks),
+ });
+ } else {
+ send.success();
+ }
+};
diff --git a/sdvx@asphyxia/index.ts b/sdvx@asphyxia/index.ts
index 5373b5b..ec1a84d 100644
--- a/sdvx@asphyxia/index.ts
+++ b/sdvx@asphyxia/index.ts
@@ -1,5 +1,14 @@
import { common } from './handlers/common';
-import { load, create, loadScores, save, saveScores } from './handlers/profile';
+import { hiscore, rival, saveMix, loadMix } from './handlers/features';
+import {
+ load,
+ create,
+ loadScore,
+ save,
+ saveScore,
+ saveCourse,
+ buy,
+} from './handlers/profiles';
export function register() {
R.GameCode('KFC');
@@ -19,14 +28,29 @@ export function register() {
// Profile
MultiRoute('new', create);
MultiRoute('load', load);
- MultiRoute('load_m', loadScores);
- MultiRoute('load_r', true);
+ MultiRoute('load_m', loadScore);
MultiRoute('save', save);
- MultiRoute('save_m', saveScores);
+ MultiRoute('save_m', saveScore);
+ MultiRoute('save_c', saveCourse);
MultiRoute('frozen', true);
+ MultiRoute('buy', buy);
- // Useless
+ // Features
+ MultiRoute('hiscore', hiscore);
+ MultiRoute('load_r', rival);
+ MultiRoute('save_ap', saveMix);
+ MultiRoute('load_ap', loadMix);
+
+ // Lazy
MultiRoute('lounge', false);
+ MultiRoute('shop', true);
+ MultiRoute('save_e', true);
+ MultiRoute('play_e', true);
+ MultiRoute('play_s', true);
+ MultiRoute('entry_s', true);
+ MultiRoute('entry_e', true);
+ MultiRoute('exception', true);
+ R.Route('eventlog.write', true);
R.Unhandled();
}
diff --git a/sdvx@asphyxia/models/counter.ts b/sdvx@asphyxia/models/counter.ts
new file mode 100644
index 0000000..e8e57d3
--- /dev/null
+++ b/sdvx@asphyxia/models/counter.ts
@@ -0,0 +1,6 @@
+export interface Counter {
+ collection: 'counter';
+
+ key: string;
+ value: number;
+}
diff --git a/sdvx@asphyxia/models/course_record.ts b/sdvx@asphyxia/models/course_record.ts
index d896b91..ab5b688 100644
--- a/sdvx@asphyxia/models/course_record.ts
+++ b/sdvx@asphyxia/models/course_record.ts
@@ -1,11 +1,13 @@
export interface CourseRecord {
collection: 'course';
+ version: number;
+
sid: number;
cid: number;
score: number;
- clearType: number;
+ clear: number;
grade: number;
- achieveRate: number;
- playCount: number;
+ rate: number;
+ count: number;
}
diff --git a/sdvx@asphyxia/models/item.ts b/sdvx@asphyxia/models/item.ts
index 9574bbf..307ddea 100644
--- a/sdvx@asphyxia/models/item.ts
+++ b/sdvx@asphyxia/models/item.ts
@@ -1,5 +1,6 @@
export interface Item {
collection: 'item';
+
type: number;
id: number;
param: number;
diff --git a/sdvx@asphyxia/models/mix.ts b/sdvx@asphyxia/models/mix.ts
index e69de29..06a01d4 100644
--- a/sdvx@asphyxia/models/mix.ts
+++ b/sdvx@asphyxia/models/mix.ts
@@ -0,0 +1,11 @@
+export interface Mix {
+ collection: 'mix';
+
+ id: number;
+ code: string;
+ name: string;
+ creator: string;
+ param: string;
+ jacket: number;
+ tag: number;
+}
diff --git a/sdvx@asphyxia/models/profile.ts b/sdvx@asphyxia/models/profile.ts
index ac579bc..045fb67 100644
--- a/sdvx@asphyxia/models/profile.ts
+++ b/sdvx@asphyxia/models/profile.ts
@@ -3,6 +3,7 @@ export interface Profile {
pluginVer: number;
+ id: number;
name: string;
appeal: number;
akaname: number;
diff --git a/sdvx@asphyxia/models/skill.ts b/sdvx@asphyxia/models/skill.ts
new file mode 100644
index 0000000..cd0bb8f
--- /dev/null
+++ b/sdvx@asphyxia/models/skill.ts
@@ -0,0 +1,9 @@
+export interface Skill {
+ collection: 'skill';
+
+ version: number;
+
+ level: number;
+ base: number;
+ name: number;
+}
diff --git a/sdvx@asphyxia/models/version_data.ts b/sdvx@asphyxia/models/version_data.ts
deleted file mode 100644
index 94d88f6..0000000
--- a/sdvx@asphyxia/models/version_data.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// Version specific data (e.g. skills level)
-export interface VersionData {
- collection: 'version';
-
- version: number;
-
- skillLevel: number;
- skillBase: number;
- skillName: number;
-}
diff --git a/sdvx@asphyxia/templates/load.pug b/sdvx@asphyxia/templates/load.pug
index 70fc1e6..5de07c3 100644
--- a/sdvx@asphyxia/templates/load.pug
+++ b/sdvx@asphyxia/templates/load.pug
@@ -1,8 +1,8 @@
game
result(__type="u8") 0
name(__type="str") #{name}
- code(__type="str") 1337-6666
- sdvx_id(__type="str") 1337-6666
+ code(__type="str") #{code}
+ sdvx_id(__type="str") #{code}
gamecoin_packet(__type="u32") #{packets}
gamecoin_block(__type="u32") #{blocks}
appeal_id(__type="u16") #{appeal}
@@ -26,10 +26,11 @@ game
narrow_down(__type="u8") #{narrowDown}
kac_id(__type="str") #{name}
- skill_level(__type="s16") #{skillLevel || 0}
- skill_base_id(__type="s16") #{skillBase || 0}
- skill_name_id(__type="s16") #{skillName || 0}
+ skill_level(__type="s16") #{skill.level}
+ skill_base_id(__type="s16") #{skill.base}
+ skill_name_id(__type="s16") #{skill.name}
+
ea_shop
packet_booster(__type="s32") 1
if version != 5
@@ -47,10 +48,10 @@ game
ssnid(__type="s16") #{course.sid}
crsid(__type="s16") #{course.cid}
sc(__type="s32") #{course.score}
- ct(__type="s16") #{course.clearType}
+ ct(__type="s16") #{course.clear}
gr(__type="s16") #{course.grade}
- ar(__type="s16") #{course.achieveRate}
- cnt(__type="s16") #{course.playCount}
+ ar(__type="s16") #{course.rate}
+ cnt(__type="s16") #{course.count}
item
each item in items
@@ -60,7 +61,7 @@ game
param(__type="u32") #{item.param}
//- Unlock automation songs
- each song in mixes
+ each song in automation
info
type(__type="u8") 15
id(__type="u32") #{song}
@@ -69,9 +70,9 @@ game
param
each param in params
info
- type(__type="u8") #{param.type}
- id(__type="u32") #{param.id}
- param(__type="u32" __count=param.param.length) #{param.param.join(" ")}
+ type(__type="s32") #{param.type}
+ id(__type="s32") #{param.id}
+ param(__type="s32" __count=param.param.length) #{param.param.join(" ")}
//- Akaname
each id in [0, 1, 2]
@@ -99,7 +100,7 @@ game
mix_name(__type="str") #{mix.name}
player_name(__type="str") #{mix.creator}
generate_param(__type="str") #{mix.param}
- distribution_date(__type="u32") 19990101
- jacket_id(__type="s32") #{mix.jacketID}
+ distribution_date(__type="u32") 20200101
+ jacket_id(__type="s32") #{mix.jacket}
tag_bit(__type="s32") #{mix.tag}
like_flg(__type="u8") 0
\ No newline at end of file
diff --git a/sdvx@asphyxia/utils.ts b/sdvx@asphyxia/utils.ts
new file mode 100644
index 0000000..3fd5e88
--- /dev/null
+++ b/sdvx@asphyxia/utils.ts
@@ -0,0 +1,14 @@
+import { Counter } from './models/counter';
+export function IDToCode(id: number) {
+ const padded = _.padStart(id.toString(), 8);
+ return `${padded.slice(0, 4)}-${padded.slice(4)}`;
+}
+
+export async function GetCounter(key: string) {
+ return (
+ await DB.Upsert(
+ { collection: 'counter', key: 'mix' },
+ { $inc: { value: 1 } }
+ )
+ ).docs[0].value;
+}