danoniplus 24.6.6 → 25.5.7

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
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 24.6.6`;
11
+ const g_version = `Ver 25.5.7`;
12
12
  const g_revisedDate = `2022/04/10`;
13
13
  const g_alphaVersion = ``;
14
14
 
@@ -231,6 +231,15 @@ const hasValInArray = (_val, _array, _pos = 0) =>
231
231
  */
232
232
  const hasArrayList = (_data, _length = 1) => _data !== undefined && _data.length >= _length;
233
233
 
234
+ /**
235
+ * 重複を排除した配列の生成
236
+ * @param {array} _array1
237
+ * @param {array} _array2
238
+ * @returns
239
+ */
240
+ const makeDedupliArray = (_array1, _array2) =>
241
+ Array.from((new Set([..._array1, ..._array2])).values());
242
+
234
243
  /**
235
244
  * 部分一致検索(リストのいずれかに合致、大小文字問わず)
236
245
  * @param {string} _str 検索文字
@@ -569,28 +578,34 @@ function getFontSize(_str, _maxWidth, _font = getBasicFont(), _maxFontsize = 64,
569
578
 
570
579
  /**
571
580
  * クリップボードコピー関数
572
- * 入力値をクリップボードへコピーする
581
+ * 入力値をクリップボードへコピーし、メッセージを表示
573
582
  * @param {string} _textVal 入力値
583
+ * @param {string} _msg
574
584
  */
575
- function copyTextToClipboard(_textVal) {
576
- // テキストエリアを用意する
577
- const copyFrom = document.createElement(`textarea`);
578
- // テキストエリアへ値をセット
579
- copyFrom.textContent = _textVal;
585
+ async function copyTextToClipboard(_textVal, _msg) {
586
+ try {
587
+ await navigator.clipboard.writeText(_textVal);
580
588
 
581
- // bodyタグの要素を取得
582
- const bodyElm = document.getElementsByTagName(`body`)[0];
583
- // 子要素にテキストエリアを配置
584
- bodyElm.appendChild(copyFrom);
589
+ } catch (error) {
590
+ // http環境では navigator.clipboard が使えないため、従来の方法を実行
591
+ // テキストエリアを用意し、値をセット
592
+ const copyFrom = document.createElement(`textarea`);
593
+ copyFrom.textContent = _textVal;
585
594
 
586
- // テキストエリアの値を選択
587
- copyFrom.select();
588
- // コピーコマンド発行
589
- const retVal = document.execCommand(`copy`);
590
- // 追加テキストエリアを削除
591
- bodyElm.removeChild(copyFrom);
592
- // 処理結果を返却
593
- return retVal;
595
+ // bodyタグの要素を取得
596
+ const bodyElm = document.getElementsByTagName(`body`)[0];
597
+ // 子要素にテキストエリアを配置
598
+ bodyElm.appendChild(copyFrom);
599
+
600
+ // テキストエリアの値を選択し、コピーコマンド発行
601
+ copyFrom.select();
602
+ document.execCommand(`copy`);
603
+ // 追加テキストエリアを削除
604
+ bodyElm.removeChild(copyFrom);
605
+
606
+ } finally {
607
+ makeInfoWindow(_msg, `leftToRightFade`);
608
+ }
594
609
  }
595
610
 
596
611
  /**
@@ -1145,6 +1160,10 @@ function makeSpriteData(_data, _calcFrame = _frame => _frame) {
1145
1160
  };
1146
1161
  if (g_headerObj.autoPreload) {
1147
1162
  if (checkImage(tmpObj.path)) {
1163
+ if (g_headerObj.syncBackPath) {
1164
+ const [file, dir] = getFilePath(tmpObj.path, `./`);
1165
+ tmpObj.path = `${dir}${file}`;
1166
+ }
1148
1167
  preloadFile(`image`, tmpObj.path);
1149
1168
  }
1150
1169
  }
@@ -1159,6 +1178,7 @@ function makeSpriteData(_data, _calcFrame = _frame => _frame) {
1159
1178
  command: tmpObj.path,
1160
1179
  jumpFrame: tmpObj.class,
1161
1180
  maxLoop: tmpObj.left,
1181
+ animationName: tmpObj.animationName,
1162
1182
  htmlText: emptyPatterns.includes(tmpObj.path) ?
1163
1183
  `` : (checkImage(tmpObj.path) ? makeSpriteImage(tmpObj) : makeSpriteText(tmpObj)),
1164
1184
  };
@@ -1466,19 +1486,13 @@ function initAfterDosLoaded() {
1466
1486
  if (document.querySelector(`#layer0`) === null) {
1467
1487
  divRoot.removeChild(document.querySelector(`#divBack`));
1468
1488
  createEmptySprite(divRoot, `divBack`);
1469
- } else if (g_headerObj.skinType !== `default` && !g_headerObj.customBackUse) {
1489
+ } else if (!g_headerObj.defaultSkinFlg && !g_headerObj.customBackUse) {
1470
1490
  createEmptySprite(divRoot, `divBack`);
1471
1491
  }
1472
1492
 
1473
1493
  // CSSファイルの読み込み
1474
- const randTime = new Date().getTime();
1475
- importCssFile(`${g_headerObj.skinRoot}danoni_skin_${g_headerObj.skinType}.css?${randTime}`, _ => {
1476
- if (g_headerObj.skinType2 !== ``) {
1477
- importCssFile(`${g_headerObj.skinRoot2}danoni_skin_${g_headerObj.skinType2}.css?${randTime}`, _ => initAfterCssLoaded());
1478
- } else {
1479
- initAfterCssLoaded();
1480
- }
1481
- });
1494
+ const skinList = g_headerObj.jsData.filter(file => file[0].indexOf(`danoni_skin`) !== -1);
1495
+ loadMultipleFiles(0, skinList, `css`, _ => initAfterCssLoaded());
1482
1496
 
1483
1497
  /**
1484
1498
  * スキンCSSファイルを読み込んだ後の処理
@@ -1543,10 +1557,9 @@ function initAfterDosLoaded() {
1543
1557
 
1544
1558
  if (g_loadObj.main) {
1545
1559
  // customjsの読み込み後、譜面詳細情報取得のために譜面をロード
1546
- loadCustomjs(_ => {
1547
- loadDos(_ => {
1548
- getScoreDetailData(0);
1549
- }, 0, true);
1560
+ loadMultipleFiles(0, g_headerObj.jsData, `js`, _ => {
1561
+ loadLegacyCustomFunc();
1562
+ loadDos(_ => getScoreDetailData(0), 0, true);
1550
1563
  });
1551
1564
  } else {
1552
1565
  getScoreDetailData(0);
@@ -1797,20 +1810,31 @@ function calcLevel(_scoreObj) {
1797
1810
  }
1798
1811
 
1799
1812
  /**
1800
- * customjsの読込
1813
+ * jsファイルの連続読込
1814
+ * @param {number} _j
1815
+ * @param {array} _fileData
1816
+ * @param {string} _loadType
1801
1817
  * @param {function} _afterFunc
1802
1818
  */
