danoniplus 38.3.1 → 39.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,19 +4,19 @@
4
4
  *
5
5
  * Source by tickle
6
6
  * Created : 2018/10/08
7
- * Revised : 2025/01/28
7
+ * Revised : 2025/02/01
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 38.3.1`;
12
- const g_revisedDate = `2025/01/28`;
11
+ const g_version = `Ver 39.0.0`;
12
+ const g_revisedDate = `2025/02/01`;
13
13
 
14
14
  // カスタム用バージョン (danoni_custom.js 等で指定可)
15
15
  let g_localVersion = ``;
16
16
  let g_localVersion2 = ``;
17
17
 
18
18
  // ショートカット用文字列(↓の文字列を検索することで対象箇所へジャンプできます)
19
- // 共通:water 初期化:peach タイトル:melon 設定:lime ディスプレイ:lemon キーコンフィグ:orange 譜面読込:strawberry メイン:banana 結果:grape
19
+ // 共通:water 初期化:peach タイトル:melon 設定:lime ディスプレイ:lemon 拡張設定:apple キーコンフィグ:orange 譜面読込:strawberry メイン:banana 結果:grape
20
20
  // シーンジャンプ:Scene
21
21
 
22
22
  /**
@@ -100,7 +100,6 @@ let g_currentPage = ``;
100
100
  let g_kcType = `Main`;
101
101
  let g_colorType = `Default`;
102
102
  let g_imgType = `Original`;
103
- let g_baseDisp = `Settings`;
104
103
 
105
104
  // ライフ・ゲームオーバー・曲終了管理
106
105
  let g_maxScore = 1000000;
@@ -1232,7 +1231,8 @@ const createColorPicker = (_parentObj, _id, _func, { x = 0, y = 0 } = {}) => {
1232
1231
  * @returns {HTMLDivElement}
1233
1232
  */
1234
1233
  const createColorObject2 = (_id,
1235
- { x = 0, y = 0, w = C_ARW_WIDTH, h = C_ARW_WIDTH, rotate = ``, styleName = ``, ...rest } = {}, ..._classes) => {
1234
+ { x = 0, y = 0, w = C_ARW_WIDTH, h = C_ARW_WIDTH, rotate = ``, styleName = ``,
1235
+ rotateEnabled = g_stateObj.rotateEnabled, ...rest } = {}, ..._classes) => {
1236
1236
 
1237
1237
  const div = createDiv(_id, x, y, w, h, _classes);
1238
1238
  const style = div.style;
@@ -1244,7 +1244,7 @@ const createColorObject2 = (_id,
1244
1244
  rotate = setVal(objData[1], 0, C_TYP_FLOAT);
1245
1245
  charaStyle = `${objData[0]}${styleName}`;
1246
1246
  }
1247
- if (g_stateObj.rotateEnabled) {
1247
+ if (rotateEnabled) {
1248
1248
  style.transform = `rotate(${rotate}deg)`;
1249
1249
  }
1250
1250
 
@@ -2931,6 +2931,10 @@ const headerConvert = _dosObj => {
2931
2931
  setIntVal(getQueryParamVal(`h`), g_sHeight), g_sHeight);
2932
2932
  $id(`canvas-frame`).height = wUnit(g_sHeight);
2933
2933
  }
2934
+ if (!(_dosObj.heightVariable || g_presetObj.heightVariable || false)) {
2935
+ obj.heightLockFlg = true;
2936
+ g_settings.playWindows = g_settings.playWindows.filter(val => !val.endsWith(`Slope`) && !val.endsWith(`SideScroll`));
2937
+ }
2934
2938
 
2935
2939
  // 曲名
2936
2940
  obj.musicTitles = [];
@@ -3398,6 +3402,8 @@ const headerConvert = _dosObj => {
3398
3402
  interlockingButton(obj, defaultOption, C_FLG_OFF, C_FLG_ON);
3399
3403
  }));
3400
3404
  }
3405
+ obj.arrowEffectUseOrg = obj.arrowEffectUse;
3406
+ obj.arrowEffectSetFlg = obj.arrowEffectSet === C_FLG_ON;
3401
3407
 
3402
3408
  // ローカルストレージに保存済みのColorType設定からDisplayのColor設定を反映
3403
3409
  if (g_localStorage.colorType !== undefined) {
@@ -4305,6 +4311,9 @@ const titleInit = () => {
4305
4311
  // タイトル用フレーム初期化
4306
4312
  g_scoreObj.titleFrameNum = 0;
4307
4313
 
4314
+ // 設定画面位置初期化
4315
+ g_settings.settingWindowNum = 0;
4316
+
4308
4317
  // タイトルアニメーション用フレーム初期化、ループカウンター設定
4309
4318
  g_animationData.forEach(sprite => {
4310
4319
  g_scoreObj[`${sprite}TitleFrameNum`] = 0;
@@ -4331,7 +4340,7 @@ const titleInit = () => {
4331
4340
  divRoot.appendChild(
4332
4341
  createColorObject2(`lblArrow`, {
4333
4342
  x: (g_sWidth - 500) / 2, y: -15 + (g_sHeight - 500) / 2,
4334
- w: 500, h: 500,
4343
+ w: 500, h: 500, rotateEnabled: true,
4335
4344
  background: makeColorGradation(g_headerObj.titlearrowgrds[0] || g_headerObj.setColorOrg[0], {
4336
4345
  _defaultColorgrd: [false, `#eeeeee`],
4337
4346
  _objType: `titleArrow`,
