danoniplus 36.1.0 → 36.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/js/danoni_main.js CHANGED
@@ -4,12 +4,12 @@
4
4
  *
5
5
  * Source by tickle
6
6
  * Created : 2018/10/08
7
- * Revised : 2024/04/18
7
+ * Revised : 2024/05/01
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 36.1.0`;
12
- const g_revisedDate = `2024/04/18`;
11
+ const g_version = `Ver 36.2.0`;
12
+ const g_revisedDate = `2024/05/01`;
13
13
 
14
14
  // カスタム用バージョン (danoni_custom.js 等で指定可)
15
15
  let g_localVersion = ``;
@@ -261,13 +261,13 @@ const trimStr = _str => _str?.split(`\t`).join(``).trimStart().trimEnd();
261
261
  * 変数が存在するかどうかをチェック
262
262
  * @param {string} _data
263
263
  */
264
- const hasVal = _data => _data !== undefined && _data !== ``;
264
+ const hasVal = (_data, ...strs) => _data !== undefined && _data !== `` && (!strs || strs.every(str => _data !== str));
265
265
 
266
266
  /**
267
267
  * 変数が存在するかどうかをチェック(null無しを含む)
268
268
  * @param {string} _data
269
269
  */
270
- const hasValN = _data => hasVal(_data) && _data !== null;
270
+ const hasValN = (_data, ...strs) => hasVal(_data, ...strs) && _data !== null;
271
271
 
272
272
  /**
273
273
  * 文字列から他の型へ変換する処理群
@@ -4841,7 +4841,7 @@ const updateScoreDetailLabel = (_name, _label, _value, _pos = 0, _labelname = _l
4841
4841
  const baseLabel = (_bLabel, _bLabelname, _bAlign) =>
4842
4842
  document.getElementById(`detail${_name}`).appendChild(
4843
4843
  createDivCss2Label(_bLabel, _bLabelname, {
4844
- x: 10, y: 105 + _pos * 20, w: 100, h: 20, siz: g_limitObj.difSelectorSiz, align: _bAlign,
4844
+ x: 10, y: 110 + _pos * 20, w: 100, h: 20, siz: g_limitObj.difSelectorSiz, align: _bAlign,
4845
4845
  })
4846
4846
  );
4847
4847
  if (document.getElementById(`data${_label}`) === null) {
@@ -5008,6 +5008,139 @@ const makeDifInfo = _scoreId => {
5008
5008
  ${makeArrowCntsView(g_detailObj.frzCnt[_scoreId])}<br><br>${push3CntStr}`;
5009
5009
  };
5010
5010
 
