danoniplus 30.5.0 → 31.0.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 : 2023/03/12
7
+ * Revised : 2023/03/20
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 30.5.0`;
12
- const g_revisedDate = `2023/03/12`;
11
+ const g_version = `Ver 31.0.0`;
12
+ const g_revisedDate = `2023/03/20`;
13
13
  const g_alphaVersion = ``;
14
14
 
15
15
  // カスタム用バージョン (danoni_custom.js 等で指定可)
@@ -115,7 +115,9 @@ let g_finishFlg = true;
115
115
  /** 共通オブジェクト */
116
116
  const g_loadObj = {};
117
117
  const g_rootObj = {};
118
- const g_presetObj = {};
118
+ const g_presetObj = {
119
+ keysDataLib: [],
120
+ };
119
121
  let g_headerObj = {};
120
122
  let g_scoreObj = {};
121
123
  let g_attrObj = {};
@@ -1873,9 +1875,13 @@ const initialControl = async () => {
1873
1875
 
1874
1876
  // 譜面ヘッダー、特殊キー情報の読込
1875
1877
  Object.assign(g_headerObj, headerConvert(g_rootObj));
1876
- if (g_presetObj.keysData !== undefined) {
1877
- keysConvert(dosConvert(g_presetObj.keysData));
1878
+ const importKeysData = _data => {
1879
+ keysConvert(dosConvert(_data));
1878
1880
  g_headerObj.undefinedKeyLists = g_headerObj.undefinedKeyLists.filter(key => g_keyObj[`chara${key}_0`] === undefined);
1881
+ };
1882
+ g_presetObj.keysDataLib.forEach(list => importKeysData(list));
1883
+ if (g_presetObj.keysData !== undefined) {
1884
+ importKeysData(g_presetObj.keysData);
1879
1885
  }
1880
1886
  g_headerObj.keyExtraList = keysConvert(g_rootObj, {
1881
1887
  keyExtraList: (g_rootObj.keyExtraList !== undefined ?
@@ -2017,11 +2023,12 @@ const loadLocalStorage = _ => {
2017
2023
  if (checkStorage) {
2018
2024
  g_localStorage = JSON.parse(checkStorage);
2019
2025
 
2020
- // Adjustment, Volume, Appearance, Opacity初期値設定
2021
- checkLocalParam(`adjustment`, C_TYP_FLOAT, C_MAX_ADJUSTMENT);
2026
+ // Adjustment, Volume, Appearance, Opacity, hitPosition初期値設定
2027
+ checkLocalParam(`adjustment`, C_TYP_FLOAT, g_settings.adjustmentNum);
2022
2028
  checkLocalParam(`volume`, C_TYP_NUMBER, g_settings.volumes.length - 1);
2023
2029
  checkLocalParam(`appearance`);
2024
2030
  checkLocalParam(`opacity`, C_TYP_NUMBER, g_settings.opacitys.length - 1);
2031
+ checkLocalParam(`hitPosition`, C_TYP_FLOAT, g_settings.hitPositionNum);
2025
2032
 
2026
2033
  // ハイスコア取得準備
2027
2034
  if (g_localStorage.highscores === undefined) {
@@ -2038,6 +2045,7 @@ const loadLocalStorage = _ => {
2038
2045
  } else {
2039
2046
  g_localStorage = {
2040
2047
  adjustment: 0,
2048
+ hitPosition: 0,
2041
2049
  volume: 100,
2042
2050
  highscores: {},
2043
2051
  };
@@ -2453,6 +2461,7 @@ const preheaderConvert = _dosObj => {
2453
2461
  }
2454
2462
 
2455
2463
  obj.jsData = [];
2464
+ obj.stepRtnUse = true;
2456
2465
 
2457
2466
  const setJsFiles = (_files, _defaultDir, _type = `custom`) => {
2458
2467
  _files.forEach(file => {
@@ -3496,9 +3505,9 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList.split(`,`) }
3496
3505
  }
3497
3506
  const keyPtn = getKeyPtnName(tmpArray[k]);
3498
3507
  g_keyObj[`${keyheader}_${k + dfPtn}`] = g_keyObj[`${_name}${keyPtn}`] !== undefined ?
3499
- copyArray2d(g_keyObj[`${_name}${keyPtn}`]) : tmpArray[k].split(`,`).map(n => _convFunc(n));
3508
+ structuredClone(g_keyObj[`${_name}${keyPtn}`]) : tmpArray[k].split(`,`).map(n => _convFunc(n));
3500
3509
  if (baseCopyFlg) {
3501
- g_keyObj[`${keyheader}_${k + dfPtn}d`] = copyArray2d(g_keyObj[`${keyheader}_${k + dfPtn}`]);
3510
+ g_keyObj[`${keyheader}_${k + dfPtn}d`] = structuredClone(g_keyObj[`${keyheader}_${k + dfPtn}`]);
3502
3511
  }
3503
3512
  loopFunc(k, keyheader);
3504
3513
  }
@@ -3543,7 +3552,7 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList.split(`,`) }
3543
3552
  }
3544
3553
  } else {
3545
3554
  // 通常の指定方法 (例: |shuffle8i=1,1,1,2,0,0,0,0/1,1,1,1,0,0,0,0| )の場合の取り込み
3546
- g_keyObj[`${keyheader}_${k + dfPtn}_${ptnCnt}`] = list.split(`,`).map(n => parseInt(n, 10));
3555
+ g_keyObj[`${keyheader}_${k + dfPtn}_${ptnCnt}`] = list.split(`,`).map(n => isNaN(Number(n)) ? n : parseInt(n, 10));
3547
3556
  ptnCnt++;
3548
3557
  }
3549
3558
  });
@@ -3647,7 +3656,7 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList.split(`,`) }
3647
3656
  newKeyTripleParam(newKey, `color`);
3648
3657
 
3649
3658
  // 矢印の回転量指定、キャラクタパターン (stepRtnX_Y)
3650
- newKeyMultiParam(newKey, `stepRtn`, toStringOrNumber, { errCd: `E_0103` });
3659
+ newKeyTripleParam(newKey, `stepRtn`);
3651
3660
 
3652
3661
  // キーコンフィグ (keyCtrlX_Y)
3653
3662
  newKeyMultiParam(newKey, `keyCtrl`, toKeyCtrlArray, { errCd: `E_0104`, baseCopyFlg: true });
@@ -4236,9 +4245,9 @@ const createOptionWindow = _sprite => {
4236
4245
  [`shuffle`, 5.5, 0, 0, 0],
4237
4246
  [`autoPlay`, 6.5, 0, 0, 0],
4238
4247
  [`gauge`, 7.5, 0, 0, 0],
4239
- [`adjustment`, 10, 0, 0, 0],
4240
- [`fadein`, 11, 0, 0, 0],
4241
- [`volume`, 12, 0, 0, 0],
4248
+ [`adjustment`, 10.5, 0, 0, 0],
4249
+ [`fadein`, 11.5, 0, 0, 0],
4250
+ [`volume`, 12.5, 0, 0, 0],
4242
4251
  ];
4243
4252
 
4244
4253
  // 設定毎に個別のスプライトを作成し、その中にラベル・ボタン類を配置
@@ -4912,7 +4921,7 @@ const createOptionWindow = _sprite => {
4912
4921
  g_gaugeType = (g_gaugeOptionObj.custom.length > 0 ? C_LFE_CUSTOM : g_stateObj.lifeMode);
4913
4922
 
4914
4923
  g_stateObj.lifeVariable = g_gaugeOptionObj[`var${g_gaugeType}`][_gaugeNum];
4915
- g_settings.gauges = copyArray2d(g_gaugeOptionObj[g_gaugeType.toLowerCase()]);
4924
+ g_settings.gauges = structuredClone(g_gaugeOptionObj[g_gaugeType.toLowerCase()]);
4916
4925
  g_stateObj.gauge = g_settings.gauges[g_settings.gaugeNum];
4917
4926
  }
4918
4927
  setLifeCategory(g_headerObj);
@@ -5014,7 +5023,7 @@ const createOptionWindow = _sprite => {
5014
5023
 
5015
5024
  // ---------------------------------------------------
5016
5025
  // タイミング調整 (Adjustment)
5017
- // 縦位置: 10 短縮ショートカットあり
5026
+ // 縦位置: 10.5 短縮ショートカットあり
5018
5027
  createGeneralSetting(spriteList.adjustment, `adjustment`, {
5019
5028
  skipTerms: g_settings.adjustmentTerms, hiddenBtn: true, scLabel: g_lblNameObj.sc_adjustment, roundNum: 5,
5020
5029
  unitName: g_lblNameObj.frame,
@@ -5022,7 +5031,7 @@ const createOptionWindow = _sprite => {
5022
5031
 
5023
5032
  // ---------------------------------------------------
5024
5033
  // フェードイン (Fadein)
5025
- // 縦位置: 11 スライダーあり
5034
+ // 縦位置: 11.5 スライダーあり
5026
5035
  spriteList.fadein.appendChild(createLblSetting(`Fadein`));
5027
5036
 
5028
5037
  const lnkFadein = createDivCss2Label(`lnkFadein`, `${g_stateObj.fadein}${g_lblNameObj.percent}`,
@@ -5053,7 +5062,7 @@ const createOptionWindow = _sprite => {
5053
5062
 
5054
5063
  // ---------------------------------------------------
5055
5064
  // ボリューム (Volume)
5056
- // 縦位置: 12
5065
+ // 縦位置: 12.5
5057
5066
  createGeneralSetting(spriteList.volume, `volume`, { unitName: g_lblNameObj.percent });
5058
5067
 
5059
5068
  /**
@@ -5163,7 +5172,7 @@ const createOptionWindow = _sprite => {
5163
5172
  }
5164
5173
 
5165
5174
  // スクロール設定用の配列を入れ替え
5166
- g_settings.scrolls = copyArray2d(
5175
+ g_settings.scrolls = structuredClone(
5167
5176
  typeof g_keyObj[`scrollDir${g_keyObj.currentKey}_${g_keyObj.currentPtn}`] === C_TYP_OBJECT ?
5168
5177
  Object.keys(g_keyObj[`scrollDir${g_keyObj.currentKey}_${g_keyObj.currentPtn}`]) : g_keyObj.scrollName_def
5169
5178
  );
@@ -5222,7 +5231,7 @@ const createOptionWindow = _sprite => {
5222
5231
  setReverseView(document.querySelector(`#btnReverse`));