1803
- function loadCustomjs(_afterFunc) {
1804
- const randTime = new Date().getTime();
1805
- loadScript(`${g_headerObj.customjsRoot}${g_headerObj.customjs}?${randTime}`, _ => {
1806
- loadScript(`${g_headerObj.customjs2Root}${g_headerObj.customjs2}?${randTime}`, _ => {
1807
- loadScript(`${g_headerObj.skinRoot}danoni_skin_${g_headerObj.skinType}.js?${randTime}`, _ => {
1808
- loadScript(`${g_headerObj.skinRoot2}danoni_skin_${g_headerObj.skinType2}.js?${randTime}`, _ => {
1809
- _afterFunc();
1810
- }, false);
1811
- }, false);
1812
- }, false);
1813
- }, false);
1819
+ function loadMultipleFiles(_j, _fileData, _loadType, _afterFunc = _ => true) {
1820
+ if (_j < _fileData.length) {
1821
+ const filePath = `${_fileData[_j][1]}${_fileData[_j][0]}?${new Date().getTime()}`;
1822
+ if (_fileData[_j][0].endsWith(`.css`)) {
1823
+ _loadType = `css`;
1824
+ }
1825
+
1826
+ // jsファイル、cssファイルにより呼び出す関数を切替
1827
+ if (_loadType === `js`) {
1828
+ loadScript(filePath, _ =>
1829
+ loadMultipleFiles(_j + 1, _fileData, _loadType, _afterFunc), false);
1830
+ } else if (_loadType === `css`) {
1831
+ const cssPath = filePath.split(`.js`).join(`.css`);
1832
+ importCssFile(cssPath, _ =>
1833
+ loadMultipleFiles(_j + 1, _fileData, _loadType, _afterFunc));
1834
+ }
1835
+ } else {
1836
+ _afterFunc();
1837
+ }
1814
1838
  }
1815
1839
 
1816
1840
  /**
@@ -1916,12 +1940,7 @@ function loadMusic() {
1916
1940
  lblLoading.textContent = `${g_lblNameObj.nowLoading} ${_event.loaded}Bytes`;
1917
1941
  }
1918
1942
  // ユーザカスタムイベント
1919
- if (typeof customLoadingProgress === C_TYP_FUNCTION) {
1920
- customLoadingProgress(_event);
1921
- if (typeof customLoadingProgress2 === C_TYP_FUNCTION) {
1922
- customLoadingProgress2(_event);
1923
- }
1924
- }
1943
+ g_customJsObj.progress.forEach(func => func(_event));
1925
1944
  });
1926
1945
 
1927
1946
  // エラー処理
@@ -2032,7 +2051,7 @@ function drawDefaultBackImage(_key) {
2032
2051
  l0ctx.fillStyle = grd;
2033
2052
  l0ctx.fillRect(0, 0, g_sWidth, g_sHeight);
2034
2053
 
2035
- if (g_headerObj.skinType !== `default`) {
2054
+ if (!g_headerObj.defaultSkinFlg) {
2036
2055
  createEmptySprite(divRoot, `divBack`);
2037
2056
  }
2038
2057
  }
@@ -2257,7 +2276,7 @@ function drawTitleResultMotion(_displayName) {
2257
2276
  * ショートカットキー表示
2258
2277
  * @param {object} _obj
2259
2278
  * @param {string} _settingLabel
2260
- * @param {object} objectList
2279
+ * @param {object} objectList
2261
2280
  */
2262
2281
  const createScText = (_obj, _settingLabel, { displayName = `option`, dfLabel = ``, targetLabel = `lnk${_settingLabel}R`,
2263
2282
  x = g_scViewObj.x, y = g_scViewObj.y, w = g_scViewObj.w, siz = g_scViewObj.siz } = {}) => {
@@ -2446,12 +2465,7 @@ function titleInit() {
2446
2465
  }
2447
2466
 
2448
2467
  // ユーザカスタムイベント(初期)
2449
- if (typeof customTitleInit === C_TYP_FUNCTION) {
2450
- customTitleInit();
2451
- if (typeof customTitleInit2 === C_TYP_FUNCTION) {
2452
- customTitleInit2();
2453
- }
2454
- }
2468
+ g_customJsObj.title.forEach(func => func());
2455
2469
 
2456
2470
  // バージョン情報取得
2457
2471
  let customVersion = ``;
@@ -2584,12 +2598,7 @@ function titleInit() {
2584
2598
  function flowTitleTimeline() {
2585
2599
 
2586
2600
  // ユーザカスタムイベント(フレーム毎)
2587
- if (typeof customTitleEnterFrame === C_TYP_FUNCTION) {
2588
- customTitleEnterFrame();
2589
- if (typeof customTitleEnterFrame2 === C_TYP_FUNCTION) {
2590
- customTitleEnterFrame2();
2591
- }
2592
- }
2601
+ g_customJsObj.titleEnterFrame.forEach(func => func());
2593
2602
 
2594
2603
  // 背景・マスクモーション
2595
2604
  drawTitleResultMotion(g_currentPage);
@@ -2611,12 +2620,7 @@ function titleInit() {
2611
2620
  document.oncontextmenu = _ => true;
2612
2621
  divRoot.oncontextmenu = _ => false;
2613
2622
 
2614
- if (typeof skinTitleInit === C_TYP_FUNCTION) {
2615
- skinTitleInit();
2616
- if (typeof skinTitleInit2 === C_TYP_FUNCTION) {
2617
- skinTitleInit2();
2618
- }
2619
- }
2623
+ g_skinJsObj.title.forEach(func => func());
2620
2624
  }
2621
2625
 
2622
2626
  /**
@@ -2649,8 +2653,8 @@ function makeWarningWindow(_text = ``, { resetFlg = false, backBtnUse = false }
2649
2653
  * お知らせウィンドウ(汎用)を表示
2650
2654
  * @param {string} _text
2651
2655
  */
2652
- function makeInfoWindow(_text, _animationName = ``) {
2653
- const lblWarning = setWindowStyle(`<p>${_text}</p>`, `#ccccff`, `#000066`, C_ALIGN_CENTER);
2656
+ function makeInfoWindow(_text, _animationName = ``, _backColor = `#ccccff`) {
2657
+ const lblWarning = setWindowStyle(`<p>${_text}</p>`, _backColor, `#000066`, C_ALIGN_CENTER);
2654
2658
  lblWarning.style.pointerEvents = C_DIS_NONE;
2655
2659
 
2656
2660
  if (_animationName !== ``) {
@@ -2664,7 +2668,7 @@ function makeInfoWindow(_text, _animationName = ``) {
2664
2668
 
2665
2669
  /**
2666
2670
  * 警告ウィンドウのスタイル設定
2667
- * @param {string} _text
2671
+ * @param {string} _text
2668
2672
  * @param {string} _bkColor
2669
2673
  * @param {string} _textColor
2670
2674
  * @param {string} _align
@@ -2750,17 +2754,30 @@ function preheaderConvert(_dosObj) {
2750
2754
  // ヘッダー群の格納先
2751
2755
  const obj = {};
2752
2756
 
2757
+ obj.jsData = [];
2758
+
2759
+ const setJsFiles = (_files, _defaultDir, _type = `custom`) => {
2760
+ _files.forEach(file => {
2761
+ if (hasVal(file)) {
2762
+ const [jsFile, jsDir] = getFilePath(file, _defaultDir);
2763
+ obj.jsData.push([_type === `skin` ? `danoni_skin_${jsFile}.js` : jsFile, jsDir]);
2764
+ }
2765
+ });
2766
+ };
2767
+
2753
2768
  // 外部スキンファイルの指定
2754
2769
  const tmpSkinType = _dosObj.skinType || (typeof g_presetSkinType === C_TYP_STRING ? g_presetSkinType : `default`);
2755
- const skinTypes = tmpSkinType.split(`,`);
2756
- [obj.skinType2, obj.skinRoot2] = getFilePath(skinTypes.length > 1 ? skinTypes[1] : `blank`, C_DIR_SKIN);
2757
- [obj.skinType, obj.skinRoot] = getFilePath(skinTypes[0], C_DIR_SKIN);
2770
+ const tmpSkinTypes = tmpSkinType.split(`,`);
2771
+ obj.defaultSkinFlg = tmpSkinTypes.includes(`default`);
2772
+ setJsFiles(tmpSkinTypes, C_DIR_SKIN, `skin`);
2758
2773
 
2759
2774
  // 外部jsファイルの指定
2760
2775
  const tmpCustomjs = _dosObj.customjs || (typeof g_presetCustomJs === C_TYP_STRING ? g_presetCustomJs : C_JSF_CUSTOM);
2761
- const customjss = tmpCustomjs.split(`,`);
2762
- [obj.customjs2, obj.customjs2Root] = getFilePath(customjss.length > 1 ? customjss[1] : C_JSF_BLANK, C_DIR_JS);
2763
- [obj.customjs, obj.customjsRoot] = getFilePath(customjss[0], C_DIR_JS);
2776
+ setJsFiles(tmpCustomjs.split(`,`), C_DIR_JS);
2777
+
2778
+ // 外部cssファイルの指定
2779
+ const tmpCustomcss = _dosObj.customcss || (typeof g_presetCustomCss === C_TYP_STRING ? g_presetCustomCss : ``);
2780
+ setJsFiles(tmpCustomcss.split(`,`), C_DIR_CSS);
2764
2781
 
2765
2782
  // デフォルト曲名表示、背景、Ready表示の利用有無
2766
2783
  g_titleLists.init.forEach(objName => {
@@ -2770,6 +2787,10 @@ function preheaderConvert(_dosObj) {
2770
2787
  setVal(g_presetCustomDesignUse[objName], false, C_TYP_BOOLEAN) : false), C_TYP_BOOLEAN);
2771
2788
  });
2772
2789
 
2790
+ // 背景・マスクモーションのパス指定方法を他の設定に合わせる設定
2791
+ const tmpSyncBackPath = (typeof g_presetSyncBackPath === C_TYP_BOOLEAN ? g_presetSyncBackPath : false);
2792
+ obj.syncBackPath = setVal(_dosObj.syncBackPath, tmpSyncBackPath, C_TYP_BOOLEAN);
2793
+
2773
2794
  return obj;
2774
2795
  }
2775
2796
 
@@ -3042,6 +3063,22 @@ function headerConvert(_dosObj) {
3042
3063
  obj.defaultFrzColorUse = true;
3043
3064
  }
3044
3065
 
3066
+ // 矢印色変化に対応してフリーズアロー色を追随する範囲の設定
3067
+ // (defaultFrzColorUse=false時のみ)
3068
+ obj.frzScopeFromArrowColors = [];
3069
+
3070
+ if (!obj.defaultFrzColorUse) {
3071
+ const tmpFrzScope = [];
3072
+
3073
+ if (hasVal(_dosObj.frzScopeFromAC)) {
3074
+ tmpFrzScope.push(..._dosObj.frzScopeFromAC.split(`,`));
3075
+ } else if (typeof g_presetFrzScopeFromAC === C_TYP_OBJECT) {
3076
+ tmpFrzScope.push(...g_presetFrzScopeFromAC);
3077
+ }
3078
+ tmpFrzScope.filter(type => [`Normal`, `Hit`].includes(type))
3079
+ .forEach(data => obj.frzScopeFromArrowColors.push(data));
3080
+ }
3081
+
3045
3082
  // 初期色情報
3046
3083
  Object.keys(g_dfColorObj).forEach(key => obj[key] = g_dfColorObj[key].concat());
3047
3084
  if (obj.baseBrightFlg) {
@@ -3392,6 +3429,23 @@ function headerConvert(_dosObj) {
3392
3429
  obj.resultFormat = escapeHtmlForEnabledTag(setVal(_dosObj.resultFormat, (typeof g_presetResultFormat === C_TYP_STRING ?
3393
3430
  setVal(g_presetResultFormat, resultFormatDefault, C_TYP_STRING) : resultFormatDefault), C_TYP_STRING));
3394
3431
 
3432
+ // フェードイン時にそれ以前のデータを蓄積しない種別(word, back, mask)を指定
3433
+ obj.unStockCategories = setVal(_dosObj.unStockCategory, ``, C_TYP_STRING).split(`,`);
3434
+ if (typeof g_presetUnStockCategories === C_TYP_OBJECT) {
3435
+ obj.unStockCategories = makeDedupliArray(obj.unStockCategories, g_presetUnStockCategories);
3436
+ }
3437
+ g_fadeinStockList = g_fadeinStockList.filter(cg => obj.unStockCategories.indexOf(cg) === -1);
3438
+
3439
+ // フェードイン時にそれ以前のデータを蓄積しないパターンを指定
3440
+ if (typeof g_presetStockForceDelList === C_TYP_OBJECT) {
3441
+ Object.assign(g_stockForceDelList, g_presetStockForceDelList);
3442
+ }
3443
+ g_fadeinStockList.forEach(type => {
3444
+ if (hasVal(_dosObj[`${type}StockForceDel`])) {
3445
+ g_stockForceDelList[type] = makeDedupliArray(g_stockForceDelList[type], _dosObj[`${type}StockForceDel`].split(`,`));
3446
+ }
3447
+ });
3448
+
3395
3449
  return obj;
3396
3450
  }
3397
3451
 
@@ -3476,8 +3530,8 @@ function resetBaseColorList(_baseObj, _dosObj, { scoreId = `` } = {}) {
3476
3530
  * 矢印・フリーズアロー色のデータ展開
3477
3531
  * @param {string} _data
3478
3532
  * @param {array} _colorInit
3479
- * @param {array} _colorInitLength
3480
- * @param {object} objectList
3533
+ * @param {number} _colorInitLength
3534
+ * @param {object} objectList
3481
3535
  */
3482
3536
  function setColorList(_data, _colorInit, _colorInitLength,
3483
3537
  { _defaultColorgrd = g_headerObj.defaultColorgrd, _colorCdPaddingUse = false,
@@ -3924,7 +3978,7 @@ const commonSettingBtn = _labelName => {
3924
3978
  createCss2Button(`btn${_labelName}`, `>`, _ => true, {
3925
3979
  x: g_sWidth / 2 + 175 - C_LEN_SETMINI_WIDTH / 2, y: 25,
3926
3980
  w: C_LEN_SETMINI_WIDTH, h: 40, title: g_msgObj[`to${_labelName}`],
3927
- resetFunc: _ => (_labelName === `Display` ? settingsDisplayInit() : optionInit()),
3981
+ resetFunc: _ => g_jumpSettingWindow[g_currentPage](),
3928
3982
  }, g_cssObj.button_Mini),
3929
3983
 
3930
3984
  // データセーブフラグの切替
@@ -3953,12 +4007,7 @@ function optionInit() {
3953
4007
  createOptionWindow(divRoot);
3954
4008
 
3955
4009
  // ユーザカスタムイベント(初期)
3956
- if (typeof customOptionInit === C_TYP_FUNCTION) {
3957
- customOptionInit();
3958
- if (typeof customOptionInit2 === C_TYP_FUNCTION) {
3959
- customOptionInit2();
3960
- }
3961
- }
4010
+ g_customJsObj.option.forEach(func => func());
3962
4011
 
3963
4012
  // ボタン描画
3964
4013
  commonSettingBtn(`Display`);
@@ -3968,12 +4017,7 @@ function optionInit() {
3968
4017
  document.oncontextmenu = _ => true;
3969
4018
  g_initialFlg = true;
3970
4019
 
3971
- if (typeof skinOptionInit === C_TYP_FUNCTION) {
3972
- skinOptionInit();
3973
- if (typeof skinOptionInit2 === C_TYP_FUNCTION) {
3974
- skinOptionInit2();
3975
- }
3976
- }
4020
+ g_skinJsObj.option.forEach(func => func());
3977
4021
  }
3978
4022
 
3979
4023
  function musicAfterLoaded() {
@@ -4022,6 +4066,18 @@ const createOptionSprite = _sprite => createEmptySprite(_sprite, `optionsprite`,
4022
4066
  x: (g_sWidth - 450) / 2, y: 65 + (g_sHeight - 500) / 2, w: 450, h: 325,
4023
4067
  });
4024
4068
 
4069
+ /**
4070
+ * スライダー共通処理
4071
+ * @param {object} _slider
4072
+ * @param {object} _link
4073
+ * @returns
4074
+ */
4075
+ const inputSlider = (_slider, _link) => {
4076
+ const value = parseInt(_slider.value);
4077
+ _link.textContent = `${value}${g_lblNameObj.percent}`;
4078
+ return value;
4079
+ }
4080
+
4025
4081
  /**
4026
4082
  * 設定・オプション画面のラベル・ボタン処理の描画
4027
4083
  * @param {Object} _sprite 基準とするスプライト(ここで指定する座標は、そのスプライトからの相対位置)
@@ -4210,7 +4266,7 @@ function createOptionWindow(_sprite) {
4210
4266
  // 縦位置: 2 短縮ショートカットあり
4211
4267
  createGeneralSetting(spriteList.speed, `speed`, {
4212
4268
  skipTerms: [20, 5, 1], hiddenBtn: true, scLabel: g_lblNameObj.sc_speed, roundNum: 5,
4213
- unitName: ` ${getStgDetailName(g_lblNameObj.multi)}`,
4269
+ unitName: ` ${g_lblNameObj.multi}`,
4214
4270
  });
4215
4271
 
4216
4272
  if (g_headerObj.scoreDetailUse) {
@@ -4521,9 +4577,8 @@ function createOptionWindow(_sprite) {
4521
4577
  makeSettingLblCssButton(`lnkDifInfo`, g_lblNameObj.s_print, 0, _ => {
4522
4578
  copyTextToClipboard(
4523
4579
  `****** ${g_lblNameObj.s_printTitle} [${g_version}] ******\r\n\r\n`
4524
- + `\t${g_lblNameObj.s_printHeader}\r\n\r\n${printData}`
4580
+ + `\t${g_lblNameObj.s_printHeader}\r\n\r\n${printData}`, g_msgInfoObj.I_0003
4525
4581
  );
4526
- makeInfoWindow(g_msgInfoObj.I_0003, `leftToRightFade`);
4527
4582
  }, {
4528
4583
  x: 10, y: 30, w: 100, borderStyle: `solid`
4529
4584
  }, g_cssObj.button_RevON),
@@ -4799,7 +4854,7 @@ function createOptionWindow(_sprite) {
4799
4854
  // 縦位置: 10 短縮ショートカットあり
4800
4855
  createGeneralSetting(spriteList.adjustment, `adjustment`, {
4801
4856
  skipTerms: [50, 10, 5], hiddenBtn: true, scLabel: g_lblNameObj.sc_adjustment, roundNum: 5,
4802
- unitName: `${getStgDetailName(g_lblNameObj.frame)}`,
4857
+ unitName: g_lblNameObj.frame,
4803
4858
  });
4804
4859
 
4805
4860
  // ---------------------------------------------------
@@ -4807,7 +4862,7 @@ function createOptionWindow(_sprite) {
4807
4862
  // 縦位置: 11 スライダーあり
4808
4863
  spriteList.fadein.appendChild(createLblSetting(`Fadein`));
4809
4864
 
4810
- const lnkFadein = createDivCss2Label(`lnkFadein`, `${g_stateObj.fadein}${getStgDetailName(g_lblNameObj.percent)}`, {
4865
+ const lnkFadein = createDivCss2Label(`lnkFadein`, `${g_stateObj.fadein}${g_lblNameObj.percent}`, {
4811
4866
  x: C_LEN_SETLBL_LEFT, y: 0,
4812
4867
  }, g_cssObj.settings_FadeinBar);
4813
4868
  spriteList.fadein.appendChild(lnkFadein);
@@ -4815,7 +4870,7 @@ function createOptionWindow(_sprite) {
4815
4870
  const setFadein = _sign => {
4816
4871
  g_stateObj.fadein = nextPos(g_stateObj.fadein, _sign, 100);
4817
4872
  fadeinSlider.value = g_stateObj.fadein;
4818
- lnkFadein.textContent = `${g_stateObj.fadein}${getStgDetailName(g_lblNameObj.percent)}`;
4873
+ lnkFadein.textContent = `${g_stateObj.fadein}${g_lblNameObj.percent}`;
4819
4874
  };
4820
4875
 
4821
4876
  multiAppend(spriteList.fadein,
@@ -4832,15 +4887,13 @@ function createOptionWindow(_sprite) {
4832
4887
  )
4833
4888
 
4834
4889
  const fadeinSlider = document.querySelector(`#fadeinSlider`);
4835
- fadeinSlider.addEventListener(`input`, _ => {
4836
- g_stateObj.fadein = parseInt(fadeinSlider.value);
4837
- lnkFadein.textContent = `${g_stateObj.fadein}${getStgDetailName(g_lblNameObj.percent)}`;
4838
- }, false);
4890
+ fadeinSlider.addEventListener(`input`, _ =>
4891
+ g_stateObj.fadein = inputSlider(fadeinSlider, lnkFadein), false);
4839
4892
 
4840
4893
  // ---------------------------------------------------
4841
4894
  // ボリューム (Volume)
4842
4895
  // 縦位置: 12
4843
- createGeneralSetting(spriteList.volume, `volume`, { unitName: getStgDetailName(g_lblNameObj.percent) });
4896
+ createGeneralSetting(spriteList.volume, `volume`, { unitName: g_lblNameObj.percent });
4844
4897
 
4845
4898
  /**
4846
4899
  * 譜面初期化処理
@@ -4961,7 +5014,7 @@ function createOptionWindow(_sprite) {
4961
5014
 
4962
5015
  // 譜面名設定 (Difficulty)
4963
5016
  const difWidth = parseFloat(lnkDifficulty.style.width);
4964
- const difNames = [`${getKeyName(g_keyObj.currentKey)} key / ${g_headerObj.difLabels[g_stateObj.scoreId]}`];
5017
+ const difNames = [`${getKeyName(g_keyObj.currentKey)} ${getStgDetailName('key')} / ${g_headerObj.difLabels[g_stateObj.scoreId]}`];
4965
5018
  lnkDifficulty.style.fontSize = `${getFontSize(difNames[0], difWidth, getBasicFont(), C_SIZ_SETLBL)}px`;
4966
5019
 
4967
5020
  if (g_headerObj.makerView) {
@@ -4974,7 +5027,7 @@ function createOptionWindow(_sprite) {
4974
5027
  lnkDifficulty.innerHTML = difNames.join(``);
4975
5028
 
4976
5029
  // 速度設定 (Speed)
4977
- setSetting(0, `speed`, ` ${getStgDetailName(g_lblNameObj.multi)}`);
5030
+ setSetting(0, `speed`, ` ${g_lblNameObj.multi}`);
4978
5031
  if (g_headerObj.scoreDetailUse) {
4979
5032
  drawSpeedGraph(g_stateObj.scoreId);
4980
5033
  drawDensityGraph(g_stateObj.scoreId);
@@ -5009,12 +5062,7 @@ function createOptionWindow(_sprite) {
5009
5062
  setGauge(0);
5010
5063
 
5011
5064
  // ユーザカスタムイベント(初期)
5012
- if (typeof customSetDifficulty === C_TYP_FUNCTION) {
5013
- customSetDifficulty(_initFlg, g_canLoadDifInfoFlg);
5014
- if (typeof customSetDifficulty2 === C_TYP_FUNCTION) {
5015
- customSetDifficulty2(_initFlg, g_canLoadDifInfoFlg);
5016
- }
5017
- }
5065
+ g_customJsObj.difficulty.forEach(func => func(_initFlg, g_canLoadDifInfoFlg));
5018
5066
 
5019
5067
  // ---------------------------------------------------
5020
5068
  // 4. 譜面初期情報ロード許可フラグの設定
@@ -5310,12 +5358,7 @@ function settingsDisplayInit() {
5310
5358
  );
5311
5359
 
5312
5360
  // ユーザカスタムイベント(初期)
5313
- if (typeof customSettingsDisplayInit === C_TYP_FUNCTION) {
5314
- customSettingsDisplayInit();
5315
- if (typeof customSettingsDisplayInit2 === C_TYP_FUNCTION) {
5316
- customSettingsDisplayInit2();
5317
- }
5318
- }
5361
+ g_customJsObj.settingsDisplay.forEach(func => func());
5319
5362
 
5320
5363
  // ボタン描画
5321
5364
  commonSettingBtn(`Settings`);
@@ -5324,12 +5367,7 @@ function settingsDisplayInit() {
5324
5367
  setShortcutEvent(g_currentPage);
5325
5368
  document.oncontextmenu = _ => true;
5326
5369
 
5327
- if (typeof skinSettingsDisplayInit === C_TYP_FUNCTION) {
5328
- skinSettingsDisplayInit();
5329
- if (typeof skinSettingsDisplayInit2 === C_TYP_FUNCTION) {
5330
- skinSettingsDisplayInit2();
5331
- }
5332
- }
5370
+ g_skinJsObj.settingsDisplay.forEach(func => func());
5333
5371
  }
5334
5372
 
5335
5373
  /**
@@ -5371,13 +5409,13 @@ function createSettingsDisplayWindow(_sprite) {
5371
5409
 
5372
5410
  // Hidden+/Sudden+初期値用スライダー、ロックボタン
5373
5411
  multiAppend(spriteList.appearance,
5374
- createDivCss2Label(`lblAppearancePos`, `${g_hidSudObj.filterPos}${getStgDetailName(g_lblNameObj.percent)}`, {
5412
+ createDivCss2Label(`lblAppearancePos`, `${g_hidSudObj.filterPos}${g_lblNameObj.percent}`, {
5375
5413
  x: C_LEN_SETLBL_LEFT, y: 20, siz: 12, align: C_ALIGN_CENTER,
5376
5414
  }),
5377
5415
  createDivCss2Label(`lblAppearanceBar`, `<input id="appearanceSlider" type="range" value="${g_hidSudObj.filterPos}" min="0" max="100" step="1">`, {
5378
5416
  x: C_LEN_SETLBL_LEFT, y: 15,
5379
5417
  }),
5380
- createCss2Button(`lnkLockBtn`, `${getStgDetailName(g_lblNameObj.filterLock)}`, evt => setLockView(evt.target), {
5418
+ createCss2Button(`lnkLockBtn`, g_lblNameObj.filterLock, evt => setLockView(evt.target), {
5381
5419
  x: C_LEN_SETLBL_LEFT + C_LEN_SETLBL_WIDTH - 40, y: 0, w: 40, h: C_LEN_SETLBL_HEIGHT, siz: 12,
5382
5420
  borderStyle: `solid`, cxtFunc: evt => setLockView(evt.target),
5383
5421
  }, g_cssObj.button_Default, g_cssObj[`button_Rev${g_stateObj.filterLock}`]),
@@ -5393,10 +5431,8 @@ function createSettingsDisplayWindow(_sprite) {
5393
5431
  }
5394
5432
 
5395
5433
  const appearanceSlider = document.querySelector(`#appearanceSlider`);
5396
- appearanceSlider.addEventListener(`input`, _ => {
5397
- g_hidSudObj.filterPos = parseInt(appearanceSlider.value);
5398
- lblAppearancePos.textContent = `${g_hidSudObj.filterPos}${getStgDetailName(g_lblNameObj.percent)}`;
5399
- }, false);
5434
+ appearanceSlider.addEventListener(`input`, _ =>
5435
+ g_hidSudObj.filterPos = inputSlider(appearanceSlider, lblAppearancePos), false);
5400
5436
 
5401
5437
  const dispAppearanceSlider = _ => {
5402
5438
  [`lblAppearancePos`, `lblAppearanceBar`, `lnkLockBtn`].forEach(obj =>
@@ -5409,7 +5445,7 @@ function createSettingsDisplayWindow(_sprite) {
5409
5445
  // ---------------------------------------------------
5410
5446
  // 判定表示系の不透明度 (Opacity)
5411
5447
  // 縦位置: 9
5412
- createGeneralSetting(spriteList.opacity, `opacity`, { unitName: getStgDetailName(g_lblNameObj.percent), displayName: g_currentPage });
5448
+ createGeneralSetting(spriteList.opacity, `opacity`, { unitName: g_lblNameObj.percent, displayName: g_currentPage });
5413
5449
 
5414
5450
  /**
5415
5451
  * Display表示/非表示ボタン
@@ -5544,7 +5580,7 @@ function keyConfigInit(_kcType = g_kcType) {
5544
5580
  );
5545
5581
 
5546
5582
  // キーの一覧を表示
5547
- const keyconSprite = createEmptySprite(divRoot, `keyconSprite`, { y: 100 + (g_sHeight - 500) / 2, h: 300 });
5583
+ const keyconSprite = createEmptySprite(divRoot, `keyconSprite`, { y: 88 + (g_sHeight - 500) / 2, h: g_sHeight, overflow: `auto` });
5548
5584
  const tkObj = getKeyInfo();
5549
5585
  const [keyCtrlPtn, keyNum, posMax, divideCnt] =
5550
5586
  [tkObj.keyCtrlPtn, tkObj.keyNum, tkObj.posMax, tkObj.divideCnt];
@@ -5554,6 +5590,19 @@ function keyConfigInit(_kcType = g_kcType) {
5554
5590
  const kWidth = parseInt(keyconSprite.style.width);
5555
5591
  changeSetColor();
5556
5592
 
5593
+ const maxLeftPos = Math.max(divideCnt, posMax - divideCnt - 2) / 2;
5594
+ const maxLeftX = Math.min(0, (kWidth - C_ARW_WIDTH) / 2 - maxLeftPos * g_keyObj.blank);
5595
+
5596
+ /**
5597
+ * keyconSpriteのスクロール位置調整
5598
+ * @param {number} _targetX
5599
+ */
5600
+ const adjustScrollPoint = _targetX => {
5601
+ if (maxLeftX !== 0) {
5602
+ keyconSprite.scrollLeft = Math.max(0, _targetX - g_sWidth / 2);
5603
+ }
5604
+ };
5605
+
5557
5606
  /**
5558
5607
  * キーコンフィグ用の矢印色を取得
5559
5608
  * @param {number} _colorPos
@@ -5619,6 +5668,8 @@ function keyConfigInit(_kcType = g_kcType) {
5619
5668
  const arrowColor = getKeyConfigColor(_j, g_keyObj[`color${keyCtrlPtn}`][_j]);
5620
5669
  $id(`arrow${_j}`).background = arrowColor;
5621
5670
  $id(`arrowShadow${_j}`).background = getShadowColor(g_keyObj[`color${keyCtrlPtn}`][_j], arrowColor);
5671
+
5672
+ adjustScrollPoint(parseFloat($id(`arrow${_j}`).left));
5622
5673
  };
5623
5674
 
5624
5675
  /**
@@ -5629,6 +5680,8 @@ function keyConfigInit(_kcType = g_kcType) {
5629
5680
  const changeTmpShuffleNum = (_j, _scrollNum = 1) => {
5630
5681
  const tmpShuffle = changeTmpData(`shuffle`, 10, _j, _scrollNum);
5631
5682
  document.getElementById(`sArrow${_j}`).textContent = tmpShuffle + 1;
5683
+
5684
+ adjustScrollPoint(parseFloat($id(`arrow${_j}`).left));
5632
5685
  };
5633
5686
 
5634
5687
  for (let j = 0; j < keyNum; j++) {
@@ -5636,8 +5689,8 @@ function keyConfigInit(_kcType = g_kcType) {
5636
5689
  const posj = g_keyObj[`pos${keyCtrlPtn}`][j];
5637
5690
  const stdPos = posj - ((posj > divideCnt ? posMax : 0) + divideCnt) / 2;
5638
5691
 
5639
- const keyconX = g_keyObj.blank * stdPos + (kWidth - C_ARW_WIDTH) / 2;
5640
- const keyconY = C_KYC_HEIGHT * (Number(posj > divideCnt));
5692
+ const keyconX = g_keyObj.blank * stdPos + (kWidth - C_ARW_WIDTH) / 2 - maxLeftX;
5693
+ const keyconY = C_KYC_HEIGHT * (Number(posj > divideCnt)) + 12;
5641
5694
  const colorPos = g_keyObj[`color${keyCtrlPtn}`][j];
5642
5695
  const arrowColor = getKeyConfigColor(j, colorPos);
5643
5696
 
@@ -5697,7 +5750,7 @@ function keyConfigInit(_kcType = g_kcType) {
5697
5750
 
5698
5751
  // カーソルの作成
5699
5752
  const cursor = keyconSprite.appendChild(createImg(`cursor`, g_imgObj.cursor,
5700
- (kWidth - C_ARW_WIDTH) / 2 + g_keyObj.blank * (posj - divideCnt / 2) - 10, 45, 15, 30));
5753
+ (kWidth - C_ARW_WIDTH) / 2 + g_keyObj.blank * (posj - divideCnt / 2) - 10, 57, 15, 30));
5701
5754
  cursor.style.transitionDuration = `0.125s`;
5702
5755
 
5703
5756
  const viewGroupObj = {
@@ -5890,13 +5943,17 @@ function keyConfigInit(_kcType = g_kcType) {
5890
5943
  const posj = g_keyObj[`pos${keyCtrlPtn}`][g_currentj];
5891
5944
  const stdPos = posj - ((posj > divideCnt ? posMax : 0) + divideCnt) / 2;
5892
5945
 
5893
- cursor.style.left = `${(kWidth - C_ARW_WIDTH) / 2 + g_keyObj.blank * stdPos - 10}px`;
5894
- const baseY = C_KYC_HEIGHT * Number(posj > divideCnt) + 45;
5946
+ const nextLeft = (kWidth - C_ARW_WIDTH) / 2 + g_keyObj.blank * stdPos - maxLeftX - 10;
5947
+ cursor.style.left = `${nextLeft}px`;
5948
+ const baseY = C_KYC_HEIGHT * Number(posj > divideCnt) + 57;
5895
5949
  cursor.style.top = `${baseY + C_KYC_REPHEIGHT * g_currentk}px`;
5896
5950
  if (g_currentk === 0 && g_kcType === `Replaced`) {
5897
5951
  g_kcType = C_FLG_ALL;
5898
5952
  lnkKcType.textContent = getStgDetailName(g_kcType);
5899
5953
  }
5954
+
5955
+ // 次の位置が見えなくなったらkeyconSpriteの位置を調整する
5956
+ adjustScrollPoint(nextLeft);
5900
5957
  };
5901
5958
 
5902
5959
  /**
@@ -5964,6 +6021,7 @@ function keyConfigInit(_kcType = g_kcType) {
5964
6021
  // ConfigType, ColorTypeの初期設定
5965
6022
  setConfigType(0);
5966
6023
  setColorType(0);
6024
+ keyconSprite.scrollLeft = - maxLeftX;
5967
6025
 
5968
6026
  // キーパターン表示
5969
6027
  const lblTransKey = hasVal(g_keyObj[`transKey${keyCtrlPtn}`]) ?
@@ -5982,12 +6040,7 @@ function keyConfigInit(_kcType = g_kcType) {
5982
6040
  };
5983
6041
 
5984
6042
  // ユーザカスタムイベント(初期)
5985
- if (typeof customKeyConfigInit === C_TYP_FUNCTION) {
5986
- customKeyConfigInit();
5987
- if (typeof customKeyConfigInit2 === C_TYP_FUNCTION) {
5988
- customKeyConfigInit2();
5989
- }
5990
- }
6043
+ g_customJsObj.keyconfig.forEach(func => func());
5991
6044
 
5992
6045
  // ラベル・ボタン描画
5993
6046
  multiAppend(divRoot,
@@ -6045,6 +6098,7 @@ function keyConfigInit(_kcType = g_kcType) {
6045
6098
  }
6046
6099
  }
6047
6100
  resetCursor(Number(g_kcType === `Replaced`));
6101
+ keyconSprite.scrollLeft = - maxLeftX;
6048
6102
  }
6049
6103
  }, {
6050
6104
  x: 0, y: g_sHeight - 75,
@@ -6111,15 +6165,8 @@ function keyConfigInit(_kcType = g_kcType) {
6111
6165
  }
6112
6166
  });
6113
6167
 
6114
- if (typeof skinKeyConfigInit === C_TYP_FUNCTION) {
6115
- skinKeyConfigInit();
6116
- if (typeof skinKeyConfigInit2 === C_TYP_FUNCTION) {
6117
- skinKeyConfigInit2();
6118
- }
6119
- }
6120
-
6168
+ g_skinJsObj.keyconfig.forEach(func => func());
6121
6169
  document.onkeyup = evt => commonKeyUp(evt);
6122
-
6123
6170
  document.oncontextmenu = _ => false;
6124
6171
  }
6125
6172
 
@@ -6198,18 +6245,8 @@ function loadingScoreInit() {
6198
6245
  g_headerObj.blankFrame = g_headerObj.blankFrameDef;
6199
6246
 
6200
6247
  // ユーザカスタムイベント
6201
- if (typeof customPreloadingInit === C_TYP_FUNCTION) {
6202
- customPreloadingInit();
6203
- if (typeof customPreloadingInit2 === C_TYP_FUNCTION) {
6204
- customPreloadingInit2();
6205
- }
6206
- }
6207
- if (typeof skinPreloadingInit === C_TYP_FUNCTION) {
6208
- skinPreloadingInit();
6209
- if (typeof skinPreloadingInit2 === C_TYP_FUNCTION) {
6210
- skinPreloadingInit2();
6211
- }
6212
- }
6248
+ g_customJsObj.preloading.forEach(func => func());
6249
+ g_skinJsObj.preloading.forEach(func => func());
6213
6250
 
6214
6251
  let dummyIdHeader = ``;
6215
6252
  if (g_stateObj.dummyId !== ``) {
@@ -6229,7 +6266,7 @@ function loadingScoreInit() {
6229
6266
 
6230
6267
  // 開始フレーム数の取得(フェードイン加味)
6231
6268
  g_scoreObj.frameNum = getStartFrame(lastFrame, g_stateObj.fadein);
6232
- g_scoreObj.baseFrame;
6269
+ g_scoreObj.baseFrame = g_scoreObj.frameNum - g_stateObj.intAdjustment;
6233
6270
 
6234
6271
  // フレームごとの速度を取得(配列形式)
6235
6272
  let speedOnFrame = setSpeedOnFrame(g_scoreObj.speedData, lastFrame);
@@ -6340,12 +6377,7 @@ function loadingScoreInit() {
6340
6377
  getArrowSettings();
6341
6378
 
6342
6379
  // ユーザカスタムイベント
6343
- if (typeof customLoadingInit === C_TYP_FUNCTION) {
6344
- customLoadingInit();
6345
- if (typeof customLoadingInit2 === C_TYP_FUNCTION) {
6346
- customLoadingInit2();
6347
- }
6348
- }
6380
+ g_customJsObj.loading.forEach(func => func());
6349
6381
 
6350
6382
  const tempId = setInterval(() => {
6351
6383
  const executeMain = _ => {
@@ -6605,6 +6637,8 @@ function scoreConvert(_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
6605
6637
  return obj;
6606
6638
  }
6607
6639
 
6640
+ obj.colorData = mergeColorData();
6641
+
6608
6642
  // 矢印モーション(個別)データの分解(3~4つで1セット, セット毎の改行区切り)
6609
6643
  obj.arrowCssMotionData = setCssMotionData(`arrow`, scoreIdHeader);
6610
6644
  obj.frzCssMotionData = setCssMotionData(`frz`, scoreIdHeader);
@@ -6680,13 +6714,25 @@ function scoreConvert(_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
6680
6714
  return [];
6681
6715
  }
6682
6716
 
6717
+ /**
6718
+ * 個別・全体色変化データをマージして整列し、単純配列として返却
6719
+ * @param {string} _header
6720
+ * @returns
6721
+ */
6722
+ function mergeColorData(_header = `color`) {
6723
+ const tmpArr = obj[`${_header}Data`].concat(obj[`a${_header}Data`]);
6724
+ return tmpArr.sort((_a, _b) => _a[0] - _b[0]).flat();
6725
+ }
6726
+
6683
6727
  /**
6684
6728
  * 色変化データの分解・格納(フレーム数, 矢印番号)
6729
+ * 後で個別・全体色変化をマージするため、二次元配列として返却
6685
6730
  * @param {string} _header
6686
6731
  * @param {number} _scoreNo
6687
6732
  */
6688
6733
  function setColorData(_header, _scoreNo) {
6689
6734
  const colorData = [];
6735
+ const allFlg = (_header.charAt(0) === `a`);
6690
6736
 
6691
6737
  if (hasVal(_dosObj[`${_header}${_scoreNo}_data`]) && g_stateObj.d_color === C_FLG_ON) {
6692
6738
  const tmpArrayData = splitLF(_dosObj[`${_header}${_scoreNo}_data`]);
@@ -6703,10 +6749,11 @@ function scoreConvert(_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
6703
6749
  const colorNum = setVal(tmpColorData[k + 1], 0, C_TYP_CALC);
6704
6750
  const colorCd = tmpColorData[k + 2];
6705
6751
 
6706
- colorData.push([frame, colorNum, colorCd]);
6752
+ // フレーム数、色番号、カラーコード、全体色変化フラグをセットとして配列化
6753
+ colorData.push([frame, colorNum, colorCd, allFlg]);
6707
6754
  }
6708
6755
  });
6709
- return colorData.sort((_a, _b) => _a[0] - _b[0]).flat();
6756
+ return colorData.sort((_a, _b) => _a[0] - _b[0]);
6710
6757
  }
6711
6758
  return [];
6712
6759
  }
@@ -7265,25 +7312,21 @@ function pushArrows(_dataObj, _speedOnFrame, _motionOnFrame, _firstArrivalFrame)
7265
7312
  }
7266
7313
 
7267
7314
  // 個別・全体色変化、モーションデータのタイミング更新
7268
- calcDataTiming(`color`, ``, 3, pushColors, { _colorFlg: true });
7269
- calcDataTiming(`color`, `a`, 3, pushColors);
7270
- calcDataTiming(`color`, `shadow`, 3, pushColors, { _colorFlg: true });
7271
- calcDataTiming(`color`, `ashadow`, 3, pushColors);
7315
+ calcDataTiming(`color`, ``, pushColors, { _colorFlg: true });
7272
7316
 
7273
- [`arrow`, `frz`, `dummyArrow`, `dummyFrz`].forEach(header =>
7274
- calcDataTiming(`CssMotion`, header, 4, pushCssMotions, { _calcFrameFlg: true }));
7317
+ g_typeLists.arrow.forEach(header =>
7318
+ calcDataTiming(`CssMotion`, header, pushCssMotions, { _calcFrameFlg: true }));
7275
7319
 
7276
7320
  /**
7277
7321
  * 色変化・モーションデータのタイミング更新
7278
7322
  * @param {string} _type
7279
7323
  * @param {string} _header
7280
- * @param {integer} _term
7281
7324
  * @param {function} _setFunc
7282
7325
  * @param {object} obj _colorFlg: 個別色変化フラグ, _calcFrameFlg: 逆算を無条件で行うかどうかの可否
7283
7326
  * @returns
7284
7327
  */
7285
- function calcDataTiming(_type, _header, _term, _setFunc = _ => true,
7286
- { _colorFlg = false, _calcFrameFlg = false } = {}) {
7328
+ function calcDataTiming(_type, _header, _setFunc = _ => true,
7329
+ { _term = 4, _colorFlg = false, _calcFrameFlg = false } = {}) {
7287
7330
  const baseData = _dataObj[`${_header}${_type}Data`];
7288
7331
 
7289
7332
  if (!hasArrayList(baseData, _term)) {
@@ -7291,7 +7334,7 @@ function pushArrows(_dataObj, _speedOnFrame, _motionOnFrame, _firstArrivalFrame)
7291
7334
  }
7292
7335
  const frontData = [];
7293
7336
  for (let k = baseData.length - _term; k >= 0; k -= _term) {
7294
- const calcFrameFlg = (_colorFlg && !isFrzHitColor(baseData[k + 1])) || _calcFrameFlg;
7337
+ const calcFrameFlg = (_colorFlg && !isFrzHitColor(baseData[k + 1]) && !baseData[k + 3]) || _calcFrameFlg;
7295
7338
 
7296
7339
  if (baseData[k] < g_scoreObj.frameNum) {
7297
7340
  if (!hasValInArray(baseData[k + 1], frontData)) {
@@ -7314,6 +7357,74 @@ function pushArrows(_dataObj, _speedOnFrame, _motionOnFrame, _firstArrivalFrame)
7314
7357
  frontData.forEach(data => _setFunc(toCapitalize(_header), g_scoreObj.frameNum, ...data));
7315
7358
  }
7316
7359
 
7360
+ g_fadeinStockList.forEach(type =>
7361
+ _dataObj[`${type}Data`] = calcAnimationData(type, _dataObj[`${type}Data`]));
7362
+
7363
+ /**
7364
+ * 歌詞表示、背景・マスク表示のフェードイン時調整処理
7365
+ * @param {string} _type
7366
+ * @param {object} _data
7367
+ * @returns
7368
+ */
7369
+ function calcAnimationData(_type, _data) {
7370
+
7371
+ const startNum = g_scoreObj.frameNum;
7372
+ const cgArrays = [`word`];
7373
+
7374
+ const isSameDepth = (_j, _k) =>
7375
+ _data[startNum][_j] !== undefined &&
7376
+ _data[startNum][_k] !== undefined &&
7377
+ (cgArrays.includes(_type) ? _data[startNum][_j][0] === _data[startNum][_k][0] :
7378
+ _data[startNum][_j].depth === _data[startNum][_k].depth);
7379
+
7380
+ const fuzzyCheck = (_str, _list) => listMatching(_str, _list);
7381
+ const isExceptData = {
7382
+ word: (_exceptList, _j) => fuzzyCheck(_data[startNum][_j][1], _exceptList.word),
7383
+ back: (_exceptList, _j) => fuzzyCheck(_data[startNum][_j].animationName, _exceptList.back),
7384
+ mask: (_exceptList, _j) => fuzzyCheck(_data[startNum][_j].animationName, _exceptList.mask),
7385
+ };
7386
+
7387
+ const getLength = _list =>
7388
+ _list === undefined ? 0 :
7389
+ (cgArrays.includes(_type) ? _list.length : Object.keys(_list).length);
7390
+
7391
+ // フェードイン位置にそれ以前のデータを前追加
7392
+ if (startNum > 0 && _data[startNum] === undefined) {
7393
+ _data[startNum] = [];
7394
+ }
7395
+ for (let j = _data.length - 1; j >= 0; j--) {
7396
+ if (_data[j] !== undefined && j < g_scoreObj.frameNum) {
7397
+ _data[startNum].unshift(..._data[j]);
7398
+ _data[j] = undefined;
7399
+ }
7400
+ }
7401
+
7402
+ // 重複する深度をカット(後方優先)
7403
+ // ただし、除外リストにあるデータは残す
7404
+ for (let j = getLength(_data[startNum]) - 1; j >= 0; j--) {
7405
+ if (_data[startNum][j] !== undefined) {
7406
+ for (let k = j - 1; k >= 0; k--) {
7407
+ if (isSameDepth(j, k) && !isExceptData[_type](g_preloadExceptList, k)) {
7408
+ _data[startNum][k] = undefined;
7409
+ }
7410
+ }
7411
+ }
7412
+ }
7413
+ // g_stockForceDelList に合致する消去対象データを検索し、削除
7414
+ for (let j = getLength(_data[startNum]) - 1; j >= 0; j--) {
7415
+ if (_data[startNum][j] !== undefined && isExceptData[_type](g_stockForceDelList, j)) {
7416
+ _data[startNum][j] = undefined;
7417
+ }
7418
+ }
7419
+
7420
+ // カットした箇所をリストから削除
7421
+ if (getLength(_data[startNum], _type) > 0) {
7422
+ _data[startNum] = _data[startNum].filter(list => getLength(list) > 0);
7423
+ }
7424
+
7425
+ return _data;
7426
+ }
7427
+
7317
7428
  // 実際に処理させる途中変速配列を作成
7318
7429
  g_workObj.speedData = [];
7319
7430
  g_workObj.speedData.length = 0;
@@ -7408,54 +7519,108 @@ function convertreplaceNums() {
7408
7519
  * @param {number} _frame
7409
7520
  * @param {number} _val
7410
7521
  * @param {string} _colorCd
7522
+ * @param {string} _allFlg
7411
7523
  */
7412
- function pushColors(_header, _frame, _val, _colorCd) {
7524
+ function pushColors(_header, _frame, _val, _colorCd, _allFlg) {
7413
7525
 
7414
7526
  const tkObj = getKeyInfo();
7415
7527
  const grdFlg = (g_colorType === `Type0` ? !g_headerObj.defaultColorgrd[0] : g_headerObj.defaultColorgrd[0])
7416
7528
  const colorCd = makeColorGradation(_colorCd, { _defaultColorgrd: [grdFlg, g_headerObj.defaultColorgrd[1]] });
7529
+ const addAll = Number(_allFlg) * 1000;
7530
+ const allUseTypes = [];
7531
+
7532
+ /**
7533
+ * 色変化用配列(フレーム別)の初期化
7534
+ * @param {string} _baseStr
7535
+ */
7536
+ const initialize = (_baseStr) => {
7537
+ if (g_workObj[_baseStr][_frame] === undefined) {
7538
+ g_workObj[_baseStr][_frame] = [];
7539
+ g_workObj[`${_baseStr}Cd`][_frame] = [];
7540
+ }
7541
+ };
7542
+
7543
+ /**
7544
+ * 全体色変化の有効化(フレーム別)
7545
+ * @param {...any} _types
7546
+ */
7547
+ const enabledAll = (..._types) => {
7548
+ if (_allFlg) {
7549
+ _types.forEach(type => g_workObj[`mk${type}ColorChangeAll`][_frame] = true);
7550
+ }
7551
+ };
7552
+
7553
+ /**
7554
+ * 色変化用配列(フレーム別)へのデータ追加
7555
+ * @param {string} _baseStr
7556
+ * @param {number} _cVal
7557
+ */
7558
+ const pushColor = (_baseStr, _cVal) => {
7559
+ g_workObj[_baseStr][_frame].push(_cVal);
7560
+ g_workObj[`${_baseStr}Cd`][_frame].push(colorCd);
7561
+ };
7417
7562
 
7418
7563
  if (_val < 30 || _val >= 1000) {
7419
- // 矢印の色変化
7420
- if (g_workObj[`mk${_header}Color`][_frame] === undefined) {
7421
- g_workObj[`mk${_header}Color`][_frame] = [];
7422
- g_workObj[`mk${_header}ColorCd`][_frame] = [];
7423
- }
7424
- if (_val < 20 || _val >= 1000) {
7425
- const realVal = g_workObj.replaceNums[_val % 1000];
7426
- g_workObj[`mk${_header}Color`][_frame].push(realVal);
7427
- g_workObj[`mk${_header}ColorCd`][_frame].push(colorCd);
7428
- } else if (_val >= 20) {
7429
- const colorNum = _val - 20;
7430
- for (let j = 0; j < tkObj.keyNum; j++) {
7431
- if (g_keyObj[`color${tkObj.keyCtrlPtn}`][j] === colorNum) {
7432
- g_workObj[`mk${_header}Color`][_frame].push(j);
7433
- g_workObj[`mk${_header}ColorCd`][_frame].push(colorCd);
7564
+ const baseHeaders = [`mk${_header}Color`];
7565
+ allUseTypes.push(`Arrow`);
7566
+
7567
+ // フリーズアロー色の追随設定がある場合、対象を追加
7568
+ g_headerObj.frzScopeFromArrowColors.forEach(type => {
7569
+ baseHeaders.push(`mkF${_header}Color${type}`, `mkF${_header}Color${type}Bar`);
7570
+ });
7571
+ if (g_headerObj.frzScopeFromArrowColors.length > 0) {
7572
+ allUseTypes.push(`Frz`);
7573
+ }
7574
+
7575
+ // 矢印の色変化 (追随指定時はフリーズアローも色変化)
7576
+ baseHeaders.forEach(baseHeader => {
7577
+ initialize(baseHeader);
7578
+
7579
+ if (_val < 20 || _val >= 1000) {
7580
+ pushColor(baseHeader, g_workObj.replaceNums[_val % 1000] + addAll);
7581
+ } else if (_val >= 20) {
7582
+ const colorNum = _val - 20;
7583
+ for (let j = 0; j < tkObj.keyNum; j++) {
7584
+ if (g_keyObj[`color${tkObj.keyCtrlPtn}`][j] === colorNum) {
7585
+ pushColor(baseHeader, j + addAll);
7586
+ }
7434
7587
  }
7435
7588
  }
7436
- }
7589
+ });
7590
+
7437
7591
  } else {
7592
+ const baseHeader = `mkF${_header}Color`;
7593
+ allUseTypes.push(`Frz`);
7594
+
7438
7595
  // フリーズアローの色変化
7439
- if (g_workObj[`mkF${_header}Color`][_frame] === undefined) {
7440
- g_workObj[`mkF${_header}Color`][_frame] = [];
7441
- g_workObj[`mkF${_header}ColorCd`][_frame] = [];
7442
- }
7596
+ const tmpVals = [];
7443
7597
  if (_val < 50) {
7444
- g_workObj[`mkF${_header}Color`][_frame].push(_val % 30);
7445
- g_workObj[`mkF${_header}ColorCd`][_frame].push(colorCd);
7598
+ tmpVals.push(_val % 30);
7446
7599
  } else if (_val < 60) {
7447
- const tmpVal = (_val % 50) * 2;
7448
- g_workObj[`mkF${_header}Color`][_frame].push(tmpVal, tmpVal + 1);
7449
- g_workObj[`mkF${_header}ColorCd`][_frame].push(colorCd, colorCd);
7600
+ tmpVals.push((_val % 50) * 2, (_val % 50) * 2 + 1);
7450
7601
  } else {
7451
7602
  if (_val === 60) {
7452
- g_workObj[`mkF${_header}Color`][_frame].push(0, 1, 2, 3, 4, 5, 6, 7);
7603
+ tmpVals.push(...Array(8).keys());
7453
7604
  } else {
7454
- g_workObj[`mkF${_header}Color`][_frame].push(10, 11, 12, 13, 14, 15, 16, 17);
7605
+ tmpVals.push(...[...Array(8).keys()].map(j => j + 10));
7455
7606
  }
7456
- g_workObj[`mkF${_header}ColorCd`][_frame].push(colorCd, colorCd, colorCd, colorCd, colorCd, colorCd, colorCd, colorCd);
7457
7607
  }
7608
+ tmpVals.forEach(targetj => {
7609
+
7610
+ // targetj=0,2,4,6,8 ⇒ Arrow, 1,3,5,7,9 ⇒ Bar
7611
+ const ctype = (targetj >= 10 ? `Hit` : `Normal`) + (targetj % 2 === 0 ? `` : `Bar`);
7612
+ const colorPos = Math.ceil((targetj % 10 - 1) / 2);
7613
+
7614
+ g_keyObj[`color${tkObj.keyCtrlPtn}`].forEach((cpattern, k) => {
7615
+ if (colorPos === cpattern) {
7616
+ initialize(baseHeader + ctype);
7617
+ pushColor(baseHeader + ctype, k + addAll);
7618
+ }
7619
+ });
7620
+ });
7458
7621
  }
7622
+
7623
+ enabledAll(...allUseTypes);
7459
7624
  }
7460
7625
 
7461
7626
  /**
@@ -7512,6 +7677,7 @@ function getArrowSettings() {
7512
7677
  g_workObj.stepHitRtn = copyArray2d(g_keyObj[`stepRtn${keyCtrlPtn}`]);
7513
7678
  g_workObj.arrowRtn = copyArray2d(g_keyObj[`stepRtn${keyCtrlPtn}`]);
7514
7679
  g_workObj.keyCtrl = copyArray2d(g_keyObj[`keyCtrl${keyCtrlPtn}`]);
7680
+ g_workObj.diffList = [];
7515
7681
 
7516
7682
  const keyCtrlLen = g_workObj.keyCtrl.length;
7517
7683
  g_workObj.keyCtrlN = [...Array(keyCtrlLen)].map(_ => []);
@@ -8083,13 +8249,7 @@ function MainInit() {
8083
8249
  }
8084
8250
 
8085
8251
  // ユーザカスタムイベント(初期)
8086
- if (typeof customMainInit === C_TYP_FUNCTION) {
8087
- g_scoreObj.baseFrame = g_scoreObj.frameNum - g_stateObj.intAdjustment;
8088
- customMainInit();
8089
- if (typeof customMainInit2 === C_TYP_FUNCTION) {
8090
- customMainInit2();
8091
- }
8092
- }
8252
+ g_customJsObj.main.forEach(func => func());
8093
8253
 
8094
8254
  /**
8095
8255
  * キーを押したときの処理
@@ -8199,12 +8359,11 @@ function MainInit() {
8199
8359
  // TODO: この部分を矢印塗りつぶし部分についても適用できるように対応
8200
8360
  arrow: (_j, _k) => {
8201
8361
  const arrowTop = document.querySelector(`#arrowTop${_j}_${_k}`);
8202
- if (g_workObj.mkAColor[g_scoreObj.frameNum] !== undefined) {
8203
- if (arrowTop.getAttribute(`color`) !== g_workObj.arrowColors[_j]) {
8204
- if (g_workObj.arrowColors[_j] === g_workObj.arrowColorsAll[_j]) {
8205
- arrowTop.style.background = g_workObj.arrowColorsAll[_j];
8206
- arrowTop.setAttribute(`color`, g_workObj.arrowColorsAll[_j]);
8207
- }
8362
+ if (g_workObj.mkArrowColorChangeAll[g_scoreObj.frameNum]) {
8363
+ if (arrowTop.getAttribute(`color`) !== g_workObj.arrowColors[_j] &&
8364
+ g_workObj.arrowColors[_j] === g_workObj.arrowColorsAll[_j]) {
8365
+ arrowTop.style.background = g_workObj.arrowColorsAll[_j];
8366
+ arrowTop.setAttribute(`color`, g_workObj.arrowColorsAll[_j]);
8208
8367
  }
8209
8368
  }
8210
8369
  },
@@ -8217,7 +8376,7 @@ function MainInit() {
8217
8376
  const frzBar = document.querySelector(`#frzBar${_j}_${_k}`);
8218
8377
  const frzBtm = document.querySelector(`#frzBtm${_j}_${_k}`);
8219
8378
 
8220
- if (g_workObj.mkFAColor[g_scoreObj.frameNum] !== undefined) {
8379
+ if (g_workObj.mkFrzColorChangeAll[g_scoreObj.frameNum]) {
8221
8380
  if (frzBtm.getAttribute(`color`) !== g_workObj[`frz${_state}Colors`][_j]) {
8222
8381
  const toColorCode = g_workObj[`frz${_state}ColorsAll`][_j];
8223
8382
  if (g_workObj[`frz${_state}Colors`][_j] === toColorCode) {
@@ -8294,12 +8453,7 @@ function MainInit() {
8294
8453
  if (_cnt === 0) {
8295
8454
  const stepDivHit = document.querySelector(`#stepHit${_j}`);
8296
8455
 
8297
- if (typeof customJudgeDummyArrow === C_TYP_FUNCTION) {
8298
- customJudgeDummyArrow(_cnt);
8299
- if (typeof customJudgeDummyArrow2 === C_TYP_FUNCTION) {
8300
- customJudgeDummyArrow2(_cnt);
8301
- }
8302
- }
8456
+ g_customJsObj.dummyArrow.forEach(func => func());
8303
8457
  stepDivHit.style.top = `-15px`;
8304
8458
  stepDivHit.style.opacity = 1;
8305
8459
  stepDivHit.classList.value = ``;
@@ -8319,12 +8473,7 @@ function MainInit() {
8319
8473
 
8320
8474
  // ダミーフリーズアロー(成功時)
8321
8475
  dummyFrzOK: (_j, _k, _frzName, _cnt) => {
8322
- if (typeof customJudgeDummyFrz === C_TYP_FUNCTION) {
8323
- customJudgeDummyFrz(_cnt);
8324
- if (typeof customJudgeDummyFrz2 === C_TYP_FUNCTION) {
8325
- customJudgeDummyFrz2(_cnt);
8326
- }
8327
- }
8476
+ g_customJsObj.dummyFrz.forEach(func => func());
8328
8477
  $id(`frzHit${_j}`).opacity = 0;
8329
8478
  g_attrObj[_frzName].judgEndFlg = true;
8330
8479
  judgeObjDelete.dummyFrz(_j, _frzName);
@@ -8478,7 +8627,7 @@ function MainInit() {
8478
8627
  if (g_headerObj.setShadowColor[colorPos] !== ``) {
8479
8628
  // 矢印の塗り部分
8480
8629
  const arrShadow = createColorObject2(`${_name}Shadow${_j}_${_arrowCnt}`, {
8481
- background: getShadowColor(colorPos, g_workObj.arrowColors[_j]), rotate: g_workObj.arrowRtn[_j], styleName: `Shadow`,
8630
+ background: getShadowColor(colorPos, _color), rotate: g_workObj.arrowRtn[_j], styleName: `Shadow`,
8482
8631
  });
8483
8632
  if (g_headerObj.setShadowColor[colorPos] === `Default`) {
8484
8633
  arrShadow.style.opacity = 0.5;
@@ -8706,11 +8855,8 @@ function MainInit() {
8706
8855
  }
8707
8856
 
8708
8857
  // ユーザカスタムイベント(フレーム毎)
8709
- if (typeof customMainEnterFrame === C_TYP_FUNCTION) {
8710
- customMainEnterFrame();
8711
- if (typeof customMainEnterFrame2 === C_TYP_FUNCTION) {
8712
- customMainEnterFrame2();
8713
- }
8858
+ g_customJsObj.mainEnterFrame.forEach(func => func());
8859
+ if (g_customJsObj.mainEnterFrame.length > 0) {
8714
8860
  g_scoreObj.baseFrame++;
8715
8861
  }
8716
8862
 
@@ -8724,19 +8870,12 @@ function MainInit() {
8724
8870
  boostCnts += 2;
8725
8871
  }
8726
8872
 
8727
- // 個別色変化 (矢印)
8728
- changeArrowColors(g_workObj.mkColor[currentFrame], g_workObj.mkColorCd[currentFrame]);
8729
-
8730
- // 個別色変化(フリーズアロー)
8731
- changeFrzColors(g_workObj.mkFColor[currentFrame], g_workObj.mkFColorCd[currentFrame],
8732
- g_keyObj[`color${keyCtrlPtn}`]);
8873
+ // 個別・全体色変化 (矢印)
8874
+ changeColors(g_workObj.mkColor[currentFrame], g_workObj.mkColorCd[currentFrame]);
8733
8875
 
8734
- // 全体色変化 (矢印)
8735
- changeArrowColors(g_workObj.mkAColor[currentFrame], g_workObj.mkAColorCd[currentFrame], `A`);
8736
-
8737
- // 全体色変化 (フリーズアロー)
8738
- changeFrzColors(g_workObj.mkFAColor[currentFrame], g_workObj.mkFAColorCd[currentFrame],
8739
- g_keyObj[`color${keyCtrlPtn}`], `A`);
8876
+ // 個別・全体色変化(フリーズアロー)
8877
+ g_typeLists.frzColor.forEach(ctype =>
8878
+ changeColors(g_workObj[`mkFColor${ctype}`][currentFrame], g_workObj[`mkFColor${ctype}Cd`][currentFrame], `frz${ctype}`));
8740
8879
 
8741
8880
  // 矢印モーション
8742
8881
  changeCssMotions(g_workObj.mkArrowCssMotion[currentFrame], g_workObj.mkArrowCssMotionName[currentFrame], `arrow`);
@@ -8911,12 +9050,7 @@ function MainInit() {
8911
9050
  g_timeoutEvtId = setTimeout(_ => flowTimeline(), 1000 / g_fps - buffTime);
8912
9051
  }
8913
9052
  }
8914
- if (typeof skinMainInit === C_TYP_FUNCTION) {
8915
- skinMainInit();
8916
- if (typeof skinMainInit2 === C_TYP_FUNCTION) {
8917
- skinMainInit2();
8918
- }
8919
- }
9053
+ g_skinJsObj.main.forEach(func => func());
8920
9054
 
8921
9055
  g_audio.currentTime = firstFrame / g_fps * g_headerObj.playbackRate;
8922
9056
  g_audio.playbackRate = g_headerObj.playbackRate;
@@ -8986,53 +9120,25 @@ function makeCounterSymbol(_id, _x, _class, _heightPos, _text, _display = C_DIS_
8986
9120
  // TODO: この部分を矢印塗りつぶし部分についても適用できるように関数を見直し
8987
9121
 
8988
9122
  /**
8989
- * 個別色変化 (矢印)
9123
+ * 個別・全体色変化
8990
9124
  * @param {array} _mkColor
8991
9125
  * @param {array} _mkColorCd
8992
- * @param {string} _allFlg
9126
+ * @param {string} _objType
8993
9127
  */
8994
- function changeArrowColors(_mkColor, _mkColorCd, _allFlg = ``) {
9128
+ function changeColors(_mkColor, _mkColorCd, _objType = `arrow`) {
8995
9129
 
8996
9130
  if (_mkColor === undefined) {
8997
9131
  return;
8998
9132
  }
8999
- _mkColor.forEach((targetj, j) => {
9000
- g_workObj.arrowColors[targetj] = _mkColorCd[j];
9001
- if (_allFlg === `A`) {
9002
- g_workObj.arrowColorsAll[targetj] = _mkColorCd[j];
9003
- }
9004
- });
9005
- }
9006
-
9007
- /**
9008
- * 個別色変化 (フリーズアロー)
9009
- * @param {array} _mkColor
9010
- * @param {array} _mkColorCd
9011
- * @param {array} _colorPatterns
9012
- * @param {string} _allFlg
9013
- */
9014
- function changeFrzColors(_mkColor, _mkColorCd, _colorPatterns, _allFlg = ``) {
9015
-
9016
- if (_mkColor === undefined) {
9017
- return;
9018
- }
9019
- _mkColor.forEach((targetj, j) => {
9020
-
9021
- // targetj=0,2,4,6,8 ⇒ Arrow, 1,3,5,7,9 ⇒ Bar
9022
- const ctype = (targetj >= 10 ? `Hit` : `Normal`) + (targetj % 2 === 0 ? `` : `Bar`);
9023
- const colorPos = Math.ceil((targetj % 10 - 1) / 2);
9024
-
9025
- _colorPatterns.forEach((cpattern, k) => {
9026
- if (colorPos === cpattern) {
9027
- g_workObj[`frz${ctype}Colors`][k] = _mkColorCd[j];
9028
- if (_allFlg === `A`) {
9029
- g_workObj[`frz${ctype}ColorsAll`][k] = _mkColorCd[j];
9030
- if (ctype === `HitBar` && isNaN(Number(g_workObj.arrowRtn[k]))) {
9031
- $id(`frzHitTop${k}`).background = _mkColorCd[j];
9032
- }
9033
- }
9133
+ _mkColor.forEach((tempj, j) => {
9134
+ const targetj = tempj % 1000;
9135
+ g_workObj[`${_objType}Colors`][targetj] = _mkColorCd[j];
9136
+ if (tempj >= 1000) {
9137
+ g_workObj[`${_objType}ColorsAll`][targetj] = _mkColorCd[j];
9138
+ if (_objType.indexOf(`HitBar`) !== -1 && isNaN(Number(g_workObj.arrowRtn[targetj]))) {
9139
+ $id(`frzHitTop${targetj}`).background = _mkColorCd[j];
9034
9140
  }
9035
- });
9141
+ }
9036
9142
  });
9037
9143
  }
9038
9144
 
@@ -9212,6 +9318,7 @@ function judgeArrow(_j) {
9212
9318
  */
9213
9319
  function displayDiff(_difFrame, _justFrames = 0) {
9214
9320
  let diffJDisp = ``;
9321
+ g_workObj.diffList.push(_difFrame);
9215
9322
  const difCnt = Math.abs(_difFrame);
9216
9323
  if (_difFrame > _justFrames) {
9217
9324
  diffJDisp = `<span class="common_matari">Fast ${difCnt} Frames</span>`;
@@ -9303,24 +9410,42 @@ function updateCombo() {
9303
9410
  }
9304
9411
 
9305
9412
  /**
9306
- * 判定処理:イイ
9307
- * @param {number} difFrame
9413
+ * 回復判定の共通処理
9414
+ * @param {string} _name
9415
+ * @param {number} _difFrame
9308
9416
  */
9309
- function judgeIi(difFrame) {
9310
- changeJudgeCharacter(`ii`, g_lblNameObj.j_ii);
9417
+ function judgeRecovery(_name, _difFrame) {
9418
+ changeJudgeCharacter(_name, g_lblNameObj[`j_${_name}`]);
9311
9419
 
9312
9420
  updateCombo();
9313
- displayDiff(difFrame, g_headerObj.justFrames);
9421
+ displayDiff(_difFrame, g_headerObj.justFrames);
9314
9422
 
9315
9423
  lifeRecovery();
9316
9424
  finishViewing();
9317
9425
 
9318
- if (typeof customJudgeIi === C_TYP_FUNCTION) {
9319
- customJudgeIi(difFrame);
9320
- if (typeof customJudgeIi2 === C_TYP_FUNCTION) {
9321
- customJudgeIi2(difFrame);
9322
- }
9323
- }
9426
+ g_customJsObj[`judg_${_name}`].forEach(func => func(_difFrame));
9427
+ }
9428
+
9429
+ /**
9430
+ * ダメージ系共通処理
9431
+ * @param {string} _name
9432
+ * @param {number} _difFrame
9433
+ */
9434
+ function judgeDamage(_name, _difFrame) {
9435
+ changeJudgeCharacter(_name, g_lblNameObj[`j_${_name}`]);
9436
+ g_resultObj.combo = 0;
9437
+ comboJ.textContent = ``;
9438
+ diffJ.textContent = ``;
9439
+ lifeDamage();
9440
+ g_customJsObj[`judg_${_name}`].forEach(func => func(_difFrame));
9441
+ }
9442
+
9443
+ /**
9444
+ * 判定処理:イイ
9445
+ * @param {number} difFrame
9446
+ */
9447
+ function judgeIi(difFrame) {
9448
+ judgeRecovery(`ii`, difFrame);
9324
9449
  }
9325
9450
 
9326
9451
  /**
@@ -9328,20 +9453,7 @@ function judgeIi(difFrame) {
9328
9453
  * @param {number} difFrame
9329
9454
  */
9330
9455
  function judgeShakin(difFrame) {
9331
- changeJudgeCharacter(`shakin`, g_lblNameObj.j_shakin);
9332
-
9333
- updateCombo();
9334
- displayDiff(difFrame, g_headerObj.justFrames);
9335
-
9336
- lifeRecovery();
9337
- finishViewing();
9338
-
9339
- if (typeof customJudgeShakin === C_TYP_FUNCTION) {
9340
- customJudgeShakin(difFrame);
9341
- if (typeof customJudgeShakin2 === C_TYP_FUNCTION) {
9342
- customJudgeShakin2(difFrame);
9343
- }
9344
- }
9456
+ judgeRecovery(`shakin`, difFrame);
9345
9457
  }
9346
9458
 
9347
9459
  /**
@@ -9355,22 +9467,7 @@ function judgeMatari(difFrame) {
9355
9467
  displayDiff(difFrame, g_headerObj.justFrames);
9356
9468
  finishViewing();
9357
9469
 
9358
- if (typeof customJudgeMatari === C_TYP_FUNCTION) {
9359
- customJudgeMatari(difFrame);
9360
- if (typeof customJudgeMatari2 === C_TYP_FUNCTION) {
9361
- customJudgeMatari2(difFrame);
9362
- }
9363
- }
9364
- }
9365
-
9366
- /**
9367
- * ダメージ系共通処理
9368
- */
9369
- function judgeDamage() {
9370
- g_resultObj.combo = 0;
9371
- comboJ.textContent = ``;
9372
- diffJ.textContent = ``;
9373
- lifeDamage();
9470
+ g_customJsObj.judg_matari.forEach(func => func(difFrame));
9374
9471
  }
9375
9472
 
9376
9473
  /**
@@ -9378,15 +9475,7 @@ function judgeDamage() {
9378
9475
  * @param {number} difFrame
9379
9476
  */
9380
9477
  function judgeShobon(difFrame) {
9381
- changeJudgeCharacter(`shobon`, g_lblNameObj.j_shobon);
9382
- judgeDamage();
9383
-
9384
- if (typeof customJudgeShobon === C_TYP_FUNCTION) {
9385
- customJudgeShobon(difFrame);
9386
- if (typeof customJudgeShobon2 === C_TYP_FUNCTION) {
9387
- customJudgeShobon2(difFrame);
9388
- }
9389
- }
9478
+ judgeDamage(`shobon`, difFrame);
9390
9479
  }
9391
9480
 
9392
9481
  /**
@@ -9394,15 +9483,7 @@ function judgeShobon(difFrame) {
9394
9483
  * @param {number} difFrame
9395
9484
  */
9396
9485
  function judgeUwan(difFrame) {
9397
- changeJudgeCharacter(`uwan`, g_lblNameObj.j_uwan);
9398
- judgeDamage();
9399
-
9400
- if (typeof customJudgeUwan === C_TYP_FUNCTION) {
9401
- customJudgeUwan(difFrame);
9402
- if (typeof customJudgeUwan2 === C_TYP_FUNCTION) {
9403
- customJudgeUwan2(difFrame);
9404
- }
9405
- }
9486
+ judgeDamage(`uwan`, difFrame);
9406
9487
  }
9407
9488
 
9408
9489
  /**
@@ -9421,12 +9502,7 @@ function judgeKita(difFrame) {
9421
9502
  lifeRecovery();
9422
9503
  finishViewing();
9423
9504
 
9424
- if (typeof customJudgeKita === C_TYP_FUNCTION) {
9425
- customJudgeKita(difFrame);
9426
- if (typeof customJudgeKita2 === C_TYP_FUNCTION) {
9427
- customJudgeKita2(difFrame);
9428
- }
9429
- }
9505
+ g_customJsObj.judg_kita.forEach(func => func(difFrame));
9430
9506
  }
9431
9507
 
9432
9508
  /**
@@ -9440,12 +9516,7 @@ function judgeIknai(difFrame) {
9440
9516
 
9441
9517
  lifeDamage();
9442
9518
 
9443
- if (typeof customJudgeIknai === C_TYP_FUNCTION) {
9444
- customJudgeIknai(difFrame);
9445
- if (typeof customJudgeIknai2 === C_TYP_FUNCTION) {
9446
- customJudgeIknai2(difFrame);
9447
- }
9448
- }
9519
+ g_customJsObj.judg_iknai.forEach(func => func(difFrame));
9449
9520
  }
9450
9521
 
9451
9522
  // クリア表示
@@ -9527,6 +9598,12 @@ function resultInit() {
9527
9598
  }
9528
9599
  }
9529
9600
 
9601
+ // diffListから適正Adjを算出(20個以下の場合は算出しない)
9602
+ const getSign = _val => (_val > 0 ? `+` : ``);
9603
+ const getDiffFrame = _val => `${getSign(_val)}${_val}${g_lblNameObj.frame}`;
9604
+ const estimatedAdj = (g_workObj.diffList.length <= 20 ?
9605
+ `` : Math.round((g_stateObj.adjustment - g_workObj.diffList.reduce((x, y) => x + y, 0) / g_workObj.diffList.length) * 10) / 10);
9606
+
9530
9607
  // 背景スプライトを作成
9531
9608
  createMultipleSprite(`backResultSprite`, g_headerObj.backResultMaxDepth);
9532
9609
 
@@ -9591,14 +9668,14 @@ function resultInit() {
9591
9668
  }
9592
9669
 
9593
9670
  let difData = [
9594
- `${getKeyName(g_headerObj.keyLabels[g_stateObj.scoreId])}${transKeyData} key / ${g_headerObj.difLabels[g_stateObj.scoreId]}`,
9671
+ `${getKeyName(g_headerObj.keyLabels[g_stateObj.scoreId])}${transKeyData} ${getStgDetailName('key')} / ${g_headerObj.difLabels[g_stateObj.scoreId]}`,
9595
9672
  `${withOptions(g_autoPlaysBase.includes(g_stateObj.autoPlay), true, `-${getStgDetailName(g_stateObj.autoPlay)}${getStgDetailName('less')}`)}`,
9596
9673
  `${withOptions(g_headerObj.makerView, false, `(${g_headerObj.creatorNames[g_stateObj.scoreId]})`)}`,
9597
9674
  `${withOptions(g_stateObj.shuffle, C_FLG_OFF, `[${getShuffleName()}]`)}`
9598
9675
  ].filter(value => value !== ``).join(` `);
9599
9676
 
9600
9677
  let playStyleData = [
9601
- `${g_stateObj.speed}${getStgDetailName(g_lblNameObj.multi)}`,
9678
+ `${g_stateObj.speed}${g_lblNameObj.multi}`,
9602
9679
  `${withOptions(g_stateObj.motion, C_FLG_OFF)}`,
9603
9680
  `${withOptions(g_stateObj.reverse, C_FLG_OFF,
9604
9681
  getStgDetailName(g_stateObj.scroll !== '---' ? 'R-' : 'Reverse'))}${withOptions(g_stateObj.scroll, '---')}`,
@@ -9684,6 +9761,12 @@ function resultInit() {
9684
9761
  makeCssResultSymbol(`lblFastS`, 260, g_cssObj.score, 1, g_resultObj.fast, C_ALIGN_RIGHT),
9685
9762
  makeCssResultSymbol(`lblSlowS`, 260, g_cssObj.score, 3, g_resultObj.slow, C_ALIGN_RIGHT),
9686
9763
  );
9764
+ if (estimatedAdj !== ``) {
9765
+ multiAppend(resultWindow,
9766
+ makeCssResultSymbol(`lblAdj`, 350, g_cssObj.common_shakin, 4, g_lblNameObj.j_adj),
9767
+ makeCssResultSymbol(`lblAdjS`, 260, g_cssObj.score, 5, `${getDiffFrame(estimatedAdj)}`, C_ALIGN_RIGHT),
9768
+ );
9769
+ }
9687
9770
  }
9688
9771
 
9689
9772
  // ランク描画
@@ -9729,7 +9812,7 @@ function resultInit() {
9729
9812
 
9730
9813
  // ハイスコア差分計算
9731
9814
  const assistFlg = (g_autoPlaysBase.includes(g_stateObj.autoPlay) ? `` : `-${g_stateObj.autoPlay}less`);
9732
- let scoreName = `${g_headerObj.keyLabels[g_stateObj.scoreId]}k-${g_headerObj.difLabels[g_stateObj.scoreId]}${assistFlg}`;
9815
+ let scoreName = `${g_headerObj.keyLabels[g_stateObj.scoreId]}${getStgDetailName('k-')}${g_headerObj.difLabels[g_stateObj.scoreId]}${assistFlg}`;
9733
9816
  if (g_headerObj.makerView) {
9734
9817
  scoreName += `-${g_headerObj.creatorNames[g_stateObj.scoreId]}`;
9735
9818
  }
@@ -9757,18 +9840,13 @@ function resultInit() {
9757
9840
  });
9758
9841
 
9759
9842
  } else {
9760
- resultWindow.appendChild(makeCssResultSymbol(`lblAutoView`, 230, g_cssObj.result_noRecord, 4, `(No Record)`));
9843
+ resultWindow.appendChild(makeCssResultSymbol(`lblAutoView`, 215, g_cssObj.result_noRecord, 4, `(No Record)`));
9761
9844
  const lblAutoView = document.querySelector(`#lblAutoView`);
9762
- lblAutoView.style.fontSize = `24px`;
9845
+ lblAutoView.style.fontSize = `20px`;
9763
9846
  }
9764
9847
 
9765
9848
  // ユーザカスタムイベント(初期)
9766
- if (typeof customResultInit === C_TYP_FUNCTION) {
9767
- customResultInit();
9768
- if (typeof customResultInit2 === C_TYP_FUNCTION) {
9769
- customResultInit2();
9770
- }
9771
- }
9849
+ g_customJsObj.result.forEach(func => func());
9772
9850
 
9773
9851
  if (highscoreCondition) {
9774
9852
 
@@ -9818,7 +9896,7 @@ function resultInit() {
9818
9896
  // Twitter用リザルト
9819
9897
  // スコアを上塗りする可能性があるため、カスタムイベント後に配置
9820
9898
  const hashTag = (g_headerObj.hashTag !== undefined ? ` ${g_headerObj.hashTag}` : ``);
9821
- let tweetDifData = `${getKeyName(g_headerObj.keyLabels[g_stateObj.scoreId])}${transKeyData}k-${g_headerObj.difLabels[g_stateObj.scoreId]}${assistFlg}`;
9899
+ let tweetDifData = `${getKeyName(g_headerObj.keyLabels[g_stateObj.scoreId])}${transKeyData}${getStgDetailName('k-')}${g_headerObj.difLabels[g_stateObj.scoreId]}${assistFlg}`;
9822
9900
  if (g_stateObj.shuffle !== `OFF`) {
9823
9901
  tweetDifData += `:${getShuffleName()}`;
9824
9902
  }
@@ -9869,8 +9947,7 @@ function resultInit() {
9869
9947
 
9870
9948
  // リザルトデータをクリップボードへコピー
9871
9949
  createCss2Button(`btnCopy`, g_lblNameObj.b_copy, _ => {
9872
- copyTextToClipboard(resultText);
9873
- makeInfoWindow(g_msgInfoObj.I_0001, `leftToRightFade`);
9950
+ copyTextToClipboard(resultText, g_msgInfoObj.I_0001);
9874
9951
  }, {
9875
9952
  x: g_sWidth / 4,
9876
9953
  w: g_sWidth / 2,
@@ -9928,12 +10005,7 @@ function resultInit() {
9928
10005
  function flowResultTimeline() {
9929
10006
 
9930
10007
  // ユーザカスタムイベント(フレーム毎)
9931
- if (typeof customResultEnterFrame === C_TYP_FUNCTION) {
9932
- customResultEnterFrame();
9933
- if (typeof customResultEnterFrame2 === C_TYP_FUNCTION) {
9934
- customResultEnterFrame2();
9935
- }
9936
- }
10008
+ g_customJsObj.resultEnterFrame.forEach(func => func());
9937
10009
 
9938
10010
  // 背景・マスクモーション
9939
10011
  drawTitleResultMotion(g_currentPage);
@@ -9969,12 +10041,7 @@ function resultInit() {
9969
10041
  setShortcutEvent(g_currentPage);
9970
10042
  document.oncontextmenu = _ => true;
9971
10043
 
9972
- if (typeof skinResultInit === C_TYP_FUNCTION) {
9973
- skinResultInit();
9974
- if (typeof skinResultInit2 === C_TYP_FUNCTION) {
9975
- skinResultInit2();
9976
- }
9977
- }
10044
+ g_skinJsObj.result.forEach(func => func());
9978
10045
  }
9979
10046
 
9980
10047
  /**