5011
+ /**
5012
+ * ハイスコア表示
5013
+ * @param {number} _scoreId
5014
+ */
5015
+ const makeHighScore = _scoreId => {
5016
+ const detailHighScore = document.getElementById(`detailHighScore`);
5017
+
5018
+ // 再描画のため一度クリア
5019
+ deleteChildspriteAll(`detailHighScore`);
5020
+
5021
+ const keyCtrlPtn = `${g_keyObj.currentKey}_${g_keyObj.currentPtn}`;
5022
+ const assistFlg = (g_autoPlaysBase.includes(g_stateObj.autoPlay) ? `` : `-${getStgDetailName(g_stateObj.autoPlay)}${getStgDetailName('less')}`);
5023
+ const mirrorName = (g_stateObj.shuffle === C_FLG_OFF ? `` : `-${g_stateObj.shuffle}`);
5024
+ const transKeyName = (hasVal(g_keyObj[`transKey${keyCtrlPtn}`]) ? `(${g_keyObj[`transKey${keyCtrlPtn}`]})` : ``);
5025
+ let scoreName = `${g_headerObj.keyLabels[_scoreId]}${transKeyName}${getStgDetailName('k-')}${g_headerObj.difLabels[_scoreId]}${assistFlg}${mirrorName}`;
5026
+ if (g_headerObj.makerView) {
5027
+ scoreName += `-${g_headerObj.creatorNames[_scoreId]}`;
5028
+ }
5029
+
5030
+ const createScoreLabel = (_id, _text, { xPos = 0, yPos = 0, dx = 0, w = 150, h = 17, colorName = _id, align = C_ALIGN_LEFT, overflow = `visible` } = {}) =>
5031
+ createDivCss2Label(`lblH${toCapitalize(_id)}`, _text, {
5032
+ x: xPos * 150 + 130 + dx, y: yPos * 16 + 5, w, h, siz: 14, align, overflow,
5033
+ }, g_cssObj[`common_${colorName}`]);
5034
+
5035
+ const charas = [
5036
+ `ii`, `shakin`, `matari`, `shobon`, `uwan`, `kita`, `iknai`, `maxCombo`, `fmaxCombo`, ``, `score`,
5037
+ ];
5038
+ const extData = {
5039
+ fast: `diffFast`, slow: `diffSlow`, adj: `estAdj`, excessive: `excessive`,
5040
+ };
5041
+ // 各判定 (FreezeComboとScoreの間に1行の空白を入れる)
5042
+ charas.forEach((chara, j) => {
5043
+ if (chara === ``) {
5044
+ return;
5045
+ }
5046
+ multiAppend(detailHighScore,
5047
+ createScoreLabel(chara, g_lblNameObj[`j_${chara}`], { yPos: j }),
5048
+ createScoreLabel(`${chara}S`, g_localStorage.highscores?.[scoreName]?.[chara] ?? `---`,
5049
+ { xPos: 0, yPos: j, align: C_ALIGN_RIGHT }),
5050
+ );
5051
+ });
5052
+ // Fast, Slow, 推定Adj, Excessive (値が無ければスキップ)
5053
+ Object.keys(extData).forEach((chara, j) => {
5054
+ if (!hasVal(g_localStorage.highscores?.[scoreName]?.[chara], `---`)) {
5055
+ return;
5056
+ }
5057
+ multiAppend(detailHighScore,
5058
+ createScoreLabel(chara, g_lblNameObj[`j_${chara}`], { xPos: 1, yPos: j, dx: 20, colorName: extData[chara] }),
5059
+ createScoreLabel(`${chara}S`, g_localStorage.highscores?.[scoreName]?.[chara],
5060
+ { xPos: 1, yPos: j, dx: -25, align: C_ALIGN_RIGHT }),
5061
+ );
5062
+ });
5063
+ if (hasVal(g_localStorage.highscores?.[scoreName]?.adj)) {
5064
+ multiAppend(detailHighScore, createScoreLabel(`adjF`, `f`, { xPos: 2, yPos: 2, dx: -23 }));
5065
+ }
5066
+
5067
+ // カスタム表示 (resultValsViewに指定した表示のみ)
5068
+ g_headerObj.resultValsView
5069
+ .filter(key => hasVal(g_localStorage.highscores?.[scoreName]?.[g_presetObj.resultVals?.[key]]))
5070
+ .forEach((key, j) => {
5071
+ multiAppend(detailHighScore,
5072
+ createScoreLabel(key, g_presetObj.resultVals[key], { xPos: 1, yPos: j + 5, dx: 20 }),
5073
+ createScoreLabel(`${key}S`, g_localStorage.highscores?.[scoreName]?.[g_presetObj.resultVals[key]],
5074
+ { xPos: 1, yPos: j + 5, dx: -25, align: C_ALIGN_RIGHT }),
5075
+ );
5076
+ });
5077
+ // ランク、クリアランプ、特殊設定条件
5078
+ multiAppend(detailHighScore,
5079
+ createDivCss2Label(`lblHRank`, g_localStorage.highscores?.[scoreName]?.rankMark ?? `--`, Object.assign(g_lblPosObj.lblHRank, {
5080
+ color: g_localStorage.highscores?.[scoreName]?.rankColor ?? `#666666`,
5081
+ fontFamily: getBasicFont(`"Bookman Old Style"`),
5082
+ })),
5083
+ createScoreLabel(`lblHDateTime`, g_localStorage.highscores?.[scoreName]?.dateTime ?? `----/--/-- --/--`, { yPos: 12 }),
5084
+ createScoreLabel(`lblHMarks`,
5085
+ `${g_localStorage.highscores?.[scoreName]?.fullCombo ?? '' ? '<span class="result_FullCombo">◆</span>' : ''}` +
5086
+ `${g_localStorage.highscores?.[scoreName]?.perfect ?? '' ? '<span class="result_Perfect">◆</span>' : ''}` +
5087
+ `${g_localStorage.highscores?.[scoreName]?.allPerfect ?? '' ? '<span class="result_AllPerfect">◆</span>' : ''}`, { xPos: 1, dx: 20, yPos: 12, w: 100, align: C_ALIGN_CENTER }),
5088
+ createScoreLabel(`lblHClearLamps`, `Cleared: ` + (g_localStorage.highscores?.[scoreName]?.clearLamps?.join(', ') ?? `---`), { yPos: 13, overflow: `auto`, w: g_sWidth / 2 + 40, h: 37 }),
5089
+
5090
+ createScoreLabel(`lblHShuffle`, g_stateObj.shuffle.indexOf(`Mirror`) < 0 ? `` : `Shuffle: <span class="common_iknai">${g_stateObj.shuffle}</span>`, { yPos: 11.5, dx: -130 }),
5091
+ createScoreLabel(`lblHAssist`, g_autoPlaysBase.includes(g_stateObj.autoPlay) ? `` : `Assist: <span class="common_kita">${g_stateObj.autoPlay}</span>`, { yPos: 12.5, dx: -130 }),
5092
+ createScoreLabel(`lblHAnother`, !hasVal(g_keyObj[`transKey${keyCtrlPtn}`]) ? `` : `A.Keymode: <span class="common_ii">${g_keyObj[`transKey${keyCtrlPtn}`]}</span>`, { yPos: 13.5, dx: -130 }),
5093
+ );
5094
+
5095
+ // 結果をクリップボードへコピー (ハイスコア保存分)
5096
+ if (g_localStorage.highscores?.[scoreName] !== undefined) {
5097
+ const twiturl = new URL(g_localStorageUrl);
5098
+ twiturl.searchParams.append(`scoreId`, _scoreId);
5099
+ const baseTwitUrl = g_isLocal ? `` : `${twiturl.toString()}`.replace(/[\t\n]/g, ``);
5100
+
5101
+ let tweetFrzJdg = ``;
5102
+ let tweetMaxCombo = `${g_localStorage.highscores?.[scoreName]?.maxCombo}`;
5103
+ if (g_allFrz > 0) {
5104
+ tweetFrzJdg = `${g_localStorage.highscores?.[scoreName]?.kita}-${g_localStorage.highscores?.[scoreName]?.iknai}`;
5105
+ tweetMaxCombo += `-${g_localStorage.highscores?.[scoreName]?.fmaxCombo}`;
5106
+ }
5107
+
5108
+ const musicTitle = g_headerObj.musicTitles[g_headerObj.musicNos[_scoreId]] || g_headerObj.musicTitle;
5109
+ let tweetDifData = `${getKeyName(g_headerObj.keyLabels[_scoreId])}${transKeyName}${getStgDetailName('k-')}${g_headerObj.difLabels[_scoreId]}${assistFlg}`;
5110
+ if (g_stateObj.shuffle !== `OFF`) {
5111
+ tweetDifData += `:${getStgDetailName(g_stateObj.shuffle)}`;
5112
+ }
5113
+
5114
+ const resultParams = {
5115
+ hashTag: (hasVal(g_headerObj.hashTag) ? ` ${g_headerObj.hashTag}` : ``),
5116
+ tuning: g_headerObj.creatorNames[_scoreId],
5117
+ rankMark: g_localStorage.highscores?.[scoreName]?.rankMark || `--`,
5118
+ playStyleData: g_localStorage.highscores[scoreName]?.playStyle || `--`,
5119
+ highscore: g_localStorage.highscores[scoreName],
5120
+ tweetExcessive: hasVal(g_localStorage.highscores[scoreName]?.excessive, `---`) ? `(+${g_resultObj.excessive})` : ``,
5121
+ musicTitle, tweetDifData, tweetFrzJdg, tweetMaxCombo, baseTwitUrl,
5122
+ };
5123
+ const resultCommon = unEscapeHtml(makeResultText(g_templateObj.resultFormatDf, resultParams));
5124
+ let tweetResultTmp = makeResultText(g_headerObj.resultFormat, resultParams);
5125
+ if (g_presetObj.resultVals !== undefined) {
5126
+ Object.keys(g_presetObj.resultVals).forEach(key =>
5127
+ tweetResultTmp = tweetResultTmp.split(`[${key}]`).join(g_localStorage.highscores[scoreName][g_presetObj.resultVals[key]] || ``));
5128
+ }
5129
+ const resultText = `${unEscapeHtml(tweetResultTmp)}`;
5130
+ multiAppend(detailHighScore,
5131
+ makeDifLblCssButton(`lnkResetHighScore`, g_lblNameObj.s_resetResult, 7, _ => {
5132
+ if (window.confirm(g_msgObj.highscResetConfirm)) {
5133
+ delete g_localStorage.highscores[scoreName];
5134
+ makeHighScore(_scoreId);
5135
+ }
5136
+ }, Object.assign({ btnStyle: `Reset` }, g_lblPosObj.lnkHighScore)),
5137
+ makeDifLblCssButton(`lnkHighScore`, g_lblNameObj.s_result, 8, _ => {
5138
+ copyTextToClipboard(keyIsShift() ? resultCommon : resultText, g_msgInfoObj.I_0001);
5139
+ }, g_lblPosObj.lnkHighScore),
5140
+ );
5141
+ }
5142
+ };
5143
+
5011
5144
  /**
5012
5145
  * 譜面初期化処理
5013
5146
  * - 譜面の基本設定(キー数、初期速度、リバース、ゲージ設定)をここで行う
@@ -5153,11 +5286,6 @@ const setDifficulty = (_initFlg) => {
5153
5286
 
5154
5287
  // 速度設定 (Speed)
5155
5288
  setSetting(0, `speed`, ` ${g_lblNameObj.multi}`);
5156
- if (g_settings.scoreDetails.length > 0) {
5157
- drawSpeedGraph(g_stateObj.scoreId);
5158
- drawDensityGraph(g_stateObj.scoreId);
5159
- makeDifInfo(g_stateObj.scoreId);
5160
- }
5161
5289
 
5162
5290
  // リバース設定 (Reverse, Scroll)
5163
5291
  if (g_headerObj.scrollUse) {
@@ -5182,6 +5310,14 @@ const setDifficulty = (_initFlg) => {
5182
5310
  g_stateObj.autoPlay = g_settings.autoPlays[g_settings.autoPlayNum];
5183
5311
  lnkAutoPlay.textContent = getStgDetailName(g_stateObj.autoPlay);
5184
5312
 
5313
+ // 譜面明細画面の再描画
5314
+ if (g_settings.scoreDetails.length > 0) {
5315
+ drawSpeedGraph(g_stateObj.scoreId);
5316
+ drawDensityGraph(g_stateObj.scoreId);
5317
+ makeDifInfo(g_stateObj.scoreId);
5318
+ makeHighScore(g_stateObj.scoreId);
5319
+ }
5320
+
5185
5321
  // ユーザカスタムイベント(初期)
5186
5322
  g_customJsObj.difficulty.forEach(func => func(_initFlg, g_canLoadDifInfoFlg));
5187
5323
 
@@ -5308,10 +5444,11 @@ const createOptionWindow = _sprite => {
5308
5444
  createScoreDetail(`Speed`),
5309
5445
  createScoreDetail(`Density`),
5310
5446
  createScoreDetail(`ToolDif`, false),
5447
+ createScoreDetail(`HighScore`, false),
5311
5448
  );
5312
5449
  g_settings.scoreDetails.forEach((sd, j) => {
5313
5450
  scoreDetail.appendChild(
5314
- makeDifLblCssButton(`lnk${sd}G`, getStgDetailName(sd), j, _ => changeScoreDetail(j), { w: g_limitObj.difCoverWidth, btnStyle: (g_stateObj.scoreDetail === sd ? `Setting` : `Default`) })
5451
+ makeDifLblCssButton(`lnk${sd}G`, getStgDetailName(sd), j, _ => changeScoreDetail(j), { w: g_limitObj.difCoverWidth, h: 20, btnStyle: (g_stateObj.scoreDetail === sd ? `Setting` : `Default`) })
5315
5452
  );
5316
5453
  createScText(document.getElementById(`lnk${sd}G`), `${sd}G`, { targetLabel: `lnk${sd}G`, x: -5 });
5317
5454
  });
@@ -5375,12 +5512,18 @@ const createOptionWindow = _sprite => {
5375
5512
  // ---------------------------------------------------
5376
5513
  // ミラー・ランダム (Shuffle)
5377
5514
  // 縦位置: 5.5
5378
- createGeneralSetting(spriteList.shuffle, `shuffle`);
5515
+ createGeneralSetting(spriteList.shuffle, `shuffle`, g_settings.scoreDetails.length > 0 ? {
5516
+ addRFunc: _ => makeHighScore(g_stateObj.scoreId),
5517
+ addLFunc: _ => makeHighScore(g_stateObj.scoreId),
5518
+ } : {});
5379
5519
 
5380
5520
  // ---------------------------------------------------
5381
5521
  // 鑑賞モード設定 (AutoPlay)
5382
5522
  // 縦位置: 6.5
5383
- createGeneralSetting(spriteList.autoPlay, `autoPlay`);
5523
+ createGeneralSetting(spriteList.autoPlay, `autoPlay`, g_settings.scoreDetails.length > 0 ? {
5524
+ addRFunc: _ => makeHighScore(g_stateObj.scoreId),
5525
+ addLFunc: _ => makeHighScore(g_stateObj.scoreId),
5526
+ } : {});
5384
5527
 
5385
5528
  // ---------------------------------------------------
5386
5529
  // ゲージ設定 (Gauge)
@@ -5775,6 +5918,7 @@ const gaugeFormat = (_mode, _border, _rcv, _dmg, _init, _lifeValFlg) => {
5775
5918
 
5776
5919
  // 達成率(Accuracy)・許容ミス数の計算
5777
5920
  const [rateText, allowableCntsText] = getAccuracy(borderVal, realRcv, realDmg, initVal, allCnt);
5921
+ g_resultObj.requiredAccuracy = rateText;
5778
5922
 
5779
5923
  return `<div id="gaugeDivCover" class="settings_gaugeDivCover">
5780
5924
  <div id="lblGaugeDivTable" class="settings_gaugeDivTable">
@@ -5919,10 +6063,10 @@ const makeSettingLblCssButton = (_id, _name, _heightPos, _func, { x, y, w, h, si
5919
6063
  * @param {number} _heightPos 上からの配置順
5920
6064
  * @param {function} _func
5921
6065
  */