5223
5232
  }
5224
5233
  } else {
5225
- g_settings.scrolls = copyArray2d(g_keyObj.scrollName_def);
5234
+ g_settings.scrolls = structuredClone(g_keyObj.scrollName_def);
5226
5235
  setSetting(0, `reverse`);
5227
5236
  }
5228
5237
 
@@ -5259,12 +5268,12 @@ const createOptionWindow = _sprite => {
5259
5268
  */
5260
5269
  const createGeneralSetting = (_obj, _settingName, { unitName = ``,
5261
5270
  skipTerms = [...Array(3)].fill(1), hiddenBtn = false, addRFunc = _ => { }, addLFunc = _ => { },
5262
- settingLabel = _settingName, displayName = `option`, scLabel = ``, roundNum = 0 } = {}) => {
5271
+ settingLabel = _settingName, displayName = g_currentPage, scLabel = ``, roundNum = 0, adjY = 0 } = {}) => {
5263
5272
 
5264
5273
  const settingUpper = toCapitalize(_settingName);
5265
5274
  const linkId = `lnk${settingUpper}`;
5266
5275
  const initName = `${getStgDetailName(g_stateObj[_settingName])}${unitName}`;
5267
- _obj.appendChild(createLblSetting(settingUpper, 0, toCapitalize(settingLabel)));
5276
+ _obj.appendChild(createLblSetting(settingUpper, adjY, toCapitalize(settingLabel)));
5268
5277
 
5269
5278
  if (g_headerObj[`${_settingName}Use`] === undefined || g_headerObj[`${_settingName}Use`]) {
5270
5279
 
@@ -5439,7 +5448,7 @@ const getKeyCtrl = (_localStorage, _extraKeyName = ``) => {
5439
5448
  const isUpdate = prevPtn !== -1 && g_keyObj.prevKey !== g_keyObj.currentKey;
5440
5449
  g_keyCopyLists.multiple.forEach(header => {
5441
5450
  if (g_keyObj[`${header}${basePtn}`] !== undefined && isUpdate) {
5442
- g_keyObj[`${header}${copyPtn}`] = copyArray2d(g_keyObj[`${header}${basePtn}`]);
5451
+ g_keyObj[`${header}${copyPtn}`] = structuredClone(g_keyObj[`${header}${basePtn}`]);
5443
5452
  }
5444
5453
  });
5445
5454
  g_keyCopyLists.simple.forEach(header => {
@@ -5452,7 +5461,7 @@ const getKeyCtrl = (_localStorage, _extraKeyName = ``) => {
5452
5461
  maxPtn++;
5453
5462
  }
5454
5463
  for (let j = 0; j < maxPtn; j++) {
5455
- g_keyObj[`${type}${copyPtn}_${j}`] = copyArray2d(g_keyObj[`${type}${basePtn}_${j}`]);
5464
+ g_keyObj[`${type}${copyPtn}_${j}`] = structuredClone(g_keyObj[`${type}${basePtn}_${j}`]);
5456
5465
  }
5457
5466
  g_keyObj[`${type}${copyPtn}_0d`] = structuredClone(g_keyObj[`${type}${copyPtn}_0`]);
5458
5467
  });
@@ -5631,6 +5640,7 @@ const createSettingsDisplayWindow = _sprite => {
5631
5640
  const settingList = [
5632
5641
  [`appearance`, 7.4, 10, 0, 0],
5633
5642
  [`opacity`, 9, 10, 0, 0],
5643
+ [`hitPosition`, 10, 10, 0, 0],
5634
5644
  ];
5635
5645
 
5636
5646
  // 設定毎に個別のスプライトを作成し、その中にラベル・ボタン類を配置
@@ -5644,7 +5654,6 @@ const createSettingsDisplayWindow = _sprite => {
5644
5654
  // 矢印の見え方 (Appearance)
5645
5655
  // 縦位置: 7.4
5646
5656
  createGeneralSetting(spriteList.appearance, `appearance`, {
5647
- displayName: g_currentPage,
5648
5657
  addRFunc: _ => dispAppearanceSlider(),
5649
5658
  addLFunc: _ => dispAppearanceSlider(),
5650
5659
  });
@@ -5688,8 +5697,16 @@ const createSettingsDisplayWindow = _sprite => {
5688
5697
  opacityUse ||= g_headerObj[`${display}Use`] || g_headerObj[`${display}Set`] === C_FLG_ON);
5689
5698
 
5690
5699
  if (opacityUse) {
5691
- createGeneralSetting(spriteList.opacity, `opacity`, { unitName: g_lblNameObj.percent, displayName: g_currentPage });
5700
+ createGeneralSetting(spriteList.opacity, `opacity`, { unitName: g_lblNameObj.percent });
5692
5701
  }
5702
+
5703
+ // ---------------------------------------------------
5704
+ // タイミング調整 (HitPosition)
5705
+ // 縦位置: 10
5706
+ createGeneralSetting(spriteList.hitPosition, `hitPosition`, {
5707
+ skipTerms: g_settings.hitPositionTerms, scLabel: g_lblNameObj.sc_hitPosition, roundNum: 5,
5708
+ unitName: g_lblNameObj.pixel,
5709
+ });
5693
5710
  };
5694
5711
 
5695
5712
  /**
@@ -5879,11 +5896,11 @@ const keyConfigInit = (_kcType = g_kcType) => {
5879
5896
  // 矢印の塗り部分
5880
5897
  createColorObject2(`arrowShadow${j}`, {
5881
5898
  x: keyconX, y: keyconY, background: hasVal(g_headerObj[`setShadowColor${g_colorType}`][colorPos]) ? getShadowColor(colorPos, arrowColor) : ``,
5882
- rotate: g_keyObj[`stepRtn${keyCtrlPtn}`][j], styleName: `Shadow`, pointerEvents: `none`,
5899
+ rotate: g_keyObj[`stepRtn${keyCtrlPtn}_${g_keycons.stepRtnGroupNum}`][j], styleName: `Shadow`, pointerEvents: `none`,
5883
5900
  }),
5884
5901
  // 矢印本体
5885
5902
  createColorObject2(`arrow${j}`, {
5886
- x: keyconX, y: keyconY, background: arrowColor, rotate: g_keyObj[`stepRtn${keyCtrlPtn}`][j], pointerEvents: `none`,
5903
+ x: keyconX, y: keyconY, background: arrowColor, rotate: g_keyObj[`stepRtn${keyCtrlPtn}_${g_keycons.stepRtnGroupNum}`][j], pointerEvents: `none`,
5887
5904
  }),
5888
5905
  );
5889
5906
  if (g_headerObj.shuffleUse && g_keyObj[`shuffle${keyCtrlPtn}`] !== undefined) {
@@ -5905,6 +5922,7 @@ const keyConfigInit = (_kcType = g_kcType) => {
5905
5922
  createCss2Button(`keycon${j}_${k}`, g_kCd[g_keyObj[`keyCtrl${keyCtrlPtn}`][j][k]], _ => {
5906
5923
  g_currentj = j;
5907
5924
  g_currentk = k;
5925
+ g_prevKey = -1;
5908
5926
  g_keycons.cursorNum = g_keycons.cursorNumList.findIndex(val => val === g_currentj);
5909
5927
  setKeyConfigCursor();
5910
5928
  }, {
@@ -5948,6 +5966,7 @@ const keyConfigInit = (_kcType = g_kcType) => {
5948
5966
  }
5949
5967
  }
5950
5968
  },
5969
+ stepRtn: (_type = ``) => { },
5951
5970
  };
5952
5971
 
5953
5972
  /**
@@ -5972,6 +5991,9 @@ const keyConfigInit = (_kcType = g_kcType) => {
5972
5991
  g_keycons[`${_type}GroupNum`] = g_keycons[`${_type}Groups`][getNextNum(_scrollNum, `${_type}Groups`, g_keycons[`${_type}GroupNum`])];
5973
5992
  g_keyObj[`${_type}${keyCtrlPtn}`] = structuredClone(g_keyObj[`${_type}${keyCtrlPtn}_${g_keycons[`${_type}GroupNum`]}`]);
5974
5993
  viewGroup(_type);
5994
+ if (_type === `stepRtn`) {
5995
+ keyConfigInit(g_kcType);
5996
+ }
5975
5997
  };
5976
5998
 
5977
5999
  /**
@@ -6021,16 +6043,16 @@ const keyConfigInit = (_kcType = g_kcType) => {
6021
6043
  * @param {string} _type
6022
6044
  * @param {object} obj (baseX)
6023
6045
  */
6024
- const makeGroupButton = (_type, { baseX = g_sWidth * 5 / 6 - 20, cssName } = {}) => {
6046
+ const makeGroupButton = (_type, { baseX = g_sWidth * 5 / 6 - 20, baseY = 0, cssName } = {}) => {
6025
6047
  if (g_headerObj[`${_type}Use`] && g_keycons[`${_type}Groups`].length > 1) {
6026
6048
  const typeName = toCapitalize(_type);
6027
6049
  multiAppend(divRoot,
6028
- makeKCButtonHeader(`lbl${_type}Group`, `${typeName}Group`, { x: baseX - 10, y: 37 }, cssName),
6050
+ makeKCButtonHeader(`lbl${_type}Group`, `${typeName}Group`, { x: baseX - 10, y: baseY }, cssName),
6029
6051
  makeKCButton(`lnk${typeName}Group`, ``, _ => setGroup(_type), {
6030
- x: baseX, y: 50, w: g_sWidth / 18, title: g_msgObj[`${_type}Group`], cxtFunc: _ => setGroup(_type, -1),
6052
+ x: baseX, y: baseY + 13, w: g_sWidth / 18, title: g_msgObj[`${_type}Group`], cxtFunc: _ => setGroup(_type, -1),
6031
6053
  }),
6032
- makeMiniKCButton(`lnk${typeName}Group`, `L`, _ => setGroup(_type, -1), { x: baseX - 10, y: 50 }),
6033
- makeMiniKCButton(`lnk${typeName}Group`, `R`, _ => setGroup(_type), { x: baseX + g_sWidth / 18, y: 50 }),
6054
+ makeMiniKCButton(`lnk${typeName}Group`, `L`, _ => setGroup(_type, -1), { x: baseX - 10, y: baseY + 13 }),
6055
+ makeMiniKCButton(`lnk${typeName}Group`, `R`, _ => setGroup(_type), { x: baseX + g_sWidth / 18, y: baseY + 13 }),
6034
6056
  );
6035
6057
  } else {
6036
6058
  g_keycons[`${_type}GroupNum`] = 0;
@@ -6051,19 +6073,13 @@ const keyConfigInit = (_kcType = g_kcType) => {
6051
6073
  g_lblPosObj.kcMsg, g_cssObj.keyconfig_warning
6052
6074
  ),
6053
6075
 
6054
- // キーコンフィグタイプ切替ボタン
6055
- makeKCButtonHeader(`lblKcType`, `ConfigType`, { x: 10 }, g_cssObj.keyconfig_ConfigType),
6056
- makeKCButton(`lnkKcType`, g_kcType, _ => setConfigType(), {
6057
- x: 20, title: g_msgObj.configType, cxtFunc: _ => setConfigType(-1),
6058
- }),
6059
-
6060
6076
  // キーカラータイプ切替ボタン
6061
- makeKCButtonHeader(`lblcolorType`, `ColorType`, {}, g_cssObj.keyconfig_ColorType),
6077
+ makeKCButtonHeader(`lblcolorType`, `ColorType`, { x: 10 }, g_cssObj.keyconfig_ColorType),
6062
6078
  makeKCButton(`lnkColorType`, g_colorType, _ => setColorType(), {
6063
- title: g_msgObj.colorType, cxtFunc: _ => setColorType(-1),
6079
+ x: 20, title: g_msgObj.colorType, cxtFunc: _ => setColorType(-1),
6064
6080
  }),
6065
- makeMiniKCButton(`lnkColorType`, `L`, _ => setColorType(-1)),
6066
- makeMiniKCButton(`lnkColorType`, `R`, _ => setColorType(), { x: g_sWidth - 20 }),
6081
+ makeMiniKCButton(`lnkColorType`, `L`, _ => setColorType(-1), { x: 10 }),
6082
+ makeMiniKCButton(`lnkColorType`, `R`, _ => setColorType(), { x: 20 + g_sWidth / 6 }),
6067
6083
  );
6068
6084
 
6069
6085
  if (g_headerObj.imgType.length > 1) {
@@ -6082,6 +6098,7 @@ const keyConfigInit = (_kcType = g_kcType) => {
6082
6098
  // カラー/シャッフルグループ切替ボタン(カラー/シャッフルパターンが複数ある場合のみ)
6083
6099
  makeGroupButton(`color`, { cssName: g_cssObj.keyconfig_ColorType });
6084
6100
  makeGroupButton(`shuffle`, { baseX: g_sWidth * 11 / 12 - 10, cssName: g_cssObj.settings_Shuffle });
6101
+ makeGroupButton(`stepRtn`, { baseY: 37, cssName: g_cssObj.settings_Adjustment });
6085
6102
 
6086
6103
  /**
6087
6104
  * カーソル位置の設定
@@ -6094,10 +6111,7 @@ const keyConfigInit = (_kcType = g_kcType) => {
6094
6111
  cursor.style.left = `${nextLeft}px`;
6095
6112
  const baseY = C_KYC_HEIGHT * Number(posj > divideCnt) + 57;
6096
6113
  cursor.style.top = `${baseY + C_KYC_REPHEIGHT * g_currentk}px`;
6097
- if (g_currentk === 0 && g_kcType === `Replaced`) {
6098
- g_kcType = C_FLG_ALL;
6099
- lnkKcType.textContent = getStgDetailName(g_kcType);
6100
- }
6114
+ g_kcType = (g_currentk === 0 ? `Main` : `Replaced`);
6101
6115
 
6102
6116
  // 次の位置が見えなくなったらkeyconSpriteの位置を調整する
6103
6117
  adjustScrollPoint(nextLeft);
@@ -6112,9 +6126,23 @@ const keyConfigInit = (_kcType = g_kcType) => {
6112
6126
 
6113
6127
  g_currentj = g_keycons.cursorNumList[_nextj];
6114
6128
  g_currentk = 0;
6115
- if (g_kcType === `Replaced` && (g_keyObj[`keyCtrl${keyCtrlPtn}`][g_currentj][1] !== undefined)) {
6129
+ if (g_kcType === `Replaced`) {
6116
6130
  g_currentk = 1;
6131
+
6132
+ // 代替キー設定の場合は次の代替キーが見つかるまで移動
6133
+ while (g_keyObj[`keyCtrl${keyCtrlPtn}`][g_currentj][1] === undefined) {
6134
+ g_keycons.cursorNum = (g_keycons.cursorNum + 1) % g_keycons.cursorNumList.length;
6135
+ g_currentj = g_keycons.cursorNumList[g_keycons.cursorNum];
6136
+
6137
+ // 一周して対象が無い場合は代替キーが無いため処理を抜ける(無限ループ対策)
6138
+ if (g_keycons.cursorNum === _nextj) {
6139
+ g_kcType = `Main`;
6140
+ g_currentk = 0;
6141
+ break;
6142
+ }
6143
+ }
6117
6144
  }
6145
+
6118
6146
  setKeyConfigCursor();
6119
6147
  keyconSprite.scrollLeft = - maxLeftX;
6120
6148
  };
@@ -6131,7 +6159,6 @@ const keyConfigInit = (_kcType = g_kcType) => {
6131
6159
  const setConfigType = (_scrollNum = 1) => {
6132
6160
  g_kcType = g_keycons.configTypes[getNextNum(_scrollNum, `configTypes`, g_kcType)];
6133
6161
  changeConfigCursor(g_keycons.cursorNum);
6134
- lnkKcType.textContent = getStgDetailName(g_kcType);
6135
6162
  };
6136
6163
 
6137
6164
  /**
@@ -6518,12 +6545,12 @@ const changeSetColor = _ => {
6518
6545
  'Shadow': (isDefault ? defaultType : `${scoreIdHeader}Default`),
6519
6546
  };
6520
6547
  Object.keys(currentTypes).forEach(pattern => {
6521
- g_headerObj[`set${pattern}Color`] = copyArray2d(g_headerObj[`set${pattern}Color${currentTypes[pattern]}`]);
6548
+ g_headerObj[`set${pattern}Color`] = structuredClone(g_headerObj[`set${pattern}Color${currentTypes[pattern]}`]);
6522
6549
  for (let j = 0; j < g_headerObj.setColorInit.length; j++) {
6523
- g_headerObj[`frz${pattern}Color`][j] = copyArray2d(g_headerObj[`frz${pattern}Color${currentTypes[pattern]}`][j]);
6550
+ g_headerObj[`frz${pattern}Color`][j] = structuredClone(g_headerObj[`frz${pattern}Color${currentTypes[pattern]}`][j]);
6524
6551
  }
6525
6552
  if (!isDefault) {
6526
- g_headerObj[`set${pattern}Color`] = copyArray2d(g_headerObj[`set${pattern}Color${g_colorType}`]);
6553
+ g_headerObj[`set${pattern}Color`] = structuredClone(g_headerObj[`set${pattern}Color${g_colorType}`]);
6527
6554
  }
6528
6555
  });
6529
6556
 
@@ -6766,7 +6793,7 @@ const loadingScoreInit = async () => {
6766
6793
 
6767
6794
  // Motionオプション適用時の矢印別の速度を取得(配列形式)
6768
6795
  const motionOnFrame = setMotionOnFrame();
6769
- g_workObj.motionOnFrames = copyArray2d(motionOnFrame);
6796
+ g_workObj.motionOnFrames = structuredClone(motionOnFrame);
6770
6797
 
6771
6798
  // 最初のフレームで出現する矢印が、ステップゾーンに到達するまでのフレーム数を取得
6772
6799
  const firstFrame = (g_scoreObj.frameNum === 0 ? 0 : g_scoreObj.frameNum + g_headerObj.blankFrame);
@@ -6782,8 +6809,8 @@ const loadingScoreInit = async () => {
6782
6809
  // フレーム・曲開始位置調整
6783
6810
  let preblankFrame = 0;
6784
6811
  if (g_scoreObj.frameNum === 0) {
6785
- if (firstArrowFrame - C_MAX_ADJUSTMENT < arrivalFrame) {
6786
- preblankFrame = arrivalFrame - firstArrowFrame + C_MAX_ADJUSTMENT;
6812
+ if (firstArrowFrame - g_limitObj.adjustment < arrivalFrame) {
6813
+ preblankFrame = arrivalFrame - firstArrowFrame + g_limitObj.adjustment;
6787
6814
 
6788
6815
  // 譜面データの再読み込み
6789
6816
  const noteExistObj = {
@@ -6796,7 +6823,7 @@ const loadingScoreInit = async () => {
6796
6823
  for (let j = 0; j < keyNum; j++) {
6797
6824
  Object.keys(noteExistObj).forEach(name => {
6798
6825
  if (tmpObj[`${name}Data`][j] !== undefined && noteExistObj[name]) {
6799
- g_scoreObj[`${name}Data`][j] = copyArray2d(tmpObj[`${name}Data`][j]);
6826
+ g_scoreObj[`${name}Data`][j] = structuredClone(tmpObj[`${name}Data`][j]);
6800
6827
  }
6801
6828
  });
6802
6829
  }
@@ -6915,7 +6942,7 @@ const applyShuffle = (_keyNum, _shuffleGroup, _style) => {
6915
6942
 
6916
6943
  // indexに従って並べ替え
6917
6944
  g_typeLists.arrow.forEach(type => {
6918
- const tmpData = copyArray2d(g_scoreObj[`${type}Data`]);
6945
+ const tmpData = structuredClone(g_scoreObj[`${type}Data`]);
6919
6946
  for (let i = 0; i < _keyNum; i++) {
6920
6947
  g_scoreObj[`${type}Data`][i] = tmpData[index[i]] || [];
6921
6948
  }
@@ -6929,7 +6956,7 @@ const applyShuffle = (_keyNum, _shuffleGroup, _style) => {
6929
6956
  */
6930
6957
  const applyMirror = (_keyNum, _shuffleGroup, _asymFlg = false) => {
6931
6958
  // シャッフルグループごとにミラー
6932
- const style = copyArray2d(_shuffleGroup).map(_group => _group.reverse());
6959
+ const style = structuredClone(_shuffleGroup).map(_group => _group.reverse());
6933
6960
  if (_asymFlg) {
6934
6961
  // グループが4の倍数のとき、4n+1, 4n+2のみ入れ替える
6935
6962
  style.forEach((group, i) => {
@@ -6950,7 +6977,7 @@ const applyMirror = (_keyNum, _shuffleGroup, _asymFlg = false) => {
6950
6977
  */
6951
6978
  const applyRandom = (_keyNum, _shuffleGroup) => {
6952
6979
  // シャッフルグループごとにシャッフル(Fisher-Yates)
6953
- const style = copyArray2d(_shuffleGroup).map(_group => {
6980
+ const style = structuredClone(_shuffleGroup).map(_group => {
6954
6981
  for (let i = _group.length - 1; i > 0; i--) {
6955
6982
  const random = Math.floor(Math.random() * (i + 1));
6956
6983
  const tmp = _group[i];
@@ -7538,7 +7565,7 @@ const getFirstArrowFrame = (_dataObj, _keyCtrlPtn = `${g_keyObj.currentKey}_${g_
7538
7565
 
7539
7566
  data.filter(data => hasVal(data)).forEach(_objData => {
7540
7567
  if (_objData[0] !== ``) {
7541
- if (_objData[0] < tmpFirstNum && _objData[0] + C_MAX_ADJUSTMENT > 0) {
7568
+ if (_objData[0] < tmpFirstNum && _objData[0] + g_limitObj.adjustment > 0) {
7542
7569
  tmpFirstNum = _objData[0];
7543
7570
  }
7544
7571
  }
@@ -7685,7 +7712,7 @@ const pushArrows = (_dataObj, _speedOnFrame, _motionOnFrame, _firstArrivalFrame)
7685
7712
  g_workObj[`mk${_header}Length`][_j][_k] = getFrzLength(_speedOnFrame, _data[_k], _data[_k + 1]);
7686
7713
  }
7687
7714
  } else if (_frzFlg && g_workObj[`mk${_header}Length`][_j] !== undefined) {
7688
- g_workObj[`mk${_header}Length`][_j] = copyArray2d(g_workObj[`mk${_header}Length`][_j].slice(_k + 2));
7715
+ g_workObj[`mk${_header}Length`][_j] = structuredClone(g_workObj[`mk${_header}Length`][_j].slice(_k + 2));
7689
7716
  }
7690
7717
  };
7691
7718
 
@@ -7726,7 +7753,7 @@ const pushArrows = (_dataObj, _speedOnFrame, _motionOnFrame, _firstArrivalFrame)
7726
7753
 
7727
7754
  // 出現位置が開始前の場合は除外
7728
7755
  if (_frzFlg && g_workObj[`mk${camelHeader}Length`][_j] !== undefined) {
7729
- g_workObj[`mk${camelHeader}Length`][_j] = copyArray2d(g_workObj[`mk${camelHeader}Length`][_j].slice(k + 2));
7756
+ g_workObj[`mk${camelHeader}Length`][_j] = structuredClone(g_workObj[`mk${camelHeader}Length`][_j].slice(k + 2));
7730
7757
  }
7731
7758
  break;
7732
7759
 
@@ -7792,7 +7819,7 @@ const pushArrows = (_dataObj, _speedOnFrame, _motionOnFrame, _firstArrivalFrame)
7792
7819
  for (let k = 0; k < delIdx; k++) {
7793
7820
  _data.shift();
7794
7821
  }
7795
- return copyArray2d(_data);
7822
+ return structuredClone(_data);
7796
7823
  }
7797
7824
  return [];
7798
7825
  };
@@ -8208,10 +8235,10 @@ const getArrowSettings = _ => {
8208
8235
  g_workObj.scrollDir = [];
8209
8236
  g_workObj.scrollDirDefault = [];
8210
8237
  g_workObj.dividePos = [];
8211
- g_workObj.stepRtn = copyArray2d(g_keyObj[`stepRtn${keyCtrlPtn}`]);
8212
- g_workObj.stepHitRtn = copyArray2d(g_keyObj[`stepRtn${keyCtrlPtn}`]);
8213
- g_workObj.arrowRtn = copyArray2d(g_keyObj[`stepRtn${keyCtrlPtn}`]);
8214
- g_workObj.keyCtrl = copyArray2d(g_keyObj[`keyCtrl${keyCtrlPtn}`]);
8238
+ g_workObj.stepRtn = structuredClone(g_keyObj[`stepRtn${keyCtrlPtn}`]);
8239
+ g_workObj.stepHitRtn = structuredClone(g_keyObj[`stepRtn${keyCtrlPtn}`]);
8240
+ g_workObj.arrowRtn = structuredClone(g_keyObj[`stepRtn${keyCtrlPtn}`]);
8241
+ g_workObj.keyCtrl = structuredClone(g_keyObj[`keyCtrl${keyCtrlPtn}`]);
8215
8242
  g_workObj.diffList = [];
8216
8243
  g_workObj.mainEndTime = 0;
8217
8244
 
@@ -8254,6 +8281,7 @@ const getArrowSettings = _ => {
8254
8281
  g_keyObj[`scrollDir${keyCtrlPtn}`][g_stateObj.scroll] : [...Array(keyNum)].fill(1));
8255
8282
 
8256
8283
  g_stateObj.autoAll = (g_stateObj.autoPlay === C_FLG_ALL ? C_FLG_ON : C_FLG_OFF);
8284
+ g_workObj.hitPosition = (g_stateObj.autoAll ? 0 : g_stateObj.hitPosition);
8257
8285
  changeSetColor();
8258
8286
 
8259
8287
  for (let j = 0; j < keyNum; j++) {
@@ -8298,8 +8326,9 @@ const getArrowSettings = _ => {
8298
8326
  // 次回キーコンフィグ画面へ戻ったとき、保存済みキーコンフィグ設定が表示されるようにする
8299
8327
  g_keyObj.prevKey = `Dummy`;
8300
8328
 
8301
- // ローカルストレージへAdjustment, Volume, Display関連設定を保存
8329
+ // ローカルストレージへAdjustment, hitPosition, Volume, colorType設定を保存
8302
8330
  g_localStorage.adjustment = g_stateObj.adjustment;
8331
+ g_localStorage.hitPosition = g_stateObj.hitPosition;
8303
8332
  g_localStorage.volume = g_stateObj.volume;
8304
8333
  g_localStorage.colorType = g_colorType;
8305
8334
 
@@ -8317,7 +8346,7 @@ const getArrowSettings = _ => {
8317
8346
  storageObj[`keyCtrl${addKey}`] = setKeyCtrl(g_localKeyStorage, keyNum, keyCtrlPtn);
8318
8347
  if (g_keyObj.currentPtn !== -1) {
8319
8348
  storageObj[`keyCtrlPtn${addKey}`] = g_keyObj.currentPtn;
8320
- g_keyObj[`keyCtrl${keyCtrlPtn}`] = copyArray2d(g_keyObj[`keyCtrl${keyCtrlPtn}d`]);
8349
+ g_keyObj[`keyCtrl${keyCtrlPtn}`] = structuredClone(g_keyObj[`keyCtrl${keyCtrlPtn}d`]);
8321
8350
  }
8322
8351
 
8323
8352
  // カラーセットの保存(キー別)
@@ -8522,8 +8551,8 @@ const mainInit = _ => {
8522
8551
 
8523
8552
  // 矢印・フリーズアロー描画スプライト(ステップゾーンの上に配置)
8524
8553
  const arrowSprite = [
8525
- createEmptySprite(mainSprite, `arrowSprite0`, { w: g_headerObj.playingWidth, h: g_posObj.arrowHeight }),
8526
- createEmptySprite(mainSprite, `arrowSprite1`, { w: g_headerObj.playingWidth, h: g_posObj.arrowHeight }),
8554
+ createEmptySprite(mainSprite, `arrowSprite0`, { y: g_workObj.hitPosition, w: g_headerObj.playingWidth, h: g_posObj.arrowHeight }),
8555
+ createEmptySprite(mainSprite, `arrowSprite1`, { y: -g_workObj.hitPosition, w: g_headerObj.playingWidth, h: g_posObj.arrowHeight }),
8527
8556
  ];
8528
8557
 
8529
8558
  // Appearanceのオプション適用時は一部描画を隠す
@@ -9815,6 +9844,7 @@ const changeHitFrz = (_j, _k, _name) => {
9815
9844
 
9816
9845
  const styfrzBar = $id(`${_name}Bar${frzNo}`);
9817
9846
  const styfrzBtm = $id(`${_name}Btm${frzNo}`);
9847
+ const styfrzTopShadow = $id(`${_name}TopShadow${frzNo}`);
9818
9848
  const styfrzBtmShadow = $id(`${_name}BtmShadow${frzNo}`);
9819
9849
  const colorPos = g_keyObj[`color${g_keyObj.currentKey}_${g_keyObj.currentPtn}`][_j];
9820
9850
 
@@ -9825,9 +9855,12 @@ const changeHitFrz = (_j, _k, _name) => {
9825
9855
  // 早押ししたboostCnt分のフリーズアロー終端位置の修正
9826
9856
  const delFrzMotionLength = sumData(g_workObj.motionOnFrames.slice(0, currentFrz.boostCnt + 1));
9827
9857
 
9858
+ // 判定位置調整分の補正
9859
+ const hitPos = g_workObj.hitPosition * g_workObj.scrollDir[_j];
9860
+
9828
9861
  currentFrz.frzBarLength -= (delFrzLength + delFrzMotionLength) * currentFrz.dir;
9829
- currentFrz.barY -= (delFrzLength + delFrzMotionLength) * currentFrz.dividePos;
9830
- currentFrz.btmY -= delFrzLength + delFrzMotionLength;
9862
+ currentFrz.barY -= (delFrzLength + delFrzMotionLength) * currentFrz.dividePos + hitPos;
9863
+ currentFrz.btmY -= delFrzLength + delFrzMotionLength + hitPos;
9831
9864
  currentFrz.y += delFrzLength;
9832
9865
  currentFrz.isMoving = false;
9833
9866
 
@@ -9836,6 +9869,7 @@ const changeHitFrz = (_j, _k, _name) => {
9836
9869
  styfrzBar.background = g_workObj[`${_name}HitBarColors`][_j];
9837
9870
  styfrzBtm.top = `${currentFrz.btmY}px`;
9838
9871
  styfrzBtm.background = g_workObj[`${_name}HitColors`][_j];
9872
+ styfrzTopShadow.opacity = 0;
9839
9873
  styfrzBtmShadow.top = styfrzBtm.top;
9840
9874
  if (_name === `frz`) {
9841
9875
  if (g_headerObj.frzShadowColor[colorPos][1] !== ``) {
@@ -9860,10 +9894,16 @@ const changeFailedFrz = (_j, _k) => {
9860
9894
  $id(`frzHit${_j}`).opacity = 0;
9861
9895
  $id(`frzTop${frzNo}`).display = C_DIS_INHERIT;
9862
9896
  $id(`frzTop${frzNo}`).background = `#cccccc`;
9897
+ $id(`frzTopShadow${frzNo}`).opacity = 1;
9863
9898
  $id(`frzBar${frzNo}`).background = `#999999`;
9864
9899
  $id(`frzBar${frzNo}`).opacity = 1;
9865
9900
  $id(`frzBtm${frzNo}`).background = `#cccccc`;
9866
9901
 
9902
+ // 判定位置調整分の補正
9903
+ const hitPos = g_workObj.hitPosition * g_workObj.scrollDir[_j];
9904
+ $id(`frzTop${frzNo}`).top = `${- hitPos}px`;
9905
+ $id(`frzTopShadow${frzNo}`).top = `${- hitPos}px`;
9906
+
9867
9907
  const colorPos = g_keyObj[`color${g_keyObj.currentKey}_${g_keyObj.currentPtn}`][_j];
9868
9908
  if (g_headerObj.frzShadowColor[colorPos][0] !== ``) {
9869
9909
  $id(`frzTopShadow${frzNo}`).background = `#333333`;
@@ -9901,7 +9941,7 @@ const judgeArrow = _j => {
9901
9941
  displayDiff(_difFrame);
9902
9942
 
9903
9943
  const stepDivHit = document.querySelector(`#stepHit${_j}`);
9904
- stepDivHit.style.top = `${currentArrow.prevY - parseFloat($id(`stepRoot${_j}`).top) - 15}px`;
9944
+ stepDivHit.style.top = `${currentArrow.prevY - parseFloat($id(`stepRoot${_j}`).top) - 15 + g_workObj.hitPosition * g_workObj.scrollDir[_j]}px`;
9905
9945
  stepDivHit.style.opacity = 0.75;
9906
9946
  stepDivHit.classList.value = ``;
9907
9947
  stepDivHit.classList.add(g_cssObj[`main_step${resultJdg}`]);