@@ -4699,7 +4708,8 @@ const commonSettingBtn = _labelName => {
4699
4708
  // Display設定へ移動
4700
4709
  createCss2Button(`btn${_labelName}`, `>`, () => true,
4701
4710
  Object.assign(g_lblPosObj.btnSwitchSetting, {
4702
- title: g_msgObj[`to${_labelName}`], resetFunc: () => g_jumpSettingWindow[g_currentPage](),
4711
+ title: g_msgObj[`to${_labelName}`], resetFunc: () => g_moveSettingWindow(),
4712
+ cxtFunc: () => g_moveSettingWindow(true, -1),
4703
4713
  }), g_cssObj.button_Mini),
4704
4714
 
4705
4715
  // データセーブフラグの切替
@@ -4727,7 +4737,6 @@ const optionInit = () => {
4727
4737
 
4728
4738
  clearWindow(true);
4729
4739
  const divRoot = document.getElementById(`divRoot`);
4730
- g_baseDisp = `Settings`;
4731
4740
  g_currentPage = `option`;
4732
4741
  g_stateObj.filterKeys = ``;
4733
4742
 
@@ -6002,7 +6011,7 @@ const createGeneralSetting = (_obj, _settingName, { unitName = ``,
6002
6011
  */
6003
6012
  const createLblSetting = (_settingName, _adjY = 0, _settingLabel = _settingName) => {
6004
6013
  const lbl = createDivCss2Label(`lbl${_settingName}`, g_lblNameObj[_settingLabel], {
6005
- x: 0, y: _adjY, w: 100,
6014
+ x: -5, y: _adjY, w: 110,
6006
6015
  }, `settings_${_settingName}`);
6007
6016
  lbl.title = g_msgObj[`${_settingName.charAt(0).toLowerCase()}${_settingName.slice(1)}`];
6008
6017
  return lbl;
@@ -6452,7 +6461,6 @@ const settingsDisplayInit = () => {
6452
6461
 
6453
6462
  clearWindow(true);
6454
6463
  const divRoot = document.getElementById(`divRoot`);
6455
- g_baseDisp = `Display`;
6456
6464
  g_currentPage = `settingsDisplay`;
6457
6465
 
6458
6466
  // 譜面初期情報ロード許可フラグ
@@ -6669,6 +6677,80 @@ const interlockingButton = (_headerObj, _name, _current, _next, _buttonFlg = fal
6669
6677
  }
6670
6678
  };
6671
6679
 
6680
+ /*-----------------------------------------------------------*/
6681
+ /* Scene : EX-SETTINGS [apple] */
6682
+ /*-----------------------------------------------------------*/
6683
+
6684
+ const exSettingInit = () => {
6685
+ clearWindow(true);
6686
+ g_currentPage = `exSetting`;
6687
+
6688
+ multiAppend(divRoot,
6689
+
6690
+ // 画面タイトル
6691
+ getTitleDivLabel(`lblTitle`,
6692
+ `<div class="settings_Title">EX-</div><div class="settings_Title2">SETTINGS</div>`
6693
+ .replace(/[\t\n]/g, ``), 0, 15, g_cssObj.flex_centering),
6694
+
6695
+ );
6696
+
6697
+ // 各ボタン用のスプライトを作成
6698
+ createEmptySprite(divRoot, `optionsprite`, g_windowObj.optionSprite);
6699
+ const spriteList = setSpriteList(g_settingPos.exSetting);
6700
+
6701
+ createGeneralSetting(spriteList.playWindow, `playWindow`);
6702
+ lblPlayWindow.title += g_headerObj.heightLockFlg ? g_msgObj.sideScrollDisable : g_msgObj.sideScrollMsg;
6703
+
6704
+ createGeneralSetting(spriteList.stepArea, `stepArea`);
6705
+ createGeneralSetting(spriteList.frzReturn, `frzReturn`);
6706
+ createGeneralSetting(spriteList.shaking, `shaking`);
6707
+ createGeneralSetting(spriteList.effect, `effect`, {
6708
+ addRFunc: () => {
6709
+ g_stateObj.d_arroweffect = boolToSwitch(g_stateObj.effect !== C_FLG_OFF || g_headerObj.arrowEffectSetFlg);
6710
+ g_headerObj.arrowEffectUse = g_stateObj.effect === C_FLG_OFF && g_headerObj.arrowEffectUseOrg;
6711
+ g_headerObj.arrowEffectSet = g_stateObj.d_arroweffect;
6712
+ },
6713
+ });
6714
+ createGeneralSetting(spriteList.camoufrage, `camoufrage`);
6715
+ createGeneralSetting(spriteList.swapping, `swapping`);
6716
+ createGeneralSetting(spriteList.judgRange, `judgRange`, {
6717
+ addRFunc: () => {
6718
+ [g_judgObj.arrowJ, g_judgObj.frzJ] = g_judgRanges[g_stateObj.judgRange];
6719
+ lblJudgRangeView.innerHTML = getJudgRangeView();
6720
+ }
6721
+ });
6722
+ createGeneralSetting(spriteList.autoRetry, `autoRetry`);
6723
+
6724
+ // 判定範囲の設定を表示
6725
+ const getJudgRangeView = () => `| ` +
6726
+ `<span class="common_ii">${g_lblNameObj.j_ii}</span>: ≦ <b>±${g_judgObj.arrowJ[0]} f</b> | ` +
6727
+ `<span class="common_shakin">${g_lblNameObj.j_shakin}</span>: ≦ <b>±${g_judgObj.arrowJ[1]} f</b> | ` +
6728
+ `<span class="common_matari">${g_lblNameObj.j_matari}</span>: ≦ <b>±${g_judgObj.arrowJ[2]} f</b> | <br>| ` +
6729
+ `<span class="common_shobon">${g_lblNameObj.j_shobon}</span>: ≦ <b>±${g_judgObj.arrowJ[3]} f</b> | ` +
6730
+ `<span class="common_uwan">${g_lblNameObj.j_uwan}</span>: > <b>±${g_judgObj.arrowJ[3]} f</b> | <br>| ` +
6731
+ `<span class="common_kita">${g_lblNameObj.j_kita}</span>: ≦ <b>±${g_judgObj.frzJ[1]} f</b> | ` +
6732
+ `<span class="common_iknai">${g_lblNameObj.j_iknai}</span>: > <b>±${g_judgObj.frzJ[1]} f</b> |`;
6733
+
6734
+ multiAppend(judgRangeSprite,
6735
+ createDivCss2Label(`lblJudgRangeView`, getJudgRangeView(), {
6736
+ x: parseFloat($id(`lblJudgRange`).left) + 10, y: parseFloat($id(`lblJudgRange`).top) + 25, w: 300, h: 30, siz: 13,
6737
+ align: C_ALIGN_LEFT,
6738
+ }),
6739
+ );
6740
+
6741
+ // ユーザカスタムイベント(初期)
6742
+ g_customJsObj.exSetting.forEach(func => func());
6743
+
6744
+ // 設定系のボタン群をまとめて作成(Data Save, Display切替, Back, KeyConfig, Playボタン)
6745
+ commonSettingBtn(g_currentPage);
6746
+
6747
+ // キー操作イベント(デフォルト)
6748
+ setShortcutEvent(g_currentPage, () => true, { dfEvtFlg: true });
6749
+ document.oncontextmenu = () => true;
6750
+
6751
+ g_skinJsObj.exSetting.forEach(func => func());
6752
+ };
6753
+
6672
6754
  /*-----------------------------------------------------------*/
6673
6755
  /* Scene : KEYCONFIG [orange] */
6674
6756
  /*-----------------------------------------------------------*/
@@ -7422,7 +7504,7 @@ const keyConfigInit = (_kcType = g_kcType) => {
7422
7504
  g_currentk = 0;
7423
7505
  g_prevKey = 0;
7424
7506
  }, Object.assign(g_lblPosObj.btnKcBack, {
7425
- resetFunc: () => (g_baseDisp === `Settings` ? optionInit() : settingsDisplayInit()),
7507
+ resetFunc: () => g_moveSettingWindow(false),
7426
7508
  }), g_cssObj.button_Back),
7427
7509
 
7428
7510
  createDivCss2Label(`lblPattern`, `${g_lblNameObj.KeyPattern}: ${g_keyObj.currentPtn === -1 ?
@@ -7883,12 +7965,12 @@ const loadingScoreInit = async () => {
7883
7965
 
7884
7966
  // シャッフルグループを扱いやすくする
7885
7967
  // [0, 0, 0, 1, 0, 0, 0] -> [[0, 1, 2, 4, 5, 6], [3]]
7886
- const shuffleGroupMap = {};
7968
+ g_workObj.shuffleGroupMap = {};
7887
7969
  g_keyObj[`shuffle${keyCtrlPtn}`].forEach((_val, _i) =>
7888
- shuffleGroupMap[_val]?.push(_i) || (shuffleGroupMap[_val] = [_i]));
7970
+ g_workObj.shuffleGroupMap[_val]?.push(_i) || (g_workObj.shuffleGroupMap[_val] = [_i]));
7889
7971
 
7890
7972
  // Mirror,Random,S-Randomの適用
7891
- g_shuffleFunc[g_stateObj.shuffle](keyNum, Object.values(shuffleGroupMap));
7973
+ g_shuffleFunc[g_stateObj.shuffle](keyNum, Object.values(g_workObj.shuffleGroupMap));
7892
7974
 
7893
7975
  // アシスト用の配列があれば、ダミーデータで上書き
7894
7976
  if (typeof g_keyObj[`assistPos${keyCtrlPtn}`] === C_TYP_OBJECT &&
@@ -7989,6 +8071,26 @@ const applyShuffle = (_keyNum, _shuffleGroup, _style) => {
7989
8071
  });
7990
8072
  };
7991
8073
 
8074
+ /**
8075
+ * X-Mirror作成用の入れ替え関数
8076
+ * グループが4の倍数のとき、4n+1, 4n+2のみ入れ替える
8077
+ * @param {number[][]} _style
8078
+ * @param {number[]} _group
8079
+ * @param {number} _i
8080
+ * @param {number} _divideNum
8081
+ * @returns
8082
+ */
8083
+ const swapGroupNums = (_style, _group, _i, _divideNum) => {
8084
+ if (_group.length % _divideNum === 0) {
8085
+ for (let k = 0; k < _group.length / _divideNum; k++) {
8086
+ const swap1 = Math.floor(_divideNum * (k + 1 / 2) - 1);
8087
+ const swap2 = Math.ceil(_divideNum * (k + 1 / 2));
8088
+ [_style[_i][swap1], _style[_i][swap2]] = [_style[_i][swap2], _style[_i][swap1]];
8089
+ }
8090
+ }
8091
+ return _style;
8092
+ };
8093
+
7992
8094
  /**
7993
8095
  * Mirrorの適用
7994
8096
  * @param {number} _keyNum
@@ -7999,23 +8101,19 @@ const applyMirror = (_keyNum, _shuffleGroup, _swapFlg = false) => {
7999
8101
 
8000
8102
  // シャッフルグループごとにミラー
8001
8103
  const style = structuredClone(_shuffleGroup).map(_group => _group.reverse());
8002
- let swapUseFlg = false;
8003
-
8004
- // X-Mirror作成用の入れ替え関数
8005
- // グループが4の倍数のとき、4n+1, 4n+2のみ入れ替える
8006
- const swapGroupNums = (_group, _i, _divideNum) => {
8007
- if (_group.length % _divideNum === 0) {
8008
- swapUseFlg = true;
8009
- for (let k = 0; k < _group.length / _divideNum; k++) {
8010
- const swap1 = Math.floor(_divideNum * (k + 1 / 2) - 1);
8011
- const swap2 = Math.ceil(_divideNum * (k + 1 / 2));
8012
- [style[_i][swap1], style[_i][swap2]] = [style[_i][swap2], style[_i][swap1]];
8013
- }
8014
- }
8015
- };
8104
+ const mirStyle = structuredClone(style);
8016
8105
 
8017
8106
  if (_swapFlg) {
8018
- style.forEach((group, i) => g_settings.swapPattern.forEach(val => swapGroupNums(group, i, val)));
8107
+ style.forEach((group, i) => g_settings.swapPattern.forEach(val => swapGroupNums(style, group, i, val)));
8108
+ let swapUseFlg = false;
8109
+ style.forEach((_group, j) => {
8110
+ _group.forEach((val, k) => {
8111
+ if (style[j][k] !== mirStyle[j][k]) {
8112
+ swapUseFlg = true;
8113
+ return;
8114
+ }
8115
+ });
8116
+ });
8019
8117
  if (!swapUseFlg) {
8020
8118
  g_stateObj.shuffle = `Mirror`;
8021
8119
  }
@@ -8370,6 +8468,12 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
8370
8468
 
8371
8469
  cssMotionData.push([frame, arrowNum, styleUp, styleDown]);
8372
8470
  });
8471
+
8472
+ // 個別のモーションデータが存在する場合、Effect設定を自動リセット
8473
+ if (cssMotionData.length > 0) {
8474
+ g_stateObj.effect = C_FLG_OFF;
8475
+ g_settings.effectNum = 0;
8476
+ }
8373
8477
  return cssMotionData.sort((_a, _b) => _a[0] - _b[0]).flat();
8374
8478
  }
8375
8479
  return [];
@@ -8396,6 +8500,12 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
8396
8500
 
8397
8501
  scrollchData.push([frame, arrowNum, frame, scrollDir]);
8398
8502
  });
8503
+
8504
+ // 個別のスクロール変化が存在する場合、StepAreaを自動リセット
8505
+ if (scrollchData.length > 0) {
8506
+ g_stateObj.stepArea = `Default`;
8507
+ g_settings.stepAreaNum = 0;
8508
+ }
8399
8509
  return scrollchData.sort((_a, _b) => _a[0] - _b[0]).flat();
8400
8510
  }
8401
8511
  return [];
@@ -9531,6 +9641,8 @@ const getArrowSettings = () => {
9531
9641
 
9532
9642
  // モーション管理
9533
9643
  g_typeLists.arrow.forEach(type => g_workObj[`${type}CssMotions`] = fillArray(keyNum, ``));
9644
+ g_workObj.frzArrowCssMotions = fillArray(keyNum, ``);
9645
+ g_workObj.dummyFrzArrowCssMotions = fillArray(keyNum, ``);
9534
9646
 
9535
9647
  const scrollDirOptions = g_keyObj[`scrollDir${keyCtrlPtn}`]?.[g_stateObj.scroll] ?? fillArray(keyNum, 1);
9536
9648
 
@@ -9546,6 +9658,9 @@ const getArrowSettings = () => {
9546
9658
 
9547
9659
  g_workObj.stepX[j] = g_keyObj.blank * stdPos + (g_headerObj.playingWidth - C_ARW_WIDTH) / 2;
9548
9660
  g_workObj.dividePos[j] = ((posj <= divideCnt ? 0 : 1) + (scrollDirOptions[j] === 1 ? 0 : 1) + (g_stateObj.reverse === C_FLG_OFF ? 0 : 1)) % 2;
9661
+ if (g_stateObj.stepArea === `X-Flower`) {
9662
+ g_workObj.dividePos[j] = (g_workObj.stepX[j] < (g_headerObj.playingWidth - C_ARW_WIDTH) / 2 ? 0 : 1) * 2 + g_workObj.dividePos[j] % 2;
9663
+ }
9549
9664
  g_workObj.scrollDir[j] = (posj <= divideCnt ? 1 : -1) * scrollDirOptions[j] * (g_stateObj.reverse === C_FLG_OFF ? 1 : -1);
9550
9665
 
9551
9666
  eachOrAll.forEach(type => {
@@ -9564,6 +9679,7 @@ const getArrowSettings = () => {
9564
9679
  });
9565
9680
  }
9566
9681
  g_workObj.scrollDirDefault = g_workObj.scrollDir.concat();
9682
+ g_stateObj.layerNum = Math.ceil((Math.max(...g_workObj.dividePos) + 1) / 2) * 2;
9567
9683
 
9568
9684
  Object.keys(g_resultObj).forEach(judgeCnt => g_resultObj[judgeCnt] = 0);
9569
9685
  g_resultObj.spState = ``;
@@ -9584,6 +9700,105 @@ const getArrowSettings = () => {
9584
9700
  g_workObj.backX = (g_workObj.nonDefaultSc && g_headerObj.playingLayout ? g_headerObj.scAreaWidth : 0);
9585
9701
  g_workObj.playingX = g_headerObj.playingX + g_workObj.backX;
9586
9702
 
9703
+ // Swapping設定に応じたステップゾーンの入れ替え
9704
+ if (g_stateObj.swapping.includes(`Mirror`)) {
9705
+
9706
+ let _style = structuredClone(Object.values(g_workObj.shuffleGroupMap));
9707
+ if (g_stateObj.swapping === `Mirror`) {
9708
+ _style.map(_group => _group.reverse());
9709
+
9710
+ } else if (g_stateObj.swapping === `X-Mirror`) {
9711
+ // X-Mirrorの場合、グループの内側だけ入れ替える
9712
+ _style.forEach((group, i) => g_settings.swapPattern.forEach(val => swapGroupNums(_style, group, i, val)));
9713
+ }
9714
+
9715
+ // 入れ替えた結果に合わせてX座標位置を入れ替える
9716
+ g_workObj.stepX_df = structuredClone(g_workObj.stepX);
9717
+ _style.forEach((_group, _i) => {
9718
+ _group.forEach((_val, _j) => {
9719
+ g_workObj.stepX[_group[_j]] = g_workObj.stepX_df[g_workObj.shuffleGroupMap[_i][_j]];
9720
+ });
9721
+ });
9722
+ }
9723
+
9724
+ // FrzReturnの初期化
9725
+ g_workObj.frzReturnFlg = false;
9726
+
9727
+ // AutoRetryの初期化
9728
+ g_workObj.autoRetryFlg = false;
9729
+
9730
+ // Camoufrageの設定
9731
+ if (!g_stateObj.rotateEnabled) {
9732
+
9733
+ // 矢印の回転が無効の場合は、設定を変える
9734
+ if (g_stateObj.camoufrage === `Arrow`) {
9735
+ g_stateObj.camoufrage = C_FLG_OFF;
9736
+ } else if (g_stateObj.camoufrage === C_FLG_ALL) {
9737
+ g_stateObj.camoufrage = `Color`;
9738
+ }
9739
+ g_settings.camoufrageNum = g_settings.camoufrages.findIndex(val => val === g_stateObj.camoufrage);
9740
+ }
9741
+ if (g_stateObj.camoufrage !== C_FLG_OFF) {
9742
+ const eachOrAll = [``, `All`];
9743
+ const keyNum = g_keyObj[`chara${g_keyObj.currentKey}_${g_keyObj.currentPtn}`].length;
9744
+
9745
+ // 位置変更用の配列を作成
9746
+ const randArray = [...Array(keyNum).keys()].map(_i => _i);
9747
+ let _i = randArray.length;
9748
+ while (_i) {
9749
+ const _j = Math.floor(Math.random() * _i--);
9750
+ [randArray[_i], randArray[_j]] = [randArray[_j], randArray[_i]];
9751
+ }
9752
+
9753
+ // 位置変更用の配列に従い、初期矢印・初期色の位置変更
9754
+ const getSwapArray = (_array) => {
9755
+ const _copiedArray = structuredClone(_array);
9756
+ return _array.map((_val, _i) => _array[_i] = _copiedArray[randArray[_i]]);
9757
+ };
9758
+ if (g_stateObj.camoufrage === `Arrow` || g_stateObj.camoufrage === C_FLG_ALL) {
9759
+
9760
+ // 矢印ヒット時に元の矢印がわかるようにするため、あえて g_workObj.stepHitRtn はそのままにする
9761
+ g_workObj.stepRtn = getSwapArray(g_workObj.stepRtn);
9762
+ g_workObj.arrowRtn = getSwapArray(g_workObj.arrowRtn);
9763
+ }
9764
+ eachOrAll.forEach(type => {
9765
+ if (g_stateObj.camoufrage === `Color` || g_stateObj.camoufrage === C_FLG_ALL) {
9766
+
9767
+ // ダミー矢印は対象外
9768
+ g_workObj[`arrowColors${type}`] = getSwapArray(g_workObj[`arrowColors${type}`]);
9769
+ g_workObj[`arrowShadowColors${type}`] = getSwapArray(g_workObj[`arrowShadowColors${type}`]);
9770
+
9771
+ g_typeLists.frzColor.forEach(frzType => {
9772
+ g_workObj[`frz${frzType}Colors${type}`] = getSwapArray(g_workObj[`frz${frzType}Colors${type}`]);
9773
+ });
9774
+ g_workObj[`frzNormalShadowColors${type}`] = getSwapArray(g_workObj[`frzNormalShadowColors${type}`]);
9775
+ g_workObj[`frzHitShadowColors${type}`] = getSwapArray(g_workObj[`frzHitShadowColors${type}`]);
9776
+ }
9777
+ });
9778
+
9779
+ // 位置変更用の配列に従い、個別・全体色変化の位置変更
9780
+ if (g_stateObj.camoufrage === `Color` || g_stateObj.camoufrage === C_FLG_ALL) {
9781
+ const getSwapList = (_array) => {
9782
+ const _copiedArray = structuredClone(_array);
9783
+ return _array.map((_val, _i) => _array[_i] = randArray[_copiedArray[_i]]);
9784
+ };
9785
+ [`mkColor`, `mkColorShadow`, `mkFColor`, `mkFColorShadow`].forEach(type => {
9786
+ if (g_workObj[type] !== undefined) {
9787
+ for (let j = 0; j < g_workObj[type].length; j++) {
9788
+ if (g_workObj[type][j] === undefined) {
9789
+ continue;
9790
+ }
9791
+ g_workObj[type][j] = getSwapList(g_workObj[type][j]);
9792
+ }
9793
+ }
9794
+ });
9795
+ }
9796
+ }
9797
+
9798
+ // Shaking: Drunkでの画面揺れ設定 (X方向、Y方向)
9799
+ g_workObj.drunkXFlg = false;
9800
+ g_workObj.drunkYFlg = false;
9801
+
9587
9802
  if (g_stateObj.dataSaveFlg) {
9588
9803
  // ローカルストレージへAdjustment, HitPosition, Volume設定を保存
9589
9804
  g_storeSettings.forEach(setting => g_localStorage[setting] = g_stateObj[setting]);
@@ -9739,15 +9954,47 @@ const mainInit = () => {
9739
9954
  let speedCnts = 0;
9740
9955
  let boostCnts = 0;
9741
9956
  let keychCnts = 0;
9742
- const flatMode = g_stateObj.d_stepzone === `FlatBar` || g_stateObj.scroll.endsWith(`Flat`) || g_keyObj[`flatMode${keyCtrlPtn}`];
9957
+
9958
+ const flatMode = g_stateObj.d_stepzone === `FlatBar` ||
9959
+ g_stateObj.scroll.endsWith(`Flat`) ||
9960
+ g_keyObj[`flatMode${keyCtrlPtn}`] ||
9961
+ (g_stateObj.stepArea === `Halfway` &&
9962
+ g_keyObj[`div${keyCtrlPtn}`] < g_keyObj[`${g_keyObj.defaultProp}${keyCtrlPtn}`].length);
9743
9963
  const stepZoneDisp = (g_stateObj.d_stepzone === C_FLG_OFF || flatMode) ? C_DIS_NONE : C_DIS_INHERIT;
9744
9964
 
9965
+ // Hidden+, Sudden+用のライン、パーセント表示
9966
+ const filterCss = g_stateObj.filterLock === C_FLG_OFF ? g_cssObj.life_Failed : g_cssObj.life_Cleared;
9967
+ [`filterBar0`, `filterBar1`, `borderBar0`, `borderBar1`].forEach(obj =>
9968
+ mainSprite.appendChild(createColorObject2(obj, g_lblPosObj.filterBar, filterCss)));
9969
+ borderBar0.style.top = wUnit(g_posObj.stepDiffY + g_stateObj.hitPosition);
9970
+ borderBar1.style.top = wUnit(g_posObj.stepDiffY + g_posObj.arrowHeight - g_stateObj.hitPosition);
9971
+
9972
+ if (g_appearanceRanges.includes(g_stateObj.appearance)) {
9973
+ mainSprite.appendChild(createDivCss2Label(`filterView`, ``, g_lblPosObj.filterView));
9974
+ if (g_stateObj.d_filterline === C_FLG_ON) {
9975
+ $id(`filterView`).opacity = g_stateObj.opacity / 100;
9976
+ $id(`filterBar0`).opacity = g_stateObj.opacity / 100;
9977
+ $id(`filterBar1`).opacity = g_stateObj.opacity / 100;
9978
+ }
9979
+ }
9980
+
9981
+ // mainSprite配下に層別のスプライトを作成し、ステップゾーン・矢印本体・フリーズアローヒット部分に分ける
9982
+ const mainSpriteN = [], stepSprite = [], arrowSprite = [], frzHitSprite = [];
9983
+ const mainCommonPos = { w: g_headerObj.playingWidth, h: g_posObj.arrowHeight };
9984
+ for (let j = 0; j < g_stateObj.layerNum; j++) {
9985
+ const mainSpriteJ = createEmptySprite(mainSprite, `mainSprite${j}`, mainCommonPos);
9986
+ mainSpriteN.push(mainSpriteJ);
9987
+ stepSprite.push(createEmptySprite(mainSpriteJ, `stepSprite${j}`, mainCommonPos));
9988
+ arrowSprite.push(createEmptySprite(mainSpriteJ, `arrowSprite${j}`, Object.assign({ y: g_workObj.hitPosition * (j % 2 === 0 ? 1 : -1) }, mainCommonPos)));
9989
+ frzHitSprite.push(createEmptySprite(mainSpriteJ, `frzHitSprite${j}`, mainCommonPos));
9990
+ }
9991
+
9745
9992
  for (let j = 0; j < keyNum; j++) {
9746
9993
  const colorPos = g_keyObj[`color${keyCtrlPtn}`][j];
9747
9994
 
9748
9995
  // ステップゾーンルート
9749
- const stepRoot = createEmptySprite(mainSprite, `stepRoot${j}`, {
9750
- x: g_workObj.stepX[j], y: C_STEP_Y + g_posObj.reverseStepY * g_workObj.dividePos[j],
9996
+ const stepRoot = createEmptySprite(stepSprite[g_workObj.dividePos[j]], `stepRoot${j}`, {
9997
+ x: g_workObj.stepX[j], y: C_STEP_Y + g_posObj.reverseStepY * (g_workObj.dividePos[j] % 2),
9751
9998
  w: C_ARW_WIDTH, h: C_ARW_WIDTH,
9752
9999
  });
9753
10000
 
@@ -9795,46 +10042,23 @@ const mainInit = () => {
9795
10042
  lineY.push(lineY[0], lineY[1]);
9796
10043
  reverses.push(!reverses[0], !reverses[1]);
9797
10044
  }
9798
- lineY.forEach((y, j) => {
9799
- mainSprite.appendChild(
9800
- createColorObject2(`stepBar${j}`, {
9801
- x: 0, y: C_STEP_Y + g_posObj.reverseStepY * Number(reverses[j]) + y,
9802
- w: g_headerObj.playingWidth - 50, h: 1, styleName: `lifeBar`,
9803
- }, g_cssObj.life_Failed)
9804
- );
9805
- });
9806
-
9807
- }
9808
-
9809
- // Hidden+, Sudden+用のライン、パーセント表示
9810
- const filterCss = g_stateObj.filterLock === C_FLG_OFF ? g_cssObj.life_Failed : g_cssObj.life_Cleared;
9811
- [`filterBar0`, `filterBar1`, `borderBar0`, `borderBar1`].forEach(obj =>
9812
- mainSprite.appendChild(createColorObject2(obj, g_lblPosObj.filterBar, filterCss)));
9813
- borderBar0.style.top = wUnit(g_posObj.stepDiffY + g_stateObj.hitPosition);
9814
- borderBar1.style.top = wUnit(g_posObj.stepDiffY + g_posObj.arrowHeight - g_stateObj.hitPosition);
9815
-
9816
- if (g_appearanceRanges.includes(g_stateObj.appearance)) {
9817
- mainSprite.appendChild(createDivCss2Label(`filterView`, ``, g_lblPosObj.filterView));
9818
- if (g_stateObj.d_filterline === C_FLG_ON) {
9819
- [`filterBar0`, `filterBar1`, `filterView`].forEach(obj => $id(obj).opacity = g_stateObj.opacity / 100);
10045
+ for (let k = 0; k < g_stateObj.layerNum; k += 2) {
10046
+ lineY.forEach((y, j) => {
10047
+ stepSprite[Number(reverses[j]) + k].appendChild(
10048
+ createColorObject2(`stepBar${j + k}`, {
10049
+ x: 0, y: C_STEP_Y + g_posObj.reverseStepY * Number(reverses[j]) + y,
10050
+ w: g_headerObj.playingWidth - 50, h: 1, styleName: `lifeBar`,
10051
+ }, g_cssObj.life_Failed)
10052
+ );
10053
+ });
9820
10054
  }
9821
10055
  }
9822
10056
 
9823
- // 矢印・フリーズアロー描画スプライト(ステップゾーンの上に配置)
9824
- const arrowSprite = [
9825
- createEmptySprite(mainSprite, `arrowSprite0`, { y: g_workObj.hitPosition, w: g_headerObj.playingWidth, h: g_posObj.arrowHeight }),
9826
- createEmptySprite(mainSprite, `arrowSprite1`, { y: -g_workObj.hitPosition, w: g_headerObj.playingWidth, h: g_posObj.arrowHeight }),
9827
- ];
9828
-
9829
- // Appearanceのオプション適用時は一部描画を隠す
9830
- changeAppearanceFilter(g_appearanceRanges.includes(g_stateObj.appearance) ?
9831
- g_hidSudObj.filterPos : g_hidSudObj.filterPosDefault[g_stateObj.appearance]);
9832
-
9833
10057
  for (let j = 0; j < keyNum; j++) {
9834
10058
 
9835
10059
  // フリーズアローヒット部分
9836
- const frzHit = createEmptySprite(mainSprite, `frzHit${j}`, {
9837
- x: g_workObj.stepX[j], y: C_STEP_Y + g_posObj.reverseStepY * g_workObj.dividePos[j],
10060
+ const frzHit = createEmptySprite(frzHitSprite[g_workObj.dividePos[j]], `frzHit${j}`, {
10061
+ x: g_workObj.stepX[j], y: C_STEP_Y + g_posObj.reverseStepY * (g_workObj.dividePos[j] % 2),
9838
10062
  w: C_ARW_WIDTH, h: C_ARW_WIDTH, opacity: 0,
9839
10063
  });
9840
10064
  if (isNaN(parseFloat(g_workObj.arrowRtn[j]))) {
@@ -9855,6 +10079,13 @@ const mainInit = () => {
9855
10079
  }
9856
10080
  }
9857
10081
 
10082
+ // StepArea処理
10083
+ g_stepAreaFunc[g_stateObj.stepArea]();
10084
+
10085
+ // Appearanceのオプション適用時は一部描画を隠す
10086
+ changeAppearanceFilter(g_appearanceRanges.includes(g_stateObj.appearance) ?
10087
+ g_hidSudObj.filterPos : g_hidSudObj.filterPosDefault[g_stateObj.appearance]);
10088
+
9858
10089
  // 現在の矢印・フリーズアローの速度、個別加算速度の初期化 (速度変化時に直す)
9859
10090
  g_workObj.currentSpeed = 2;
9860
10091
  g_workObj.boostSpd = 1;
@@ -10113,6 +10344,14 @@ const mainInit = () => {
10113
10344
  // ユーザカスタムイベント(初期)
10114
10345
  g_customJsObj.main.forEach(func => func());
10115
10346
 
10347
+ // mainSpriteのtransform追加処理
10348
+ g_workObj.transform = mainSprite.style.transform || ``;
10349
+ g_workObj.transform += g_playWindowFunc[g_stateObj.playWindow]();
10350
+ mainSprite.style.transform = g_workObj.transform;
10351
+
10352
+ // EffectのArrowEffect追加処理
10353
+ g_effectFunc[g_stateObj.effect]();
10354
+
10116
10355
  /**
10117
10356
  * キーを押したときの処理
10118
10357
  */
@@ -10518,7 +10757,7 @@ const mainInit = () => {
10518
10757
  */
10519
10758
  const makeArrow = (_attrs, _arrowCnt, _name, _color, _shadowColor) => {
10520
10759
  const _j = _attrs.pos;
10521
- const dividePos = g_workObj.dividePos[_j];
10760
+ const dividePos = g_workObj.dividePos[_j] % 2;
10522
10761
  const colorPos = g_keyObj[`color${keyCtrlPtn}`][_j];
10523
10762
 
10524
10763
  const arrowName = `${_name}${_j}_${_arrowCnt}`;
@@ -10526,7 +10765,7 @@ const mainInit = () => {
10526
10765
  (_attrs.initY * g_workObj.boostSpd +
10527
10766
  _attrs.initBoostY * g_workObj.boostDir) * g_workObj.scrollDir[_j];
10528
10767
 
10529
- const stepRoot = createEmptySprite(arrowSprite[dividePos], arrowName, {
10768
+ const stepRoot = createEmptySprite(arrowSprite[g_workObj.dividePos[_j]], arrowName, {
10530
10769
  x: g_workObj.stepX[_j], y: firstPosY, w: C_ARW_WIDTH, h: C_ARW_WIDTH,
10531
10770
  });
10532
10771
  /**
@@ -10553,7 +10792,7 @@ const mainInit = () => {
10553
10792
  // 矢印色の設定
10554
10793
  // - 枠/塗りつぶし色: g_attrObj[arrowName].Arrow / ArrowShadow
10555
10794
  g_typeLists.arrowColor.forEach(val => g_attrObj[arrowName][`Arrow${val}`] = g_workObj[`${_name}${val}Colors`][_j]);
10556
- arrowSprite[dividePos].appendChild(stepRoot);
10795
+ arrowSprite[g_workObj.dividePos[_j]].appendChild(stepRoot);
10557
10796
 
10558
10797
  if (g_workObj[`${_name}CssMotions`][_j] !== ``) {
10559
10798
  stepRoot.classList.add(g_workObj[`${_name}CssMotions`][_j]);
@@ -10581,6 +10820,7 @@ const mainInit = () => {
10581
10820
  stepRoot.appendChild(createColorObject2(`${_name}Top${_j}_${_arrowCnt}`, {
10582
10821
  background: _color, rotate: g_workObj.arrowRtn[_j],
10583
10822
  }));
10823
+ g_customJsObj.makeArrow.forEach(func => func(_attrs, arrowName, _name, _arrowCnt));
10584
10824
  };
10585
10825
 
10586
10826
  /**
@@ -10621,7 +10861,7 @@ const mainInit = () => {
10621
10861
  */
10622
10862
  const makeFrzArrow = (_attrs, _arrowCnt, _name, _normalColor, _barColor, _shadowColor) => {
10623
10863
  const _j = _attrs.pos;
10624
- const dividePos = g_workObj.dividePos[_j];
10864
+ const dividePos = g_workObj.dividePos[_j] % 2;
10625
10865
  const frzNo = `${_j}_${_arrowCnt}`;
10626
10866
  const frzName = `${_name}${frzNo}`;
10627
10867
  const firstPosY = C_STEP_Y + g_posObj.reverseStepY * dividePos +
@@ -10629,7 +10869,7 @@ const mainInit = () => {
10629
10869
  _attrs.initBoostY * g_workObj.boostDir) * g_workObj.scrollDir[_j];
10630
10870
  const firstBarLength = g_workObj[`mk${toCapitalize(_name)}Length`][_j][(_arrowCnt - 1) * 2] * g_workObj.boostSpd;
10631
10871
 
10632
- const frzRoot = createEmptySprite(arrowSprite[dividePos], frzName, {
10872
+ const frzRoot = createEmptySprite(arrowSprite[g_workObj.dividePos[_j]], frzName, {
10633
10873
  x: g_workObj.stepX[_j], y: firstPosY, w: C_ARW_WIDTH, h: C_ARW_WIDTH + firstBarLength,
10634
10874
  });
10635
10875
  /**
@@ -10667,12 +10907,7 @@ const mainInit = () => {
10667
10907
  // - 通常時 (矢印枠/矢印塗りつぶし/帯): g_attrObj[frzName].Normal / NormalShadow / NormalBar
10668
10908
  // - ヒット時 (矢印枠/矢印塗りつぶし/帯): g_attrObj[frzName].Hit / HitShadow / HitBar
10669
10909
  g_typeLists.frzColor.forEach(val => g_attrObj[frzName][val] = g_workObj[`${_name}${val}Colors`][_j]);
10670
- arrowSprite[dividePos].appendChild(frzRoot);
10671
-
10672
- if (g_workObj[`${_name}CssMotions`][_j] !== ``) {
10673
- frzRoot.classList.add(g_workObj[`${_name}CssMotions`][_j]);
10674
- frzRoot.style.animationDuration = `${_attrs.arrivalFrame / g_fps}s`;
10675
- }
10910
+ arrowSprite[g_workObj.dividePos[_j]].appendChild(frzRoot);
10676
10911
  let shadowColor = _shadowColor === `Default` ? _normalColor : _shadowColor;
10677
10912
 
10678
10913
  /**
@@ -10686,30 +10921,49 @@ const mainInit = () => {
10686
10921
  x: 5, y: g_attrObj[frzName].barY, w: C_ARW_WIDTH - 10, h: firstBarLength, background: _barColor, styleName: `frzBar`,
10687
10922
  opacity: 0.75,
10688
10923
  }),
10924
+ );
10925
+ const frzTopRoot = createEmptySprite(frzRoot, `${_name}TopRoot${frzNo}`,
10926
+ { x: 0, y: 0, w: C_ARW_WIDTH, h: C_ARW_WIDTH });
10927
+ const frzBtmRoot = createEmptySprite(frzRoot, `${_name}BtmRoot${frzNo}`,
10928
+ { x: 0, y: g_attrObj[frzName].btmY, w: C_ARW_WIDTH, h: C_ARW_WIDTH });
10689
10929
 
10690
- // 開始矢印の塗り部分。ヒット時は前面に出て光る。
10930
+ multiAppend(frzTopRoot,
10931
+
10932
+ // 開始矢印の塗り部分。ヒット時は前面に表示
10691
10933
  createColorObject2(`${_name}TopShadow${frzNo}`, {
10692
10934
  background: shadowColor, rotate: g_workObj.arrowRtn[_j], styleName: `Shadow`,
10693
10935
  }, g_cssObj.main_objShadow),
10694
10936
 
10695
- // 開始矢印。ヒット時は隠れる。
10937
+ // 開始矢印。ヒット時は非表示
10696
10938
  createColorObject2(`${_name}Top${frzNo}`, {
10697
10939
  background: _normalColor, rotate: g_workObj.arrowRtn[_j],
10698
10940
  }),
10941
+ );
10942
+
10943
+ multiAppend(frzBtmRoot,
10699
10944
 
10700
10945
  // 後発矢印の塗り部分
10701
10946
  createColorObject2(`${_name}BtmShadow${frzNo}`, {
10702
- x: 0, y: g_attrObj[frzName].btmY,
10703
10947
  background: shadowColor, rotate: g_workObj.arrowRtn[_j], styleName: `Shadow`,
10704
10948
  }, g_cssObj.main_objShadow),
10705
10949
 
10706
10950
  // 後発矢印
10707
10951
  createColorObject2(`${_name}Btm${frzNo}`, {
10708
- x: 0, y: g_attrObj[frzName].btmY,
10709
10952
  background: _normalColor, rotate: g_workObj.arrowRtn[_j],
10710
10953
  }),
10711
10954
 
10712
10955
  );
10956
+ if (g_workObj[`${_name}CssMotions`][_j] !== ``) {
10957
+ frzRoot.classList.add(g_workObj[`${_name}CssMotions`][_j]);
10958
+ frzRoot.style.animationDuration = `${_attrs.arrivalFrame / g_fps}s`;
10959
+ }
10960
+ if (g_workObj[`${_name}ArrowCssMotions`][_j] !== ``) {
10961
+ [frzTopRoot, frzBtmRoot].forEach(obj => {
10962
+ obj.classList.add(g_workObj[`${_name}ArrowCssMotions`][_j]);
10963
+ obj.style.animationDuration = `${_attrs.arrivalFrame / g_fps}s`;
10964
+ });
10965
+ }
10966
+ g_customJsObj.makeFrzArrow.forEach(func => func(_attrs, frzName, _name, _arrowCnt));
10713
10967
  };
10714
10968
 
10715
10969
  /**
@@ -10755,8 +11009,7 @@ const mainInit = () => {
10755
11009
 
10756
11010
  $id(`${_name}Bar${frzNo}`).height = wUnit(currentFrz.frzBarLength);
10757
11011
  $id(`${_name}Bar${frzNo}`).top = wUnit(currentFrz.barY);
10758
- $id(`${_name}Btm${frzNo}`).top = wUnit(currentFrz.btmY);
10759
- $id(`${_name}BtmShadow${frzNo}`).top = wUnit(currentFrz.btmY);
11012
+ $id(`${_name}BtmRoot${frzNo}`).top = wUnit(currentFrz.btmY);
10760
11013
 
10761
11014
  if (!checkKeyUpFunc[`${_name}${g_stateObj.autoAll}`](_j)) {
10762
11015
  currentFrz.keyUpFrame++;
@@ -10821,6 +11074,9 @@ const mainInit = () => {
10821
11074
  g_audio.volume = Math.max((g_audio.volume - (3 * g_stateObj.volume / 100 * C_FRM_AFTERFADE / g_scoreObj.fadeOutTerm) / 1000), 0);
10822
11075
  }
10823
11076
 
11077
+ // 画面揺れの設定
11078
+ g_shakingFunc[g_stateObj.shaking]();
11079
+
10824
11080
  // ユーザカスタムイベント(フレーム毎)
10825
11081
  g_customJsObj.mainEnterFrame.forEach(func => func());
10826
11082
 
@@ -11051,12 +11307,12 @@ const changeAppearanceFilter = (_num = 10) => {
11051
11307
  const topShape = `inset(${_num}% 0% ${numPlus}% 0%)`;
11052
11308
  const bottomShape = `inset(${numPlus}% 0% ${_num}% 0%)`;
11053
11309
 
11054
- $id(`arrowSprite${topNum}`).clipPath = topShape;
11055
- $id(`arrowSprite${bottomNum}`).clipPath = bottomShape;
11056
-
11057
- $id(`filterBar0`).top = wUnit(g_posObj.arrowHeight * _num / MAX_FILTER_POS + g_stateObj.hitPosition);
11058
- $id(`filterBar1`).top = wUnit(g_posObj.arrowHeight * (MAX_FILTER_POS - _num) / MAX_FILTER_POS - g_stateObj.hitPosition);
11059
-
11310
+ for (let j = 0; j < g_stateObj.layerNum; j += 2) {
11311
+ $id(`arrowSprite${topNum + j}`).clipPath = topShape;
11312
+ $id(`arrowSprite${bottomNum + j}`).clipPath = bottomShape;
11313
+ }
11314
+ $id(`filterBar0`).top = wUnit(parseFloat($id(`arrowSprite${topNum}`).top) + g_posObj.arrowHeight * _num / MAX_FILTER_POS);
11315
+ $id(`filterBar1`).top = wUnit(parseFloat($id(`arrowSprite${bottomNum}`).top) + g_posObj.arrowHeight * (MAX_FILTER_POS - _num) / MAX_FILTER_POS);
11060
11316
  if (g_appearanceRanges.includes(g_stateObj.appearance)) {
11061
11317
  $id(`filterView`).top =
11062
11318
  $id(`filterBar${g_hidSudObj.std[g_stateObj.appearance][g_stateObj.reverse]}`).top;
@@ -11113,6 +11369,45 @@ const appearKeyTypes = (_j, _targets, _alphas = fillArray(_targets.length, 1)) =
11113
11369
  });
11114
11370
  };
11115
11371
 
11372
+ /**
11373
+ * FrzReturnの追加処理
11374
+ * @param {number} _rad 回転角度
11375
+ * @param {number[]} _axis 回転軸
11376
+ */
11377
+ const changeReturn = (_rad, _axis) => {
11378
+ g_workObj.frzReturnFlg = true;
11379
+ let _transform = g_workObj.transform;
11380
+ _transform += ` rotate${_axis[0]}(${_rad}deg)`;
11381
+ if (_axis[1] !== undefined) {
11382
+ _transform += ` rotate${_axis[1]}(${_rad}deg)`;
11383
+ }
11384
+ if (document.getElementById(`mainSprite`) !== null) {
11385
+ mainSprite.style.transform = _transform;
11386
+
11387
+ if (_rad < 360 && g_workObj.frzReturnFlg) {
11388
+ setTimeout(() => changeReturn(_rad + 4, _axis), 20);
11389
+ } else {
11390
+ g_workObj.frzReturnFlg = false;
11391
+ }
11392
+ }
11393
+ }
11394
+
11395
+ /**
11396
+ * AutoRetryの設定
11397
+ * @param {number} _retryNum AutoRetryの設定位置(g_settings.autoRetryNum)
11398
+ */
11399
+ const quickRetry = (_retryNum) => {
11400
+ if (g_settings.autoRetryNum >= _retryNum && !g_workObj.autoRetryFlg) {
11401
+ g_workObj.autoRetryFlg = true;
11402
+ setTimeout(() => {
11403
+ g_audio.pause();
11404
+ clearTimeout(g_timeoutEvtId);
11405
+ clearWindow();
11406
+ musicAfterLoaded();
11407
+ }, 16);
11408
+ }
11409
+ };
11410
+
11116
11411
  /**
11117
11412
  * 個別・全体色変化
11118
11413
  * @param {number[]} _mkColor
@@ -11148,7 +11443,7 @@ const changeCssMotions = (_header, _name, _frameNum) => {
11148
11443
  const camelHeader = _header === `` ? _name : `${_header}${toCapitalize(_name)}`;
11149
11444
  g_workObj[`mk${toCapitalize(camelHeader)}CssMotion`][_frameNum]?.forEach((targetj, j) =>
11150
11445
  g_workObj[`${camelHeader}CssMotions`][targetj] =
11151
- g_workObj[`mk${toCapitalize(camelHeader)}CssMotionName`][_frameNum][2 * j + g_workObj.dividePos[targetj]]);
11446
+ g_workObj[`mk${toCapitalize(camelHeader)}CssMotionName`][_frameNum][2 * j + (g_workObj.dividePos[targetj] % 2)]);
11152
11447
  };
11153
11448
 
11154
11449
  /**
@@ -11158,7 +11453,8 @@ const changeCssMotions = (_header, _name, _frameNum) => {
11158
11453
  const changeScrollArrowDirs = (_frameNum) =>
11159
11454
  g_workObj.mkScrollchArrow[_frameNum]?.forEach((targetj, j) => {
11160
11455
  g_workObj.scrollDir[targetj] = g_workObj.scrollDirDefault[targetj] * g_workObj.mkScrollchArrowDir[_frameNum][j];
11161
- g_workObj.dividePos[targetj] = (g_workObj.scrollDir[targetj] === 1 ? 0 : 1);
11456
+ const baseLayer = Math.floor(g_workObj.dividePos[targetj] / 2) * 2;
11457
+ g_workObj.dividePos[targetj] = baseLayer + (g_workObj.scrollDir[targetj] === 1 ? 0 : 1);
11162
11458
  });
11163
11459
 
11164
11460
  /**
@@ -11190,9 +11486,10 @@ const changeHitFrz = (_j, _k, _name, _difFrame = 0) => {
11190
11486
  }
11191
11487
 
11192
11488
  const styfrzBar = $id(`${_name}Bar${frzNo}`);
11489
+ const styfrzBtmRoot = $id(`${_name}BtmRoot${frzNo}`);
11193
11490
  const styfrzBtm = $id(`${_name}Btm${frzNo}`);
11491
+ const styfrzTopRoot = $id(`${_name}TopRoot${frzNo}`);
11194
11492
  const styfrzTop = $id(`${_name}Top${frzNo}`);
11195
- const styfrzTopShadow = $id(`${_name}TopShadow${frzNo}`);
11196
11493
  const styfrzBtmShadow = $id(`${_name}BtmShadow${frzNo}`);
11197
11494
 
11198
11495
  // フリーズアロー位置の修正(ステップゾーン上に来るように)
@@ -11227,11 +11524,9 @@ const changeHitFrz = (_j, _k, _name, _difFrame = 0) => {
11227
11524
  styfrzBar.top = wUnit(currentFrz.barY);
11228
11525
  styfrzBar.height = wUnit(currentFrz.frzBarLength);
11229
11526
  styfrzBar.background = getColor(`HitBar`);
11230
- styfrzBtm.top = wUnit(currentFrz.btmY);
11527
+ styfrzBtmRoot.top = wUnit(currentFrz.btmY);
11231
11528
  styfrzBtm.background = tmpHitColor;
11232
- styfrzTop.top = wUnit(- hitPos);
11233
- styfrzTopShadow.top = styfrzTop.top;
11234
- styfrzBtmShadow.top = styfrzBtm.top;
11529
+ styfrzTopRoot.top = wUnit(- hitPos);
11235
11530
  if (_name === `frz`) {
11236
11531
  const tmpShadowColor = getColor(`HitShadow`);
11237
11532
  styfrzBtmShadow.background = tmpShadowColor === `Default` ? tmpHitColor : tmpShadowColor;
@@ -11242,6 +11537,12 @@ const changeHitFrz = (_j, _k, _name, _difFrame = 0) => {
11242
11537
  }
11243
11538
  }
11244
11539
 
11540
+ // FrzReturnの設定
11541
+ if (g_stateObj.frzReturn !== C_FLG_OFF) {
11542
+ if (!g_workObj.frzReturnFlg) {
11543
+ changeReturn(4, g_frzReturnFunc[g_stateObj.frzReturn]());
11544
+ }
11545
+ }
11245
11546
  g_customJsObj[`judg_${_name}Hit`].forEach(func => func(_difFrame));
11246
11547
  };
11247
11548
 
@@ -11260,6 +11561,13 @@ const changeFailedFrz = (_j, _k) => {
11260
11561
  $id(`frzBar${frzNo}`).background = `#999999`;
11261
11562
  $id(`frzBar${frzNo}`).opacity = 1;
11262
11563
  $id(`frzBtm${frzNo}`).background = `#cccccc`;
11564
+
11565
+ // FrzReturnの設定
11566
+ if (g_stateObj.frzReturn !== C_FLG_OFF) {
11567
+ if (!g_workObj.frzReturnFlg) {
11568
+ changeReturn(4, g_frzReturnFunc[g_stateObj.frzReturn]());
11569
+ }
11570
+ }
11263
11571
  };
11264
11572
 
11265
11573
  /**
@@ -11379,9 +11687,11 @@ const displayDiff = (_difFrame, _fjdg = ``, _justFrames = g_headerObj.justFrames
11379
11687
  } else if (_difFrame > _justFrames) {
11380
11688
  diffJDisp = `<span class="common_diffFast">Fast ${difCnt} Frames</span>`;
11381
11689
  g_resultObj.fast++;
11690
+ quickRetry(4);
11382
11691
  } else if (_difFrame < _justFrames * (-1)) {
11383
11692
  diffJDisp = `<span class="common_diffSlow">Slow ${difCnt} Frames</span>`;
11384
11693
  g_resultObj.slow++;
11694
+ quickRetry(4);
11385
11695
  }
11386
11696
  document.getElementById(`diff${_fjdg}J`).innerHTML = diffJDisp;
11387
11697
  };
@@ -11427,6 +11737,7 @@ const lifeRecovery = () => {
11427
11737
  */
11428
11738
  const lifeDamage = (_excessive = false) => {
11429
11739
  g_workObj.lifeVal -= g_workObj.lifeDmg * (_excessive ? 0.25 : 1);
11740
+ quickRetry(1);
11430
11741
 
11431
11742
  if (g_workObj.lifeVal <= 0) {
11432
11743
  g_workObj.lifeVal = 0;
@@ -11472,6 +11783,14 @@ const judgeRecovery = (_name, _difFrame) => {
11472
11783
  lifeRecovery();
11473
11784
  finishViewing();
11474
11785
 
11786
+ if (g_stateObj.freezeReturn !== C_FLG_OFF) {
11787
+ if ((g_resultObj.ii + g_resultObj.shakin) % 100 === 0 && !g_workObj.frzReturnFlg) {
11788
+ changeReturn(1, g_frzReturnFunc[g_stateObj.frzReturn]());
11789
+ }
11790
+ }
11791
+ if (_name === `shakin`) {
11792
+ quickRetry(3);
11793
+ }
11475
11794
  g_customJsObj[`judg_${_name}`].forEach(func => func(_difFrame));
11476
11795
  };
11477
11796
 
@@ -11509,6 +11828,7 @@ const judgeMatari = _difFrame => {
11509
11828
  changeJudgeCharacter(`matari`, g_lblNameObj.j_matari);
11510
11829
  comboJ.textContent = ``;
11511
11830
  finishViewing();
11831
+ quickRetry(2);
11512
11832
 
11513
11833
  g_customJsObj.judg_matari.forEach(func => func(_difFrame));
11514
11834
  };
@@ -11743,11 +12063,19 @@ const resultInit = () => {
11743
12063
  // 設定の組み立て処理 (Ex: 4x, Brake, Reverse, Sudden+, NoRecovery)
11744
12064
  let playStyleData = [
11745
12065
  `${g_stateObj.speed}${g_lblNameObj.multi}`,
11746
- `${withOptions(g_stateObj.motion, C_FLG_OFF)}`,
12066
+ withOptions(g_stateObj.motion, C_FLG_OFF),
11747
12067
  `${withOptions(g_stateObj.reverse, C_FLG_OFF,
11748
12068
  getStgDetailName(g_stateObj.scroll !== '---' ? 'R-' : 'Reverse'))}${withOptions(g_stateObj.scroll, '---')}`,
11749
- `${withOptions(g_stateObj.appearance, `Visible`)}`,
11750
- `${withOptions(g_stateObj.gauge, g_settings.gauges[0])}`
12069
+ withOptions(g_stateObj.appearance, `Visible`),
12070
+ withOptions(g_stateObj.gauge, g_settings.gauges[0]),
12071
+ withOptions(g_stateObj.playWindow, `Default`),
12072
+ withOptions(g_stateObj.stepArea, `Default`),
12073
+ withOptions(g_stateObj.frzReturn, C_FLG_OFF, `FR:${g_stateObj.frzReturn}`),
12074
+ withOptions(g_stateObj.shaking, C_FLG_OFF),
12075
+ withOptions(g_stateObj.effect, C_FLG_OFF),
12076
+ withOptions(g_stateObj.camoufrage, C_FLG_OFF, `Cmf:${g_stateObj.camoufrage}`),
12077
+ withOptions(g_stateObj.swapping, C_FLG_OFF, `Swap:${g_stateObj.swapping}`),
12078
+ withOptions(g_stateObj.judgRange, `Normal`, `Judg:${g_stateObj.judgRange}`),
11751
12079
  ].filter(value => value !== ``).join(`, `);
11752
12080
 
11753
12081
  // Display設定の組み立て処理 (Ex: Step : FlatBar, Judge, Life : OFF)
@@ -11796,6 +12124,23 @@ const resultInit = () => {
11796
12124
  makeCssResultPlayData(`lblDisplay2Data`, dataRX, g_cssObj.result_style, 5, display2Data),
11797
12125
  );
11798
12126
 
12127
+ // 設定項目が多い場合に2行に分解して表示する処理
12128
+ let playStyleBreakNum = lblStyleData.textContent.length;
12129
+ if (lblStyleData.textContent.length > 60) {
12130
+ for (let j = Math.floor(lblStyleData.textContent.length / 2); j > 0; j--) {
12131
+ if (lblStyleData.textContent[j] === `,`) {
12132
+ playStyleBreakNum = j + 2;
12133
+ break;
12134
+ }
12135
+ }
12136
+ lblStyleData.style.top = `${parseFloat(lblStyleData.style.top) - 3}px`;
12137
+ lblStyleData.innerHTML = `${lblStyleData.textContent.slice(0, playStyleBreakNum)}<br>` +
12138
+ `${lblStyleData.textContent.slice(playStyleBreakNum)}`;
12139
+ lblStyleData.style.fontSize = `${getFontSize(lblStyleData.textContent.slice(0, playStyleBreakNum), 350, getBasicFont(), 10)}px`;
12140
+ } else {
12141
+ lblStyleData.style.fontSize = `${getFontSize(lblStyleData.textContent, 350, getBasicFont(), 14)}px`;
12142
+ }
12143
+
11799
12144
  /**
11800
12145
  * キャラクタ、スコア描画のID共通部、色CSS名、スコア変数名
11801
12146
  * @property {number} pos 表示位置(縦)
@@ -12065,8 +12410,13 @@ const resultInit = () => {
12065
12410
  drawText(unEscapeHtml(mTitleForView[1]), { hy: 2 });
12066
12411
  drawText(`📝 ${unEscapeHtml(g_headerObj.tuning)} / 🎵 ${unEscapeHtml(artistName)}`, { hy: mTitleForView[1] !== `` ? 3 : 2, siz: 12 });
12067
12412
  drawText(unEscapeHtml(difDataForImage), { hy: 4 });
12068
- drawText(playStyleData, { hy: 5 });
12069
12413
 
12414
+ if (playStyleData.length > 60) {
12415
+ drawText(playStyleData.slice(0, playStyleBreakNum), { hy: 5, siz: getFontSize(playStyleData.slice(0, playStyleBreakNum), 370, getBasicFont(), 14) });
12416
+ drawText(playStyleData.slice(playStyleBreakNum), { hy: 6, siz: getFontSize(playStyleData.slice(playStyleBreakNum), 370, getBasicFont(), 14) });
12417
+ } else {
12418
+ drawText(playStyleData, { hy: 5, siz: getFontSize(lblStyleData.textContent, 370, getBasicFont(), 15) });
12419
+ }
12070
12420
  Object.keys(jdgScoreObj).forEach(score => {
12071
12421
  drawText(g_lblNameObj[`j_${score}`], { hy: 7 + jdgScoreObj[score].pos, color: jdgScoreObj[score].dfColor });
12072
12422
  drawText(g_resultObj[score], { x: 200, hy: 7 + jdgScoreObj[score].pos, align: C_ALIGN_RIGHT });