mirror of
https://github.com/asphyxia-core/plugins.git
synced 2026-03-21 17:34:46 -05:00
Add rivals support for Lapistoria-peace
Fix stamp not properly initialized on usaneko
This commit is contained in:
parent
efb28ad9a0
commit
c3119b6e4b
|
|
@ -1,6 +1,6 @@
|
|||
# Pop'n Music
|
||||
|
||||
Plugin Version: **v2.0.0**
|
||||
Plugin Version: **v2.1.0**
|
||||
|
||||
## Supported Versions
|
||||
- pop'n music 19 Tune Street
|
||||
|
|
@ -15,6 +15,10 @@ Important : require minimum Asphyxia Core **v1.31**
|
|||
|
||||
## Changelog
|
||||
|
||||
### 2.1.0
|
||||
* Add rivals support
|
||||
* Various fixes
|
||||
|
||||
### 2.0.0
|
||||
* Big rewrite/reorganization of the code
|
||||
* Add support for Tune Street, fantasia, Sunny Park, Lapistoria
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ export const setRoutes = () => {
|
|||
R.Route(`player23.read_score`, readScore);
|
||||
R.Route(`player23.write_music`, writeScore);
|
||||
R.Route(`player23.write`, write);
|
||||
R.Route(`player23.friend`, friend);
|
||||
}
|
||||
|
||||
const getInfoCommon = (req: EamuseInfo) => {
|
||||
|
|
@ -130,16 +131,31 @@ const readScore = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<
|
|||
const refid = $(data).str('ref_id');
|
||||
if (!refid) return send.deny();
|
||||
|
||||
send.object({ music: await getScores(refid, version) });
|
||||
};
|
||||
|
||||
const getScores = async (refid: string, version: string, forFriend: boolean = false) => {
|
||||
const scoresData = await utils.readScores(refid, version);
|
||||
const result: any = {
|
||||
music: [],
|
||||
};
|
||||
const result = [];
|
||||
|
||||
for (const key in scoresData.scores) {
|
||||
const keyData = key.split(':');
|
||||
const score = scoresData.scores[key];
|
||||
const music = parseInt(keyData[0], 10);
|
||||
const sheet = parseInt(keyData[1], 10);
|
||||
const clearType = {
|
||||
100: 1,
|
||||
200: 2,
|
||||
300: 3,
|
||||
400: 4,
|
||||
500: 5,
|
||||
600: 6,
|
||||
700: 7,
|
||||
800: 8,
|
||||
900: 9,
|
||||
1000: 10,
|
||||
1100: 11,
|
||||
}[score.clear_type];
|
||||
|
||||
if (music > GAME_MAX_MUSIC_ID) {
|
||||
continue;
|
||||
|
|
@ -148,28 +164,24 @@ const readScore = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<
|
|||
continue;
|
||||
}
|
||||
|
||||
result.music.push({
|
||||
music_num: K.ITEM('s16', music),
|
||||
sheet_num: K.ITEM('u8', sheet),
|
||||
score: K.ITEM('s32', score.score),
|
||||
clear_type: K.ITEM('u8', {
|
||||
100: 1,
|
||||
200: 2,
|
||||
300: 3,
|
||||
400: 4,
|
||||
500: 5,
|
||||
600: 6,
|
||||
700: 7,
|
||||
800: 8,
|
||||
900: 9,
|
||||
1000: 10,
|
||||
1100: 11,
|
||||
}[score.clear_type]),
|
||||
cnt: K.ITEM('s16', score.cnt),
|
||||
});
|
||||
if(forFriend) {
|
||||
result.push(K.ATTR({
|
||||
music_num: music.toString(),
|
||||
sheet_num: sheet.toString(),
|
||||
score: score.score.toString(),
|
||||
clearmedal: clearType.toString()
|
||||
}));
|
||||
} else {
|
||||
result.push({
|
||||
music_num: K.ITEM('s16', music),
|
||||
sheet_num: K.ITEM('u8', sheet),
|
||||
score: K.ITEM('s32', score.score),
|
||||
clear_type: K.ITEM('u8', clearType),
|
||||
cnt: K.ITEM('s16', score.cnt),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
send.object(result);
|
||||
return result;
|
||||
};
|
||||
|
||||
const writeScore = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<any> => {
|
||||
|
|
@ -223,6 +235,7 @@ const writeScore = async (req: EamuseInfo, data: any, send: EamuseSend): Promise
|
|||
*/
|
||||
const getProfile = async (refid: string, name?: string) => {
|
||||
const profile = await utils.readProfile(refid);
|
||||
const rivals = await utils.readRivals(refid);
|
||||
|
||||
if (name && name.length > 0) {
|
||||
profile.name = name;
|
||||
|
|
@ -261,6 +274,7 @@ const getProfile = async (refid: string, name?: string) => {
|
|||
is_conv: K.ITEM('s8', 0),
|
||||
meteor_flg: K.ITEM('bool', true),
|
||||
license_data: K.ARRAY('s16', Array(20).fill(-1)),
|
||||
active_fr_num: K.ITEM('u8', rivals.rivals.length),
|
||||
|
||||
// TODO: replace with real data
|
||||
total_play_cnt: K.ITEM('s16', 100),
|
||||
|
|
@ -270,7 +284,6 @@ const getProfile = async (refid: string, name?: string) => {
|
|||
interval_day: K.ITEM('s16', 1),
|
||||
my_best: K.ARRAY('s16', myBest),
|
||||
latest_music: K.ARRAY('s16', [-1, -1, -1, -1, -1]),
|
||||
active_fr_num: K.ITEM('u8', 0),
|
||||
},
|
||||
netvs: {
|
||||
record: K.ARRAY('s16', [0, 0, 0, 0, 0, 0]),
|
||||
|
|
@ -424,6 +437,34 @@ const write = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<any>
|
|||
send.success();
|
||||
};
|
||||
|
||||
const friend = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<any> => {
|
||||
const refid = $(data).attr()['ref_id'];
|
||||
const no = parseInt($(data).attr()['no'], -1);
|
||||
|
||||
const rivals = await utils.readRivals(refid);
|
||||
|
||||
if(no < 0 || no >= rivals.rivals.length) {
|
||||
send.object({result : K.ITEM('s8', 2)});
|
||||
return;
|
||||
}
|
||||
|
||||
const profile = await utils.readProfile(rivals.rivals[no]);
|
||||
const params = await utils.readParams(rivals.rivals[no], version);
|
||||
|
||||
const friend = {
|
||||
friend: {
|
||||
no: K.ITEM('s16', no),
|
||||
g_pm_id: K.ITEM('str', 'ASPHYXIAPLAY'),
|
||||
name: K.ITEM('str', profile.name),
|
||||
chara: K.ITEM('s16', params.params.chara || -1),
|
||||
is_open: K.ITEM('s8', 1),
|
||||
music : await getScores(rivals.rivals[no], version, true),
|
||||
}
|
||||
}
|
||||
|
||||
send.object(friend);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const version: string = 'v23';
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ export const setRoutes = () => {
|
|||
R.Route(`player22.read`, read);
|
||||
R.Route(`player22.write_music`, writeScore);
|
||||
R.Route(`player22.write`, write);
|
||||
R.Route(`player22.friend`, friend);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -110,6 +111,7 @@ const writeScore = async (req: EamuseInfo, data: any, send: EamuseSend): Promise
|
|||
*/
|
||||
const getProfile = async (refid: string, name?: string) => {
|
||||
const profile = await utils.readProfile(refid);
|
||||
const rivals = await utils.readRivals(refid);
|
||||
|
||||
if (name && name.length > 0) {
|
||||
profile.name = name;
|
||||
|
|
@ -126,6 +128,7 @@ const getProfile = async (refid: string, name?: string) => {
|
|||
item_type: K.ITEM('s16', 0),
|
||||
item_id: K.ITEM('s16', 0),
|
||||
license_data: K.ARRAY('s16', [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1]),
|
||||
active_fr_num: K.ITEM('u8', rivals.rivals.length),
|
||||
|
||||
// TODO: replace with real data
|
||||
total_play_cnt: K.ITEM('s16', 100),
|
||||
|
|
@ -134,7 +137,6 @@ const getProfile = async (refid: string, name?: string) => {
|
|||
total_days: K.ITEM('s16', 366),
|
||||
interval_day: K.ITEM('s16', 1),
|
||||
latest_music: K.ARRAY('s16', [-1, -1, -1, -1, -1]),
|
||||
active_fr_num: K.ITEM('u8', 0),
|
||||
},
|
||||
netvs: {
|
||||
rank_point: K.ITEM('s32', 0),
|
||||
|
|
@ -372,6 +374,70 @@ const write = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<any>
|
|||
send.success();
|
||||
};
|
||||
|
||||
const friend = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<any> => {
|
||||
const refid = $(data).attr()['ref_id'];
|
||||
const no = parseInt($(data).attr()['no'], -1);
|
||||
|
||||
const rivals = await utils.readRivals(refid);
|
||||
|
||||
if(no < 0 || no >= rivals.rivals.length) {
|
||||
send.object({result : K.ITEM('s8', 2)});
|
||||
return;
|
||||
}
|
||||
|
||||
const profile = await utils.readProfile(rivals.rivals[no]);
|
||||
const params = await utils.readParams(rivals.rivals[no], version);
|
||||
|
||||
// Add Score
|
||||
const scoresData = await utils.readScores(rivals.rivals[no], version);
|
||||
const scores = [];
|
||||
for (const key in scoresData.scores) {
|
||||
const keyData = key.split(':');
|
||||
const score = scoresData.scores[key];
|
||||
const music = parseInt(keyData[0], 10);
|
||||
const sheet = parseInt(keyData[1], 10);
|
||||
|
||||
if (music > GAME_MAX_MUSIC_ID) {
|
||||
continue;
|
||||
}
|
||||
if ([0, 1, 2, 3].indexOf(sheet) == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
scores.push(K.ATTR({
|
||||
music_num: music.toString(),
|
||||
sheet_num: sheet.toString(),
|
||||
score: score.score.toString(),
|
||||
clearmedal: {
|
||||
100: 1,
|
||||
200: 2,
|
||||
300: 3,
|
||||
400: 4,
|
||||
500: 5,
|
||||
600: 6,
|
||||
700: 7,
|
||||
800: 8,
|
||||
900: 9,
|
||||
1000: 10,
|
||||
1100: 11,
|
||||
}[score.clear_type].toString(),
|
||||
}));
|
||||
}
|
||||
|
||||
const friend = {
|
||||
friend: {
|
||||
no: K.ITEM('s16', no),
|
||||
g_pm_id: K.ITEM('str', 'ASPHYXIAPLAY'),
|
||||
name: K.ITEM('str', profile.name),
|
||||
chara: K.ITEM('s16', params.params.chara || -1),
|
||||
is_open: K.ITEM('s8', 1),
|
||||
music: scores,
|
||||
}
|
||||
}
|
||||
|
||||
send.object(friend);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const version: string = 'v22';
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ export const setRoutes = () => {
|
|||
R.Route(`player24.read_score`, readScore);
|
||||
R.Route(`player24.write_music`, writeScore);
|
||||
R.Route(`player24.write`, write);
|
||||
R.Route(`player24.friend`, friend);
|
||||
}
|
||||
|
||||
const getInfoCommon = (req: EamuseInfo) => {
|
||||
|
|
@ -148,7 +149,7 @@ const readScore = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<
|
|||
send.object({ music: await getScores(refid, version) });
|
||||
};
|
||||
|
||||
const getScores = async (refid: string, version: string) => {
|
||||
const getScores = async (refid: string, version: string, forFriend: boolean = false) => {
|
||||
const scoresData = await utils.readScores(refid, version);
|
||||
const result = [];
|
||||
|
||||
|
|
@ -157,6 +158,19 @@ const getScores = async (refid: string, version: string) => {
|
|||
const score = scoresData.scores[key];
|
||||
const music = parseInt(keyData[0], 10);
|
||||
const sheet = parseInt(keyData[1], 10);
|
||||
const clearType = {
|
||||
100: 1,
|
||||
200: 2,
|
||||
300: 3,
|
||||
400: 4,
|
||||
500: 5,
|
||||
600: 6,
|
||||
700: 7,
|
||||
800: 8,
|
||||
900: 9,
|
||||
1000: 10,
|
||||
1100: 11,
|
||||
}[score.clear_type];
|
||||
|
||||
if (music > GAME_MAX_MUSIC_ID[version]) {
|
||||
continue;
|
||||
|
|
@ -165,26 +179,24 @@ const getScores = async (refid: string, version: string) => {
|
|||
continue;
|
||||
}
|
||||
|
||||
result.push({
|
||||
music_num: K.ITEM('s16', music),
|
||||
sheet_num: K.ITEM('u8', sheet),
|
||||
score: K.ITEM('s32', score.score),
|
||||
clear_type: K.ITEM('u8', {
|
||||
100: 1,
|
||||
200: 2,
|
||||
300: 3,
|
||||
400: 4,
|
||||
500: 5,
|
||||
600: 6,
|
||||
700: 7,
|
||||
800: 8,
|
||||
900: 9,
|
||||
1000: 10,
|
||||
1100: 11,
|
||||
}[score.clear_type]),
|
||||
clear_rank: K.ITEM('u8', getRank(score.score)),
|
||||
cnt: K.ITEM('s16', score.cnt),
|
||||
});
|
||||
if(forFriend) {
|
||||
result.push(K.ATTR({
|
||||
music_num: music.toString(),
|
||||
sheet_num: sheet.toString(),
|
||||
score: score.score.toString(),
|
||||
cleartype: clearType.toString(),
|
||||
clearrank: getRank(score.score).toString()
|
||||
}));
|
||||
} else {
|
||||
result.push({
|
||||
music_num: K.ITEM('s16', music),
|
||||
sheet_num: K.ITEM('u8', sheet),
|
||||
score: K.ITEM('s32', score.score),
|
||||
clear_type: K.ITEM('u8', clearType),
|
||||
clear_rank: K.ITEM('u8', getRank(score.score)),
|
||||
cnt: K.ITEM('s16', score.cnt),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -261,6 +273,7 @@ const writeScore = async (req: EamuseInfo, data: any, send: EamuseSend): Promise
|
|||
*/
|
||||
const getProfile = async (refid: string, version: string, name?: string) => {
|
||||
const profile = await utils.readProfile(refid);
|
||||
const rivals = await utils.readRivals(refid);
|
||||
|
||||
if (name && name.length > 0) {
|
||||
profile.name = name;
|
||||
|
|
@ -299,6 +312,7 @@ const getProfile = async (refid: string, version: string, name?: string) => {
|
|||
is_conv: K.ITEM('s8', 0),
|
||||
license_data: K.ARRAY('s16', Array(20).fill(-1)),
|
||||
my_best: K.ARRAY('s16', myBest),
|
||||
active_fr_num: K.ITEM('u8', rivals.rivals.length),
|
||||
|
||||
// TODO: replace with real data
|
||||
total_play_cnt: K.ITEM('s16', 100),
|
||||
|
|
@ -307,7 +321,6 @@ const getProfile = async (refid: string, version: string, name?: string) => {
|
|||
total_days: K.ITEM('s16', 366),
|
||||
interval_day: K.ITEM('s16', 1),
|
||||
latest_music: K.ARRAY('s16', [-1, -1, -1, -1, -1]),
|
||||
active_fr_num: K.ITEM('u8', 0),
|
||||
},
|
||||
netvs: {
|
||||
record: K.ARRAY('s16', [0, 0, 0, 0, 0, 0]),
|
||||
|
|
@ -381,7 +394,10 @@ const getProfile = async (refid: string, version: string, name?: string) => {
|
|||
});
|
||||
}
|
||||
|
||||
const profileStamps = achievements.stamps || { '0': 0 };
|
||||
let profileStamps = achievements.stamps;
|
||||
if(Object.entries(profileStamps).length == 0) {
|
||||
profileStamps = {"0": 0 };
|
||||
}
|
||||
for (const stamp_id in profileStamps) {
|
||||
player.stamp.push({
|
||||
stamp_id: K.ITEM('s16', parseInt(stamp_id, 10)),
|
||||
|
|
@ -595,6 +611,35 @@ const write = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<any>
|
|||
send.success();
|
||||
};
|
||||
|
||||
const friend = async (req: EamuseInfo, data: any, send: EamuseSend): Promise<any> => {
|
||||
const refid = $(data).attr()['ref_id'];
|
||||
const no = parseInt($(data).attr()['no'], -1);
|
||||
const version = getVersion(req);
|
||||
|
||||
const rivals = await utils.readRivals(refid);
|
||||
|
||||
if(no < 0 || no >= rivals.rivals.length) {
|
||||
send.object({result : K.ITEM('s8', 2)});
|
||||
return;
|
||||
}
|
||||
|
||||
const profile = await utils.readProfile(rivals.rivals[no]);
|
||||
const params = await utils.readParams(rivals.rivals[no], version);
|
||||
|
||||
const friend = {
|
||||
friend: {
|
||||
no: K.ITEM('s16', no),
|
||||
g_pm_id: K.ITEM('str', 'ASPHYXIAPLAY'),
|
||||
name: K.ITEM('str', profile.name),
|
||||
chara: K.ITEM('s16', params.params.chara || -1),
|
||||
is_open: K.ITEM('s8', 1),
|
||||
music : await getScores(rivals.rivals[no], version, true),
|
||||
}
|
||||
}
|
||||
|
||||
send.object(friend);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const getVersion = (req: EamuseInfo): string => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Achievements } from "../models/achievements";
|
||||
import { Profile, Scores, ExtraData, Params } from "../models/common";
|
||||
import { Profile, Scores, ExtraData, Params, Rivals } from "../models/common";
|
||||
|
||||
const CURRENT_DATA_VERSION = 2;
|
||||
|
||||
|
|
@ -68,6 +68,11 @@ export const writeProfile = async (refid: string, profile: Profile) => {
|
|||
await DB.Upsert<Profile>(refid, { collection: 'profile' }, profile);
|
||||
}
|
||||
|
||||
export const readRivals = async (refid: string): Promise<Rivals> => {
|
||||
const rivals = await DB.FindOne<Rivals>(refid, { collection: 'rivals' });
|
||||
return rivals || { collection: 'rivals', rivals: [] };
|
||||
}
|
||||
|
||||
export const readParams = async (refid: string, version: string): Promise<Params> => {
|
||||
const params = await DB.FindOne<Params>(refid, { collection: 'params', version });
|
||||
return params || { collection: 'params', version, params: {} };
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import * as lapistoria from "./handler/lapistoria";
|
|||
import * as eclale from "./handler/eclale";
|
||||
import * as usaneko from "./handler/usaneko";
|
||||
import { importPnmData } from "./handler/webui";
|
||||
import { Rivals } from "./models/common";
|
||||
|
||||
const getVersion = (req: any) => {
|
||||
switch (req.gameCode) {
|
||||
|
|
@ -24,7 +25,7 @@ export function register() {
|
|||
|
||||
R.Config("enable_score_sharing", {
|
||||
name: "Score sharing",
|
||||
desc: "Enable sharing scores between versions",
|
||||
desc: "Enable sharing scores between versions. This also affect rivals scores.",
|
||||
type: "boolean",
|
||||
default: true,
|
||||
});
|
||||
|
|
@ -35,8 +36,29 @@ export function register() {
|
|||
await DB.Update(data.refid, { collection: 'profile' }, { $set: { name: data.name } });
|
||||
});
|
||||
|
||||
// Route management for PnM <= 21
|
||||
// Rivals UI management
|
||||
R.WebUIEvent('deleteRival', async (data: any) => {
|
||||
const rivals = await DB.FindOne<Rivals>(data.refid, { collection: 'rivals' }) || {collection: 'rivals', rivals: []};
|
||||
const idx = rivals.rivals.indexOf(data.rivalid);
|
||||
if(idx >= 0) {
|
||||
rivals.rivals.splice(idx, 1);
|
||||
await DB.Update(data.refid, { collection: 'rivals' }, rivals);
|
||||
}
|
||||
});
|
||||
|
||||
R.WebUIEvent('addRival', async (data: any) => {
|
||||
const refid = data.refid.trim();
|
||||
const profile = await DB.FindOne(refid, { collection: 'profile'});
|
||||
if(profile != undefined && profile != null) {
|
||||
const rivals = await DB.FindOne<Rivals>(refid, { collection: 'rivals' }) || {collection: 'rivals', rivals: []};
|
||||
if(rivals.rivals.length < 4) {
|
||||
rivals.rivals.push(data.rivalid);
|
||||
await DB.Upsert(refid, { collection: 'rivals' }, rivals);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Route management for PnM <= 21
|
||||
R.Route(`game.get`, async (req, data, send) => getVersion(req).getInfo(req, data, send));
|
||||
R.Route(`playerdata.new`, async (req, data, send) => getVersion(req).newPlayer(req, data, send));
|
||||
R.Route(`playerdata.conversion`, async (req, data, send) => getVersion(req).newPlayer(req, data, send));
|
||||
|
|
@ -44,7 +66,6 @@ export function register() {
|
|||
R.Route(`playerdata.set`, async (req, data, send) => getVersion(req).write(req, data, send));
|
||||
|
||||
// For Pnm >= 22, each game set his own route
|
||||
|
||||
lapistoria.setRoutes();
|
||||
eclale.setRoutes();
|
||||
usaneko.setRoutes();
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ export interface Params {
|
|||
};
|
||||
}
|
||||
|
||||
export interface Rivals {
|
||||
collection: 'rivals',
|
||||
rivals: string[]
|
||||
}
|
||||
|
||||
export interface Scores {
|
||||
collection: 'scores',
|
||||
version: string,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//DATA//
|
||||
profile: DB.FindOne(refid, { collection: 'profile' })
|
||||
rivals: DB.FindOne(refid, { collection: 'rivals' })
|
||||
|
||||
div
|
||||
div.notification.is-success.is-hidden#import-success
|
||||
|
|
@ -23,6 +24,44 @@ div
|
|||
span.icon
|
||||
i.mdi.mdi-check
|
||||
span Submit
|
||||
.card
|
||||
.card-header
|
||||
p.card-header-title
|
||||
span.icon
|
||||
i.mdi.mdi-account-edit
|
||||
| Rivals
|
||||
.card-content
|
||||
.columns.is-multiline
|
||||
if rivals != null
|
||||
- for (const rival of rivals.rivals)
|
||||
form(method="post" action="/emit/deleteRival").column.is-4
|
||||
.box
|
||||
input(type="hidden" id="refid" name="refid" value=refid)
|
||||
input(type="hidden" id="rivalid" name="rivalid" value=rival)
|
||||
.field
|
||||
input.input(type="text" value=rival disabled="disabled")
|
||||
.field
|
||||
button.button.is-primary
|
||||
span.icon
|
||||
i.mdi.mdi-file-import-outline
|
||||
span Delete
|
||||
if rivals == null || rivals.rivals.length < 4
|
||||
form(method="post" action="/emit/addRival").column.is-4
|
||||
.box
|
||||
input(type="hidden" id="refid" name="refid" value=refid)
|
||||
.field
|
||||
input.input(type="text" id="rivalid" name="rivalid" placeholder="Rival ID (ex. AAB56E7436549D83)")
|
||||
.field
|
||||
button.button.is-primary
|
||||
span.icon
|
||||
i.mdi.mdi-file-import-outline
|
||||
span Add
|
||||
div
|
||||
label To add a rival, use the profile ID located on the POPN Profiles page.
|
||||
div
|
||||
label There is a limit of 4 rivals maximum (only the 2 firsts will be used for Sunny Park and lower).
|
||||
div
|
||||
label The score sharing option also affect scores get from rivals.
|
||||
.card
|
||||
.card-header
|
||||
p.card-header-title
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user