5922
- const makeDifLblCssButton = (_id, _name, _heightPos, _func, { x = 0, w = g_limitObj.difSelectorWidth, btnStyle = `Default` } = {}) =>
6066
+ const makeDifLblCssButton = (_id, _name, _heightPos, _func, { x = 0, w = g_limitObj.difSelectorWidth, h = g_limitObj.setLblHeight, btnStyle = `Default` } = {}) =>
5923
6067
  createCss2Button(_id, _name, _func, {
5924
- x, y: g_limitObj.setLblHeight * _heightPos,
5925
- w, h: g_limitObj.setLblHeight,
6068
+ x, y: h * _heightPos,
6069
+ w, h,
5926
6070
  siz: g_limitObj.difSelectorSiz,
5927
6071
  borderStyle: `solid`,
5928
6072
  }, g_cssObj[`button_${btnStyle}`], g_cssObj.button_ON);
@@ -6888,8 +7032,7 @@ const keyConfigInit = (_kcType = g_kcType) => {
6888
7032
  makeInfoWindow(g_msgInfoObj.I_0002, `fadeOut0`);
6889
7033
  return;
6890
7034
  } else if ((setKey === C_KEY_TITLEBACK && g_currentk === 0) ||
6891
- ((keyIsDown(g_kCdNameObj.metaLKey) || keyIsDown(g_kCdNameObj.metaRKey)) &&
6892
- (keyIsDown(g_kCdNameObj.shiftLKey) || keyIsDown(g_kCdNameObj.shiftRKey)))) {
7035
+ ((keyIsDown(g_kCdNameObj.metaLKey) || keyIsDown(g_kCdNameObj.metaRKey)) && keyIsShift())) {
6893
7036
  return;
6894
7037
  }
