danoniplus 40.6.0 → 40.7.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 : 2025/03/16
7
+ * Revised : 2025/03/22
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 40.6.0`;
12
- const g_revisedDate = `2025/03/16`;
11
+ const g_version = `Ver 40.7.0`;
12
+ const g_revisedDate = `2025/03/22`;
13
13
 
14
14
  // カスタム用バージョン (danoni_custom.js 等で指定可)
15
15
  let g_localVersion = ``;
@@ -2605,6 +2605,19 @@ const initialControl = async () => {
2605
2605
  const customKeyList = g_headerObj.keyLists.filter(val =>
2606
2606
  g_keyObj.defaultKeyList.findIndex(key => key === val) < 0);
2607
2607
 
2608
+ if (customKeyList.length === 0) {
2609
+ g_settings.preconditions = g_settings.preconditions.filter(val => !val.includes(`g_editorTmp`));
2610
+ }
2611
+
2612
+ const addNewOrderGroup = (_orgList, _sortRule) => {
2613
+ // インデックスを保持した配列を作成、ルールに従ってソート
2614
+ const indexedList = _orgList.map((value, idx) => ({ value, idx }));
2615
+ const sortedList = [...indexedList].sort(_sortRule);
2616
+ // ソート後の配列のインデックスに基づいて、元のインデックスを取得
2617
+ const newIdxs = sortedList.map(({ idx }) => indexedList.findIndex(({ idx: originalIdx }) => originalIdx === idx));
2618
+ return !newIdxs.every((val, j) => val === j) ? newIdxs : undefined;
2619
+ };
2620
+
2608
2621
  customKeyList.forEach(key => {
2609
2622
  const keyBase = `${key}_0`;
2610
2623
  const keyCtrlPtn = `${g_keyObj.defaultProp}${keyBase}`;
@@ -2613,14 +2626,21 @@ const initialControl = async () => {
2613
2626
  const orgKeyNum = g_keyObj[keyCtrlPtn].length;
2614
2627
  const baseX = Math.floor(Math.random() * (100 - keyGroupList.length));
2615
2628
 
2629
+ const divPos = g_keyObj[`div${keyBase}`];
2630
+ const divMaxPos = g_keyObj[`divMax${keyBase}`] ?? Math.max(...g_keyObj[`pos${keyBase}`]) + 1;
2631
+ const stdPos = Math.max(divPos, divMaxPos - divPos);
2632
+ const [deltaXAbove, deltaXBelow] = [(divPos - stdPos) / 2, (divMaxPos - divPos - stdPos) / 2];
2633
+
2616
2634
  keyGroupList.forEach((keyGroupNo, j) => {
2617
2635
  const keyN = keyGroupNo === `0` ? key : `${key}_${j + 1}`;
2618
2636
  const filterCond = (j) => keyGroup[j].findIndex(val => val === keyGroupNo) >= 0;
2619
2637
  const keyCtrlList = g_keyObj[keyCtrlPtn].filter((val, j) => filterCond(j));
2620
2638
  const charaList = g_keyObj[`chara${keyBase}`].filter((val, j) => filterCond(j));
2621
2639
  const colorList = g_keyObj[`color${keyBase}_0`].filter((val, j) => filterCond(j));
2640
+ const stepRtnList = g_keyObj[`stepRtn${keyBase}_0`].filter((val, j) => filterCond(j));
2622
2641
  const keyNum = g_keyObj[keyCtrlPtn].filter((val, j) => filterCond(j)).length;
2623
2642
 
2643
+ // ---- Dancing☆Onigiri (CW Edition対応)のフォーマット
2624
2644
  g_editorTmp[keyN] = {};
2625
2645
  g_editorTmp[keyN].id = orgKeyNum * 100 + baseX + j;
2626
2646
  g_editorTmp[keyN].num = keyNum;
@@ -2636,6 +2656,77 @@ const initialControl = async () => {
2636
2656
  return `${frzName}_data`;
2637
2657
  });
2638
2658
  g_editorTmp[keyN].colorGroup = colorList.map(val => val % 3);
2659
+
2660
+ // orderGroupsのカスタマイズ
2661
+ if (divMaxPos > divPos) {
2662
+
2663
+ // posXの実際の相対位置を計算
2664
+ const orgPosList = g_keyObj[`pos${keyBase}`].filter((val, j) => filterCond(j));
2665
+ const posList = orgPosList.map(val => val < divPos ? val - deltaXAbove : val - divPos - deltaXBelow);
2666
+
2667
+ g_editorTmp[keyN].orderGroups = [];
2668
+
2669
+ // パターン1: 上下グループ分けして各グループ内で位置順にソート(上下反転)
2670
+ const upDownIdxs = addNewOrderGroup(orgPosList, (a, b) => {
2671
+ const aAbove = a.value < divPos;
2672
+ const bAbove = b.value < divPos;
2673
+ if (aAbove !== bAbove) return Number(aAbove) - Number(bAbove);
2674
+ return a.value - b.value;
2675
+ });
2676
+ if (upDownIdxs !== undefined) {
2677
+ g_editorTmp[keyN].orderGroups.push(upDownIdxs);
2678
+ }
2679
+
2680
+ // パターン2: 単純にステップゾーンのX座標が小さい順にソート
2681
+ const sortedIdxs = addNewOrderGroup(posList, (a, b) => a.value - b.value);
2682
+ if (sortedIdxs !== undefined) {
2683
+ g_editorTmp[keyN].orderGroups.push(sortedIdxs);
2684
+ }
2685
+ if (g_editorTmp[keyN].orderGroups.length === 0) {
2686
+ delete g_editorTmp[keyN].orderGroups;
2687
+ }
2688
+ }
2689
+
2690
+ // ---- ダンおに譜面作成エディタ ver3フォーマット
2691
+
2692
+ // 既存のシャッフルグループからミラー配列を自動生成
2693
+ let k = 0, n = 0, convTxt = ``;
2694
+ let prevMirrorList = [];
2695
+ while (g_keyObj[`shuffle${keyBase}_${k}`] !== undefined) {
2696
+
2697
+ const orgTmpList = []
2698
+ const mirrorTmpList = [];
2699
+ const mirrorList = [];
2700
+ g_keyObj[`shuffle${keyBase}_${k}`].filter((val, m) => filterCond(m))
2701
+ .forEach((_val, _i) => orgTmpList[_val]?.push(_i) || (orgTmpList[_val] = [_i]));
2702
+ orgTmpList.forEach((list, idx) => mirrorTmpList[idx] = list.toReversed());
2703
+ orgTmpList?.forEach((list, a) => list?.forEach((val, b) => mirrorList[orgTmpList[a][b]] = mirrorTmpList[a][b]));
2704
+ if (!mirrorList.every((val, p) => val === prevMirrorList[p])) {
2705
+ convTxt += `\$conv${n + 1}=Mirror${n + 1},${mirrorList.join(',')}<br>`;
2706
+ prevMirrorList = mirrorList.concat();
2707
+ n++;
2708
+ }
2709
+ k++;
2710
+ }
2711
+
2712
+ // 矢印・フリーズアローのヘッダー情報を定義
2713
+ let noteTxt = ``, freezeTxt = ``;
2714
+ g_editorTmp[keyN].noteNames.forEach((val, j) =>
2715
+ noteTxt += `|${val.slice(0, -(`_data`.length))}[i]_data=[a${String(j).padStart(2, `0`)}]|[E]<br>`);
2716
+
2717
+ g_editorTmp[keyN].freezeNames.forEach((val, j) =>
2718
+ freezeTxt += `|${val.slice(0, -(`_data`.length))}[i]_data=[f${String(j).padStart(2, `0`)}]|[E]<br>`);
2719
+
2720
+ g_editorTmp2 += g_editorTmp2Template
2721
+ .replace(`[__KEY__]`, keyN)
2722
+ .replace(`[__MAP__]`, colorList.map(val => val < 3 ? (val + 1) % 3 : val % 7).join(','))
2723
+ .replace(`[__POS__]`, fillArray(keyNum).map((val, j) =>
2724
+ isNaN(parseFloat(stepRtnList[j])) ? 28 : 24).join(`,`))
2725
+ .replace(`[__TXT__]`, g_editorTmp[keyN].chars.map(val => val.replace(`, `, ``)).join(`,`))
2726
+ .replace(`[__CONV__]`, convTxt)
2727
+ .replace(`[__NOTE__]`, noteTxt)
2728
+ .replace(`[__FREEZE__]`, freezeTxt)
2729
+ .replaceAll(`\n`, ``);
2639
2730
  });
2640
2731
  });
2641
2732
  };
@@ -5275,9 +5366,14 @@ const preconditionInit = () => {
5275
5366
 
5276
5367
  createDivCss2Label(`lblPrecondView`, viewKeyStorage(`g_rootObj`), g_lblPosObj.lblPrecondView),
5277
5368
  createCss2Button(`btnPrecondView`, g_lblNameObj.b_copyStorage, () =>
5278
- copyTextToClipboard(
5279
- viewKeyStorage(g_settings.preconditions[g_settings.preconditionNum * numOfPrecs + g_settings.preconditionNumSub], ``, false),
5280
- g_msgInfoObj.I_0007),
5369
+ copyTextToClipboard((() => {
5370
+ const key = g_settings.preconditions[g_settings.preconditionNum * numOfPrecs + g_settings.preconditionNumSub];
5371
+ if (key === `g_editorTmp2`) {
5372
+ return g_editorTmp2.replaceAll(`<br>`, `\r\n`).replaceAll(`&nbsp;`, ` `);
5373
+ } else {
5374
+ return viewKeyStorage(key, ``, false);
5375
+ }
5376
+ })(), g_msgInfoObj.I_0007),
5281
5377
  g_lblPosObj.btnPrecondView, g_cssObj.button_Default, g_cssObj.button_ON),
5282
5378
  );
5283
5379
  setUserSelect($id(`lblPrecondView`), `text`);
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2019/11/19
8
- * Revised : 2025/03/12 (v40.5.2)
8
+ * Revised : 2025/03/22 (v40.7.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -1179,7 +1179,7 @@ const g_settings = {
1179
1179
  settingWindowNum: 0,
1180
1180
 
1181
1181
  preconditions: [`g_rootObj`, `g_headerObj`, `g_keyObj`, `g_scoreObj`, `g_workObj`,
1182
- `g_detailObj`, `g_stateObj`, `g_attrObj`, `g_editorTmp`],
1182
+ `g_detailObj`, `g_stateObj`, `g_attrObj`, `g_editorTmp`, `g_editorTmp2`],
1183
1183
  preconditionNum: 0,
1184
1184
  preconditionNumSub: 0,
1185
1185
  };
@@ -3187,7 +3187,42 @@ g_keycons.groups.forEach(type => {
3187
3187
  tmpName.forEach(property => g_keyObj[`${property.slice(0, -2)}`] = g_keyObj[property].concat());
3188
3188
  });
3189
3189
 
3190
+ // 外部エディター用テンプレート
3191
+ // g_editorTmp: Dancing☆Onigiriエディター (CW Edition対応)
3192
+ // g_editorTmp2: ダンおに譜面作成エディタ ver3.x
3190
3193
  const g_editorTmp = {};
3194
+ let g_editorTmp2 = ``;
3195
+
3196
+ const g_editorTmp2Template = `
3197
+ <br>
3198
+ \$key=[__KEY__]<br>
3199
+ \$map=[__MAP__]<br>
3200
+ \$pos=[__POS__]<br>
3201
+ \$txt=[__TXT__]<br>
3202
+ [__CONV__]
3203
+ <br>
3204
+ \$dosformat=<br>function externalDosInit() {[E]<br>
3205
+ [E]<br>
3206
+ &nbsp;&nbsp;g_externalDos = \`[E]<br>
3207
+ [E]<br>
3208
+ [header][E]<br>
3209
+ [E]<br>
3210
+ [notestart]<br>
3211
+ [__NOTE__]
3212
+ <br>
3213
+ [__FREEZE__]
3214
+ <br>
3215
+ |speed[i]_data=[speed]|[E]<br>
3216
+ |boost[i]_data=[boost]|[E]<br>
3217
+ [datatext][E]<br>
3218
+ |edit[i]_info=[edit]|[E][E]<br>
3219
+ [noteend]<br>
3220
+ <br>
3221
+ [footer]<br>
3222
+ &nbsp;&nbsp;\`;[E]<br>
3223
+ }<br>
3224
+ <br>
3225
+ `;
3191
3226
 
3192
3227
  // 特殊キーのコピー種 (simple: 代入、multiple: 配列ごと代入)
3193
3228
  // 後でプロパティ削除に影響するため、先頭文字が全く同じ場合は長い方を先に定義する (例: divMax, div)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "danoniplus",
3
- "version": "40.6.0",
3
+ "version": "40.7.0",
4
4
  "description": "Dancing☆Onigiri (CW Edition) - Web-based Rhythm Game",
5
5
  "main": "./js/danoni_main.js",
6
6
  "scripts": {