6895
7038
 
@@ -9353,7 +9496,7 @@ const mainInit = _ => {
9353
9496
  // 曲中リトライ、タイトルバック
9354
9497
  if (setCode === g_kCdN[g_headerObj.keyRetry]) {
9355
9498
 
9356
- if (g_isMac && (keyIsDown(g_kCdNameObj.shiftLKey) || keyIsDown(g_kCdNameObj.shiftRKey))) {
9499
+ if (g_isMac && keyIsShift()) {
9357
9500
  // Mac OS、IPad OSはDeleteキーが無いためShift+BSで代用
9358
9501
  g_audio.pause();
9359
9502
  clearTimeout(g_timeoutEvtId);
@@ -9370,7 +9513,7 @@ const mainInit = _ => {
9370
9513
  } else if (setCode === g_kCdN[g_headerObj.keyTitleBack]) {
9371
9514
  g_audio.pause();
9372
9515
  clearTimeout(g_timeoutEvtId);
9373
- if (keyIsDown(g_kCdNameObj.shiftLKey) || keyIsDown(g_kCdNameObj.shiftRKey)) {
9516
+ if (keyIsShift()) {
9374
9517
  if (g_currentArrows !== g_fullArrows || g_stateObj.lifeMode === C_LFE_BORDER && g_workObj.lifeVal < g_workObj.lifeBorder) {
9375
9518
  g_gameOverFlg = true;
9376
9519
  g_finishFlg = false;
@@ -10413,6 +10556,11 @@ const changeFailedFrz = (_j, _k) => {
10413
10556
  */
10414
10557
  const keyIsDown = _keyCode => g_inputKeyBuffer[_keyCode];
10415
10558
 
10559
+ /**
10560
+ * 押したキーがシフトキーかどうかを判定
10561
+ */
10562
+ const keyIsShift = _ => keyIsDown(g_kCdNameObj.shiftLKey) || keyIsDown(g_kCdNameObj.shiftRKey);
10563
+
10416
10564
  /**
10417
10565
  * 矢印・フリーズアロー判定
10418
10566
  * @param {number} _j 対象矢印・フリーズアロー
@@ -11021,6 +11169,7 @@ const resultInit = _ => {
11021
11169
  }
11022
11170
 
11023
11171
  // ユーザカスタムイベント(初期)
11172
+ const currentDateTime = new Date().toLocaleString();
11024
11173
  g_customJsObj.result.forEach(func => func());
11025
11174
 
11026
11175
  if (highscoreCondition) {
@@ -11029,10 +11178,58 @@ const resultInit = _ => {
11029
11178
  .forEach(judge => highscoreDfObj[judge] = g_resultObj[judge] -
11030
11179
  (scoreName in g_localStorage.highscores ? g_localStorage.highscores[scoreName][judge] : 0));
11031
11180
 
11032
- if (highscoreDfObj.score > 0 && g_stateObj.dataSaveFlg) {
11033
- g_localStorage.highscores[scoreName] = {};
11034
- Object.keys(jdgScoreObj).filter(judge => judge !== ``)
11035
- .forEach(judge => g_localStorage.highscores[scoreName][judge] = g_resultObj[judge]);
11181
+ if (g_stateObj.dataSaveFlg) {
11182
+
11183
+ const setScoreData = _ => {
11184
+ g_localStorage.highscores[scoreName].dateTime = currentDateTime;
11185
+ g_localStorage.highscores[scoreName].rankMark = rankMark;
11186
+ g_localStorage.highscores[scoreName].rankColor = rankColor;
11187
+ g_localStorage.highscores[scoreName].playStyle = playStyleData;
11188
+
11189
+ g_localStorage.highscores[scoreName].fast = g_resultObj.fast;
11190
+ g_localStorage.highscores[scoreName].slow = g_resultObj.slow;
11191
+ g_localStorage.highscores[scoreName].adj = estimatedAdj;
11192
+ g_localStorage.highscores[scoreName].excessive = g_stateObj.excessive === C_FLG_ON ?
11193
+ g_resultObj.excessive : `---`;
11194
+
11195
+ if (g_presetObj.resultVals !== undefined) {
11196
+ Object.keys(g_presetObj.resultVals).forEach(key =>
11197
+ g_localStorage.highscores[scoreName][g_presetObj.resultVals[key]] = g_resultObj[g_presetObj.resultVals[key]]);
11198
+ }
11199
+ };
11200
+
11201
+ // All Perfect時(かつスコアが同一時)はFast+Slowが最小のときに更新処理を行う
11202
+ if (rankMark === g_rankObj.rankMarkAllPerfect &&
11203
+ g_localStorage.highscores[scoreName]?.score === g_resultObj.score) {
11204
+ if (g_localStorage.highscores[scoreName].fast === undefined ||
11205
+ g_localStorage.highscores[scoreName].fast + g_localStorage.highscores[scoreName].slow >
11206
+ g_resultObj.fast + g_resultObj.slow) {
11207
+ setScoreData();
11208
+ g_localStorage.highscores[scoreName].score = g_resultObj.score;
11209
+ }
11210
+ }
11211
+
11212
+ // ハイスコア更新時処理
11213
+ if (highscoreDfObj.score > 0) {
11214
+ if (g_localStorage.highscores[scoreName] === undefined) {
11215
+ g_localStorage.highscores[scoreName] = {};
11216
+ }
11217
+ Object.keys(jdgScoreObj).filter(judge => judge !== ``)
11218
+ .forEach(judge => g_localStorage.highscores[scoreName][judge] = g_resultObj[judge]);
11219
+ setScoreData();
11220
+ }
11221
+
11222
+ // クリアランプ点灯処理
11223
+ if (![``, `failed`, `cleared`].includes(g_resultObj.spState)) {
11224
+ g_localStorage.highscores[scoreName][g_resultObj.spState] = true;
11225
+ }
11226
+ if (!g_gameOverFlg && g_finishFlg && g_resultObj.requiredAccuracy !== `----`) {
11227
+ if (g_localStorage.highscores[scoreName].clearLamps === undefined) {
11228
+ g_localStorage.highscores[scoreName].clearLamps = [];
11229
+ }
11230
+ g_localStorage.highscores[scoreName].clearLamps =
11231
+ makeDedupliArray(g_localStorage.highscores[scoreName].clearLamps, [g_stateObj.gauge]);
11232
+ }
11036
11233
  localStorage.setItem(g_localStorageUrl, JSON.stringify(g_localStorage));
11037
11234
  }
11038
11235
 
@@ -11076,21 +11273,14 @@ const resultInit = _ => {
11076
11273
  tweetMaxCombo += `-${g_resultObj.fmaxCombo}`;
11077
11274
  }
11078
11275
 
11079
- const makeResultText = _format => replaceStr(_format, [
11080
- [`[hashTag]`, hashTag],
11081
- [`[musicTitle]`, musicTitle],
11082
- [`[keyLabel]`, tweetDifData],
11083
- [`[maker]`, g_headerObj.tuning],
11084
- [`[rank]`, rankMark],
11085
- [`[score]`, g_resultObj.score],
11086
- [`[playStyle]`, playStyleData],
11087
- [`[arrowJdg]`, `${g_resultObj.ii}-${g_resultObj.shakin}-${g_resultObj.matari}-${g_resultObj.shobon}-${g_resultObj.uwan}${tweetExcessive}`],
11088
- [`[frzJdg]`, tweetFrzJdg],
11089
- [`[maxCombo]`, tweetMaxCombo],
11090
- [`[url]`, baseTwitUrl]
11091
- ]);
11092
- let tweetResultTmp = makeResultText(g_headerObj.resultFormat);
11093
- let resultCommonTmp = makeResultText(g_templateObj.resultFormatDf);
11276
+ const resultParams = {
11277
+ tuning: g_headerObj.tuning,
11278
+ highscore: g_resultObj,
11279
+ hashTag, musicTitle, tweetDifData, playStyleData, rankMark,
11280
+ tweetExcessive, tweetFrzJdg, tweetMaxCombo, baseTwitUrl
11281
+ };
11282
+ let tweetResultTmp = makeResultText(g_headerObj.resultFormat, resultParams);
11283
+ let resultCommonTmp = makeResultText(g_templateObj.resultFormatDf, resultParams);
11094
11284
 
11095
11285
  if (g_presetObj.resultVals !== undefined) {
11096
11286
  Object.keys(g_presetObj.resultVals).forEach(key =>
@@ -11098,7 +11288,6 @@ const resultInit = _ => {
11098
11288
  }
11099
11289
  const resultText = `${unEscapeHtml(tweetResultTmp)}`;
11100
11290
  const tweetResult = `https://twitter.com/intent/tweet?text=${encodeURIComponent(resultText)}`;
11101
- const currentDateTime = new Date().toLocaleString();
11102
11291
 
11103
11292
  /**
11104
11293
  * リザルト画像をCanvasで作成しクリップボードへコピー
@@ -11192,7 +11381,7 @@ const resultInit = _ => {
11192
11381
  if (ClipboardItem === undefined) {
11193
11382
  throw new Error(`error`);
11194
11383
  }
11195
- if (keyIsDown(g_kCdNameObj.shiftLKey) || keyIsDown(g_kCdNameObj.shiftRKey)) {
11384
+ if (keyIsShift()) {
11196
11385
  viewResultImage();
11197
11386
  } else {
11198
11387
  // Canvas の内容を PNG 画像として取得
@@ -11251,7 +11440,7 @@ const resultInit = _ => {
11251
11440
 
11252
11441
  // リザルトデータをクリップボードへコピー
11253
11442
  createCss2Button(`btnCopy`, g_lblNameObj.b_copy, _ =>
11254
- copyTextToClipboard(keyIsDown(g_kCdNameObj.shiftLKey) || keyIsDown(g_kCdNameObj.shiftRKey) ?
11443
+ copyTextToClipboard(keyIsShift() ?
11255
11444
  unEscapeHtml(resultCommonTmp) : resultText, g_msgInfoObj.I_0001),
11256
11445
  g_lblPosObj.btnRsCopy, g_cssObj.button_Setting),
11257
11446
  );
@@ -11322,6 +11511,29 @@ const resultInit = _ => {
11322
11511
  g_skinJsObj.result.forEach(func => func());
11323
11512
  };
11324
11513
 
11514
+ /**
11515
+ * リザルトフォーマットの整形処理
11516
+ * @param {string} _format
11517
+ * @param {object} フォーマット置き換え変数群
11518
+ * @returns
11519
+ */
11520
+ const makeResultText = (_format, {
11521
+ hashTag, musicTitle, tweetDifData, tuning, rankMark, playStyleData,
11522
+ highscore, tweetExcessive, tweetFrzJdg, tweetMaxCombo, baseTwitUrl } = {}) =>
11523
+ replaceStr(_format, [
11524
+ [`[hashTag]`, hashTag],
11525
+ [`[musicTitle]`, musicTitle],
11526
+ [`[keyLabel]`, tweetDifData],
11527
+ [`[maker]`, tuning],
11528
+ [`[rank]`, rankMark],
11529
+ [`[score]`, highscore?.score],
11530
+ [`[playStyle]`, playStyleData],
11531
+ [`[arrowJdg]`, `${highscore?.ii}-${highscore?.shakin}-${highscore?.matari}-${highscore?.shobon}-${highscore?.uwan}${tweetExcessive}`],
11532
+ [`[frzJdg]`, tweetFrzJdg],
11533
+ [`[maxCombo]`, tweetMaxCombo],
11534
+ [`[url]`, baseTwitUrl]
11535
+ ]);
11536
+
11325
11537
  /**
11326
11538
  * 結果表示作成(曲名、オプション)
11327
11539
  * @param {string} _id
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2019/11/19
8
- * Revised : 2024/04/15 (v36.0.0)
8
+ * Revised : 2024/05/01 (v36.2.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -198,7 +198,7 @@ const updateWindowSiz = _ => {
198
198
  difCover: { x: 25, y: 60, w: 140, h: 261 + g_sHeight - 500, opacity: 0.95 },
199
199
  difFilter: { x: 0, y: 61, w: 140, h: 200 + g_sHeight - 500, overflow: `auto` },
200
200
  displaySprite: { x: 25, y: 30, w: (g_sWidth - 450) / 2, h: g_limitObj.setLblHeight * 5 },
201
- scoreDetail: { x: 20, y: 85, w: (g_sWidth - 500) / 2 + 420, h: 236, visibility: `hidden` },
201
+ scoreDetail: { x: 20, y: 85, w: (g_sWidth - 500) / 2 + 420, h: 240, visibility: `hidden` },
202
202
  detailObj: { w: (g_sWidth - 500) / 2 + 420, h: 230, visibility: `hidden` },
203
203
  keyconSprite: { y: 88, h: g_sHeight - 85, overflow: `auto` },
204
204
  loader: { y: g_sHeight - 10, h: 10, backgroundColor: `#333333` },
@@ -307,7 +307,13 @@ const updateWindowSiz = _ => {
307
307
  x: 140, y: 70, w: (g_sWidth - 500) / 2 + 275, h: 150, overflow: `auto`,
308
308
  },
309
309
  lnkDifInfo: {
310
- w: g_limitObj.difCoverWidth, borderStyle: `solid`,
310
+ w: g_limitObj.difCoverWidth, h: 20, borderStyle: `solid`,
311
+ },
312
+ lnkHighScore: {
313
+ w: g_limitObj.difCoverWidth, h: 20, borderStyle: `solid`,
314
+ },
315
+ lblHRank: {
316
+ x: 290, y: 145, w: 120, h: 20, siz: 50, align: C_ALIGN_CENTER,
311
317
  },
312
318
 
313
319
  /** ディスプレイ画面 */
@@ -966,7 +972,7 @@ const g_settings = {
966
972
 
967
973
  opacitys: [10, 25, 50, 75, 100],
968
974
 
969
- scoreDetailDefs: [`Density`, `Speed`, `ToolDif`],
975
+ scoreDetailDefs: [`Density`, `Speed`, `ToolDif`, `HighScore`],
970
976
  scoreDetails: [],
971
977
  scoreDetailCursors: [],
972
978
 
@@ -1535,12 +1541,17 @@ const g_shortcutObj = {
1535
1541
  Digit1: { id: `lnkDensityG` },
1536
1542
  Digit2: { id: `lnkSpeedG` },
1537
1543
  Digit3: { id: `lnkToolDifG` },
1544
+ Digit4: { id: `lnkHighScoreG` },
1538
1545
  Numpad1: { id: `lnkDensityG` },
1539
1546
  Numpad2: { id: `lnkSpeedG` },
1540
1547
  Numpad3: { id: `lnkToolDifG` },
1548
+ Numpad4: { id: `lnkHighScoreG` },
1541
1549
  KeyQ: { id: `lnkDensityG` },
1542
1550
  KeyP: { id: `lnkDifInfo` },
1543
1551
  KeyZ: { id: `btnSave` },
1552
+ ControlLeft_KeyC: { id: `` },
1553
+ ControlRight_KeyC: { id: `` },
1554
+ KeyC: { id: `lnkHighScore`, reset: true },
1544
1555
 
1545
1556
  Escape: { id: `btnBack` },
1546
1557
  Space: { id: `btnKeyConfig` },
@@ -1563,11 +1574,16 @@ const g_shortcutObj = {
1563
1574
  Digit1: { id: `lnkDensityG` },
1564
1575
  Digit2: { id: `lnkSpeedG` },
1565
1576
  Digit3: { id: `lnkToolDifG` },
1577
+ Digit4: { id: `lnkHighScoreG` },
1566
1578
  Numpad1: { id: `lnkDensityG` },
1567
1579
  Numpad2: { id: `lnkSpeedG` },
1568
1580
  Numpad3: { id: `lnkToolDifG` },
1581
+ Numpad4: { id: `lnkHighScoreG` },
1569
1582
  KeyQ: { id: `lnkDensityG` },
1570
1583
  KeyP: { id: `lnkDifInfo` },
1584
+ ControlLeft_KeyC: { id: `` },
1585
+ ControlRight_KeyC: { id: `` },
1586
+ KeyC: { id: `lnkHighScore`, reset: true },
1571
1587
 
1572
1588
  Escape: { id: `btnBack` },
1573
1589
  Space: { id: `btnKeyConfig` },
@@ -2754,7 +2770,7 @@ const g_lang_msgInfoObj = {
2754
2770
  E_0103: `新しいキー:{0}の[stepRtn]が未定義です。(E-0103)<br>
2755
2771
  |stepRtn{0}=0,45,-90,135,180,onigiri|`,
2756
2772
  E_0104: `新しいキー:{0}の[keyCtrl]が未定義です。(E-0104)<br>
2757
- |keyCtrl{0}=75,79,76,80,187,32/0|`,
2773
+ |keyCtrl{0}=S,D,E/R,F,Space,J,M/Comma,K,L|`,
2758
2774
 
2759
2775
  E_0201: `色変化データで指定した色変化対象が存在しません。[pattern={0}] (E-0201)`,
2760
2776
 
@@ -2803,7 +2819,7 @@ const g_lang_msgInfoObj = {
2803
2819
  E_0103: `New key: {0} [stepRtn] is not set. (E-0103)<br>
2804
2820
  |stepRtn{0}=0,45,-90,135,180,onigiri|`,
2805
2821
  E_0104: `New key: {0} [keyCtrl] is not set. (E-0104)<br>
2806
- |keyCtrl{0}=75,79,76,80,187,32/0|`,
2822
+ |keyCtrl{0}=S,D,E/R,F,Space,J,M/Comma,K,L|`,
2807
2823
 
2808
2824
  E_0201: `The color change target specified in the color change data does not exist. [pattern={0}] (E-0201)`,
2809
2825
 
@@ -2977,6 +2993,7 @@ const g_lblNameObj = {
2977
2993
  'u_Speed': `Velocity`,
2978
2994
  'u_Density': `Density`,
2979
2995
  'u_ToolDif': `DifLevel`,
2996
+ 'u_HighScore': `HighScore`,
2980
2997
 
2981
2998
  'u_Main': `Main`,
2982
2999
  'u_Replaced': `Replaced`,
@@ -3049,6 +3066,8 @@ const g_lang_lblNameObj = {
3049
3066
  s_cnts: `All Arrows`,
3050
3067
  s_linecnts: `- 矢印 Arrow:<br><br>- 氷矢 Frz:<br><br>- 3つ押し位置 ({0}):`,
3051
3068
  s_print: `データ出力`,
3069
+ s_result: `CopyResult`,
3070
+ s_resetResult: `Reset`,
3052
3071
  s_printTitle: `Dancing☆Onigiri レベル計算ツール+++`,
3053
3072
  s_printHeader: `難易度\t同時\t縦連\t総数\t矢印\t氷矢印\tAPM\t時間`,
3054
3073
 
@@ -3086,6 +3105,8 @@ const g_lang_lblNameObj = {
3086
3105
  s_cnts: `All Arrows`,
3087
3106
  s_linecnts: `- Arrow:<br><br>- Freeze Arrow:<br><br>- Polychord positions ({0}):`,
3088
3107
  s_print: `CopyData`,
3108
+ s_result: `CopyResult`,
3109
+ s_resetResult: `Reset`,
3089
3110
  s_printTitle: `Dancing☆Onigiri Level Calculator+++`,
3090
3111
  s_printHeader: `Level\tChords\tJack\tAll\tArrow\tFrz\tAPM\tTime`,
3091
3112
 
@@ -3127,8 +3148,9 @@ const g_lang_msgObj = {
3127
3148
  github: `Dancing☆Onigiri (CW Edition)のGitHubページへ移動します。`,
3128
3149
  security: `Dancing☆Onigiri (CW Edition)のサポート情報ページへ移動します。`,
3129
3150
 
3130
- dataResetConfirm: `この作品のローカル設定をクリアします。よろしいですか?\n(ハイスコアやAdjustment等のデータがクリアされます)`,
3151
+ dataResetConfirm: `この作品のローカル設定をクリアします。よろしいですか?\n(ハイスコアやAdjustment等のデータが全てクリアされます)`,
3131
3152
  keyResetConfirm: `キーを初期配置に戻します。よろしいですか?`,
3153
+ highscResetConfirm: `この譜面のハイスコアを消去します。よろしいですか?`,
3132
3154
  colorCopyConfirm: `フリーズアローの配色を矢印色に置き換えます\n(通常・ヒット時双方を置き換えます)。よろしいですか?`,
3133
3155
 
3134
3156
  difficulty: `譜面を選択します。`,
@@ -3186,6 +3208,7 @@ const g_lang_msgObj = {
3186
3208
 
3187
3209
  dataResetConfirm: `Delete the local settings in this game. Is it OK?\n(High score, adjustment, volume and some settings will be initialized)`,
3188
3210
  keyResetConfirm: `Resets the assigned key to the initial state. Is it OK?`,
3211
+ highscResetConfirm: `Erases the high score for this chart. Is it OK?`,
3189
3212
  colorCopyConfirm: `Replace freeze arrow color scheme with arrow color\n(replace both normal and hit). Is this OK?`,
3190
3213
 
3191
3214
  difficulty: `Select a chart.`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "danoniplus",
3
- "version": "36.1.0",
3
+ "version": "36.2.0",
4
4
  "description": "Dancing☆Onigiri (CW Edition) - Web-based Rhythm Game",
5
5
  "main": "index.js",
6
6
  "scripts": {