danoniplus 50.5.2 → 51.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
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 50.5.2`;
11
+ const g_version = `Ver 51.0.0`;
12
12
  const g_revisedDate = `2026/09/23`;
13
13
 
14
14
  // カスタム用バージョン (danoni_custom.js 等で指定可)
@@ -16,7 +16,8 @@ let g_localVersion = ``;
16
16
  let g_localVersion2 = ``;
17
17
 
18
18
  // ショートカット用文字列(↓の文字列を検索することで対象箇所へジャンプできます)
19
- // 共通:water 初期化:peach タイトル:melon データ管理:pear 前提条件表示:mango 設定:lime ディスプレイ:lemon 拡張設定:apple キーコンフィグ:orange 譜面読込:strawberry メイン:banana 結果:grape
19
+ // 共通:water 初期化:peach タイトル:melon データ管理:pear 前提条件表示:mango
20
+ // 設定:lime ディスプレイ:lemon 拡張設定:apple キーコンフィグ:orange 譜面読込:strawberry メイン:banana 結果:grape
20
21
  // シーンジャンプ:Scene
21
22
 
22
23
  /**
@@ -2140,7 +2141,9 @@ const fillCanvasText = (_ctx, _text, _x, _y, { siz = 15, font, color, align = C_
2140
2141
  */
2141
2142
  const createImg = (_id, _imgPath, _x, _y, _width, _height) => {
2142
2143
  const div = createDiv(_id, _x, _y, _width, _height);
2143
- div.innerHTML = `<img id="${_id}img" src="${_imgPath}" style="width:${wUnit(_width)};height:${wUnit(_height)}"${g_isFile ? `` : ` crossOrigin="anonimous"`}>`;
2144
+ div.innerHTML =
2145
+ `<img id="${_id}img" src="${_imgPath}" style="width:${wUnit(_width)};height:${wUnit(_height)}"` +
2146
+ `${g_isFile ? `` : ` crossOrigin="anonimous"`}>`;
2144
2147
 
2145
2148
  return div;
2146
2149
  };
@@ -2562,7 +2565,9 @@ const makeWarningWindow = (_text = ``, { resetFlg = false, backBtnUse = false }
2562
2565
  * @param {number} [object._y=0]
2563
2566
  * @param {number} [object._w=g_btnWidth()]
2564
2567
  */
2565
- const makeInfoWindow = (_text, _animationName = ``, { _backColor = `#ccccff`, _textColor = `#000066`, _pointerEvents = C_DIS_NONE, _x = g_btnX(), _y = 0, _w = g_btnWidth() } = {}) => {
2568
+ const makeInfoWindow = (_text, _animationName = ``, {
2569
+ _backColor = `#ccccff`, _textColor = `#000066`, _pointerEvents = C_DIS_NONE, _x = g_btnX(), _y = 0, _w = g_btnWidth()
2570
+ } = {}) => {
2566
2571
  const lblWarning = setWindowStyle(`<p>${_text}</p>`, _backColor, _textColor, C_ALIGN_CENTER, { _x, _y, _w });
2567
2572
  lblWarning.style.pointerEvents = _pointerEvents;
2568
2573
 
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2019/11/19
8
- * Revised : 2026/09/13 (v50.5.0)
8
+ * Revised : 2026/09/23 (v51.0.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -1322,32 +1322,57 @@ const C_LFE_CUSTOM = `Custom`;
1322
1322
  const C_LFE_MAXLIFE = `maxLife`;
1323
1323
 
1324
1324
  /**
1325
- * ゲージ初期設定
1325
+ * 汎用ゲージの定義(g_presetObj.gauge/gaugeCustomと同じBorder/Recovery/Damage/Initに
1326
+ * Variable(回復・ダメージ量が矢印数等で変動:ON/固定:OFF)を加えた5項目のみ)
1327
+ * headerOverridable: 譜面ヘッダー(difData)による上書き対象(Step3)かどうか
1328
+ * deriveRecoveryFrom: difDataしか参照値が無い場合のみ、参照元ゲージの回復量を2倍にして使う
1326
1329
  */
1330
+ const g_gaugeDefObj = {
1331
+ Original: { Border: `x`, Recovery: 6, Damage: 40, Init: 25, Variable: C_FLG_OFF, headerOverridable: true },
1332
+ Heavy: { Border: `x`, Recovery: 2, Damage: 50, Init: 50, Variable: C_FLG_OFF },
1333
+ NoRecovery: { Border: `x`, Recovery: 0, Damage: 50, Init: 100, Variable: C_FLG_OFF },
1334
+ SuddenDeath: { Border: `x`, Recovery: 0, Damage: C_LFE_MAXLIFE, Init: 100, Variable: C_FLG_OFF },
1335
+ Practice: { Border: `x`, Recovery: 0, Damage: 0, Init: 50, Variable: C_FLG_OFF },
1336
+ Light: { Border: `x`, Recovery: 12, Damage: 40, Init: 25, Variable: C_FLG_OFF, headerOverridable: true, deriveRecoveryFrom: `Original` },
1337
+
1338
+ Normal: { Border: 70, Recovery: 2, Damage: 7, Init: 25, Variable: C_FLG_ON, headerOverridable: true },
1339
+ Hard: { Border: 0, Recovery: 1, Damage: 50, Init: 100, Variable: C_FLG_ON },
1340
+ Easy: { Border: 70, Recovery: 4, Damage: 7, Init: 25, Variable: C_FLG_ON, headerOverridable: true, deriveRecoveryFrom: `Normal` },
1341
+ };
1342
+
1343
+ /**
1344
+ * カスタムゲージの選択状態・個別上書き値
1345
+ * - g_gaugeSelObj[scoreId] = {
1346
+ * __order: [名前, ...], // customGauge指定時のみ存在。並び順がそのままカーソル移動の順序
1347
+ * 名前: { 上書きプロパティ }, // customGaugeのインライン指定なら{Variable}のみ、
1348
+ * // gaugeXXXヘッダー由来なら{Border,Recovery,Damage,Init}を含む
1349
+ * }
1350
+ * - 'default'キー:g_presetObj.gaugeList由来の、譜面指定が無い場合の共通デフォルト(同じ形)
1351
+ * 上書きプロパティは常にg_gaugeDefObj[名前]とマージして使う(Border等が無ければg_gaugeDefObjの値を使う)
1352
+ *
1353
+ * - 例:
1354
+ * g_gaugeSelObj = {
1355
+ * default: {
1356
+ * __order: [`Original`, `Normal`],
1357
+ * Original: { Variable: C_FLG_OFF },
1358
+ * },
1359
+ * 0: {
1360
+ * __order: [], // カスタムゲージ未定義 (difDataの定義もしくはデフォルト値を使用)
1361
+ * },
1362
+ * 1: {
1363
+ * __order: [`Escape`, `Normal`],
1364
+ * Escape: { Variable: C_FLG_ON, Border: 0, Recovery: 1, Damage: 100, Init: 100 }, // |customGauge2=Escape::V|gaugeEscape2=0,1,100,100|
1365
+ * Normal: { Variable: C_FLG_OFF, Border: 75, Recovery: 3, Damage: 7, Init: 25 }, // |customGauge2=Normal::F|gaugeNormal2=75,3,7,25|
1366
+ * },
1367
+ * };
1368
+ */
1369
+ const g_gaugeSelObj = {};
1370
+
1371
+ /** どの名前をどの順で選択肢に出すかだけを持つ。詳細値はg_gaugeDefObjやg_gaugeSelObjを参照 */
1327
1372
  const g_gaugeOptionObj = {
1328
1373
  survival: [`Original`, `Heavy`, `NoRecovery`, `SuddenDeath`, `Practice`, `Light`],
1329
1374
  border: [`Normal`, `Hard`, `SuddenDeath`, `Easy`],
1330
- custom: [],
1331
- customDefault: [],
1332
1375
  customFulls: {},
1333
-
1334
- initSurvival: [25, 50, 100, 100, 50, 25],
1335
- rcvSurvival: [6, 2, 0, 0, 0, 12],
1336
- dmgSurvival: [40, 50, 50, C_LFE_MAXLIFE, 0, 40],
1337
- typeSurvival: [C_LFE_SURVIVAL, C_LFE_SURVIVAL, C_LFE_SURVIVAL, C_LFE_SURVIVAL, C_LFE_SURVIVAL, C_LFE_SURVIVAL],
1338
- varSurvival: [C_FLG_OFF, C_FLG_OFF, C_FLG_OFF, C_FLG_OFF, C_FLG_OFF, C_FLG_OFF],
1339
- clearSurvival: [0, 0, 0, 0, 0, 0],
1340
-
1341
- initBorder: [25, 100, 100, 25],
1342
- rcvBorder: [2, 1, 0, 4],
1343
- dmgBorder: [7, 50, C_LFE_MAXLIFE, 7],
1344
- typeBorder: [C_LFE_BORDER, C_LFE_BORDER, C_LFE_SURVIVAL, C_LFE_BORDER],
1345
- varBorder: [C_FLG_ON, C_FLG_ON, C_FLG_OFF, C_FLG_ON],
1346
- clearBorder: [70, 0, 0, 70],
1347
-
1348
- varCustom: [],
1349
- varCustomDefault: [],
1350
- defaultList: [`survival`, `border`],
1351
1376
  defaultPlusList: [`survival`, `border`, `customDefault`],
1352
1377
  };
1353
1378
  let g_gaugeType;
@@ -1506,7 +1531,7 @@ const g_settings = {
1506
1531
  settingWindowNum: 0,
1507
1532
 
1508
1533
  preconditions: [`g_rootObj`, `g_headerObj`, `g_keyObj`, `g_scoreObj`, `g_workObj`,
1509
- `g_detailObj`, `g_stateObj`, `g_attrObj`, `g_editorTmp`, `g_editorTmp2`],
1534
+ `g_detailObj`, `g_stateObj`, `g_attrObj`, `g_gaugeDefObj`, `g_gaugeSelObj`, `g_editorTmp`, `g_editorTmp2`],
1510
1535
  preconditionNum: 0,
1511
1536
  preconditionNumSub: 0,
1512
1537
  };
@@ -5302,6 +5327,8 @@ const g_root = {
5302
5327
  get g_imgObj() { return g_imgObj },
5303
5328
  get g_judgObj() { return g_judgObj },
5304
5329
  get g_judgRanges() { return g_judgRanges },
5330
+ get g_gaugeDefObj() { return g_gaugeDefObj },
5331
+ get g_gaugeSelObj() { return g_gaugeSelObj },
5305
5332
  };
5306
5333
  const getPathVal = _path => _path.split(`.`).reduce((o, k) => o?.[k], g_root);
5307
5334
  const setPathVal = (_path, _value) => {
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2026/09/13
8
- * Revised :
8
+ * Revised : 2026/09/23 (v51.0.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -171,7 +171,8 @@ const fetchMusicBlobUrl = (_url, _lblLoading) => new Promise((resolve, reject) =
171
171
  _lblLoading.textContent = g_lblNameObj.pleaseWait;
172
172
  resolve(blobUrl);
173
173
  } else {
174
- makeWarningWindow(`${g_msgInfoObj.E_0041.split('{0}').join(getFullPath(_url))}<br>(${request.status} ${request.statusText})`, { backBtnUse: true });
174
+ makeWarningWindow(`${g_msgInfoObj.E_0041.split('{0}').join(getFullPath(_url))}<br>(${request.status} ${request.statusText})`,
175
+ { backBtnUse: true });
175
176
  reject(new Error(`HTTP ${request.status}`));
176
177
  }
177
178
  });
@@ -663,11 +664,14 @@ const applySRandom = (_keyNum, _shuffleGroup, _arrowHeader, _frzHeader) => {
663
664
  const getFreeSpaces = ({ scatterFrame = 0, frzFlg = false, prevFlg = false } = {}) =>
664
665
  _group.filter(_key =>
665
666
  // 通常矢印と重ならない
666
- tmpArrowData[_key].find(_other => _arrow >= _other - scatterFrame && _arrow <= _other + scatterFrame) === undefined
667
+ tmpArrowData[_key].find(_other =>
668
+ _arrow >= _other - scatterFrame && _arrow <= _other + scatterFrame) === undefined
667
669
  // フリーズと重ならない
668
- && (!frzFlg || tmpFrzData[_key].find(_freeze => _arrow >= _freeze.begin - scatterFrame && _arrow <= _freeze.end + scatterFrame) === undefined)
670
+ && (!frzFlg || tmpFrzData[_key].find(_freeze =>
671
+ _arrow >= _freeze.begin - scatterFrame && _arrow <= _freeze.end + scatterFrame) === undefined)
669
672
  // 直前の矢印と重ならない
670
- && (!prevFlg || tmpArrowData[_key].find(_other => prev2Num === _other) === undefined)
673
+ && (!prevFlg || tmpArrowData[_key].find(_other =>
674
+ prev2Num === _other) === undefined)
671
675
  );
672
676
 
673
677
  // 置ける場所を検索
@@ -2266,7 +2270,9 @@ const getArrowSettings = () => {
2266
2270
 
2267
2271
  g_workObj.stepX[j] = g_keyObj.blank * stdPos + (g_headerObj.playingWidth - C_ARW_WIDTH) / 2;
2268
2272
  const baseLayer = g_keyObj[`layerGroup${keyCtrlPtn}`]?.[j] || 0;
2269
- g_workObj.dividePos[j] = baseLayer * 2 + ((posj <= divideCnt ? 0 : 1) + (scrollDirOptions[j] === 1 ? 0 : 1) + (g_stateObj.reverse === C_FLG_OFF ? 0 : 1)) % 2;
2273
+ g_workObj.dividePos[j] = baseLayer * 2 + (
2274
+ (posj <= divideCnt ? 0 : 1) + (scrollDirOptions[j] === 1 ? 0 : 1) + (g_stateObj.reverse === C_FLG_OFF ? 0 : 1)
2275
+ ) % 2;
2270
2276
  g_workObj.scrollDir[j] = (posj <= divideCnt ? 1 : -1) * scrollDirOptions[j] * (g_stateObj.reverse === C_FLG_OFF ? 1 : -1);
2271
2277
 
2272
2278
  // 個別色設定
@@ -2428,7 +2434,9 @@ const getArrowSettings = () => {
2428
2434
  g_workObj.arrowReturnVal = 0;
2429
2435
  g_gameOverFlg = false;
2430
2436
  g_finishFlg = true;
2431
- g_workObj.nonDefaultSc = g_headerObj.keyRetry !== C_KEY_RETRY || g_headerObj.keyTitleBack !== C_KEY_TITLEBACK || g_headerObj.keyPause !== C_KEY_PAUSE;
2437
+ g_workObj.nonDefaultSc = g_headerObj.keyRetry !== C_KEY_RETRY ||
2438
+ g_headerObj.keyTitleBack !== C_KEY_TITLEBACK ||
2439
+ g_headerObj.keyPause !== C_KEY_PAUSE;
2432
2440
  if (g_headerObj.scAreaWidth === 0 && (
2433
2441
  g_headerObj.keyRetry !== g_headerObj.keyRetryDef2 ||
2434
2442
  g_headerObj.keyTitleBack !== g_headerObj.keyTitleBackDef2 ||
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2026/09/13
8
- * Revised :
8
+ * Revised : 2026/09/23 (v51.0.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -206,20 +206,65 @@ const initialControl = async () => {
206
206
  g_stateObj.dosDivideFlg = setBoolVal(document.getElementById(`externalDosDivide`)?.value ?? getQueryParamVal(`dosDivide`));
207
207
  g_stateObj.scoreLockFlg = setBoolVal(document.getElementById(`externalDosLock`)?.value ?? getQueryParamVal(`dosLock`));
208
208
 
209
- // 非分割時は resetGaugeSetting が全難易度を一括構築するため、初回のみで十分
209
+ // カスタムゲージ設定(共通設定ファイル)
210
+ addGaugeFulls(g_gaugeOptionObj.survival);
211
+ addGaugeFulls(g_gaugeOptionObj.border);
212
+
213
+ if (g_presetObj.gaugeCustom !== undefined) {
214
+ g_gaugeSelObj.default ??= { __order: [] };
215
+ Object.entries(g_presetObj.gaugeCustom).forEach(([name, def]) =>
216
+ g_gaugeSelObj.default[name] = { ...g_gaugeSelObj.default[name], ...def });
217
+ }
218
+ if (g_presetObj.gaugeList !== undefined) {
219
+ g_gaugeSelObj.default ??= { __order: [] };
220
+ g_gaugeSelObj.default.__order ??= [];
221
+ Object.keys(g_presetObj.gaugeList).forEach(name => {
222
+ g_gaugeSelObj.default.__order.push(name);
223
+ g_gaugeSelObj.default[name] = { ...g_gaugeSelObj.default[name], Variable: boolToSwitch(g_presetObj.gaugeList[name] === `V`) };
224
+ });
225
+ addGaugeFulls(g_gaugeSelObj.default.__order);
226
+ }
227
+
228
+ // 初期色設定(譜面ヘッダー)の初期設定
229
+ Object.assign(g_headerObj, resetBaseColorList(g_headerObj, g_rootObj));
230
+
231
+ // 非分割時は getGaugeSetting が全難易度を一括構築するため、初回のみで十分
210
232
  const loopCount = g_stateObj.dosDivideFlg ? g_headerObj.keyLabels.length : 1;
211
233
 
212
- for (let j = 0; j < g_headerObj.keyLabels.length; j++) {
234
+ for (let j = 0; j < g_headerObj.difLabels.length; j++) {
213
235
 
214
236
  // 譜面ファイルが分割されている場合、譜面詳細情報取得のために譜面をロード
215
237
  if (g_stateObj.dosDivideFlg) {
216
238
  await loadChartFile(j);
217
- resetColorSetting(j);
239
+
240
+ if (g_stateObj.scoreLockFlg) {
241
+ Object.assign(g_rootObj, copySetColor(g_rootObj, j));
242
+
243
+ // 分割先のファイルで初期色が未定義の場合はデフォルト値を適用
244
+ [``, `Shadow`].forEach(pattern =>
245
+ [`set`, `frz`].forEach(arrow => {
246
+ // frzShadowColorStrのみ、空で構成された初期配列があるためその条件を追加して除外条件とする
247
+ if (!hasVal(g_rootObj[`${arrow}${pattern}Color${j + 1}`])
248
+ && g_headerObj[`${arrow}${pattern}ColorStr`]?.flat()?.some(val => hasVal(val))) {
249
+ g_rootObj[`${arrow}${pattern}Color`] = g_headerObj[`${arrow}${pattern}ColorStr`].join(`,`);
250
+ }
251
+ })
252
+ );
253
+ }
218
254
  }
219
- getScoreDetailData(j);
255
+ // 初期色設定(譜面ヘッダー)の譜面別設定
256
+ Object.assign(g_headerObj, resetBaseColorList(g_headerObj, g_rootObj, { scoreId: j, scoreLockFlg: false }));
257
+
258
+ // 譜面詳細データの格納
259
+ const keyCtrlPtnDef = `${g_headerObj.keyLabels[j]}_0`;
260
+ storeBaseData(j, scoreConvert(g_rootObj, j, 0, ``, keyCtrlPtnDef, true), keyCtrlPtnDef);
261
+
262
+ // カスタムゲージの設定(譜面ヘッダー側)
263
+ resetCustomGauge(g_rootObj, { scoreId: j });
220
264
  if (j < loopCount) {
221
- // 分割時は各譜面ごとに上書き・補完、非分割時は初回のみ実行
222
- resetGaugeSetting(j);
265
+ // ゲージ設定:分割時は各譜面ごとに上書き・補完、非分割時は初回のみ実行
266
+ Object.keys(g_gaugeOptionObj.customFulls).forEach(gaugePtn =>
267
+ getGaugeSetting(g_rootObj, gaugePtn, g_headerObj.difLabels.length, { scoreId: j }));
223
268
  }
224
269
  }
225
270
  }
@@ -295,8 +340,10 @@ const initialControl = async () => {
295
340
  g_editorTmp[keyN].id = orgKeyNum * 100 + baseX + j;
296
341
  g_editorTmp[keyN].num = keyNum;
297
342
  g_editorTmp[keyN].chars = keyCtrlList.map(val => g_kCd[val[0]]);
298
- g_editorTmp[keyN].keys = keyCtrlList.map(val => g_kCdN[val[0]]).map(val => replaceStr(val, g_escapeStr.editorKey));
299
- g_editorTmp[keyN].alternativeKeys = keyCtrlList.map(val => val[1] === 0 ? `` : g_kCdN[val[1]]).map(val => replaceStr(val, g_escapeStr.editorKey));
343
+ g_editorTmp[keyN].keys = keyCtrlList.map(val => g_kCdN[val[0]])
344
+ .map(val => replaceStr(val, g_escapeStr.editorKey));
345
+ g_editorTmp[keyN].alternativeKeys = keyCtrlList.map(val => val[1] === 0 ? `` : g_kCdN[val[1]])
346
+ .map(val => replaceStr(val, g_escapeStr.editorKey));
300
347
  g_editorTmp[keyN].noteNames = charaList.map(val => `${val}_data`);
301
348
  g_editorTmp[keyN].freezeNames = charaList.map(val => {
302
349
  let frzName = replaceStr(val, g_escapeStr.frzName);
@@ -496,7 +543,6 @@ const dosConvert = (_dos = ``) => {
496
543
  const loadChartFile = async (_scoreId = g_stateObj.scoreId) => {
497
544
 
498
545
  const dosInput = document.getElementById(`dos`);
499
- const divRoot = document.getElementById(`divRoot`);
500
546
  const queryDos = getQueryParamVal(`dos`) !== null ?
501
547
  `dos/${getQueryParamVal('dos')}.txt` : encodeURI(document.getElementById(`externalDos`)?.value ?? ``);
502
548
 
@@ -541,39 +587,6 @@ const loadChartFile = async (_scoreId = g_stateObj.scoreId) => {
541
587
  }
542
588
  };
543
589
 
544
- /**
545
- * 譜面をファイルで分割している場合に初期色を追加取得
546
- * @param {string} _scoreId
547
- */
548
- const resetColorSetting = _scoreId => {
549
- // 初期矢印・フリーズアロー色の再定義
550
- if (g_stateObj.scoreLockFlg) {
551
- Object.assign(g_rootObj, copySetColor(g_rootObj, _scoreId));
552
-
553
- // 分割先のファイルで初期色が未定義の場合はデフォルト値を適用
554
- [``, `Shadow`].forEach(pattern =>
555
- [`set`, `frz`].forEach(arrow => {
556
- // frzShadowColorStrのみ、空で構成された初期配列があるためその条件を追加して除外条件とする
557
- if (!hasVal(g_rootObj[`${arrow}${pattern}Color${_scoreId + 1}`])
558
- && g_headerObj[`${arrow}${pattern}ColorStr`]?.flat()?.some(val => hasVal(val))) {
559
- g_rootObj[`${arrow}${pattern}Color`] = g_headerObj[`${arrow}${pattern}ColorStr`].join(`,`);
560
- }
561
- })
562
- );
563
- }
564
- Object.assign(g_headerObj, resetBaseColorList(g_headerObj, g_rootObj, { scoreId: _scoreId, scoreLockFlg: false }));
565
- };
566
-
567
- /**
568
- * 譜面をファイルで分割している場合にゲージ情報を追加取得
569
- * @param {string} _scoreId
570
- */
571
- const resetGaugeSetting = _scoreId => {
572
- // ライフ設定のカスタム部分再取得(譜面ヘッダー加味)
573
- Object.assign(g_gaugeOptionObj, resetCustomGauge(g_rootObj, { scoreId: _scoreId }));
574
- Object.keys(g_gaugeOptionObj.customFulls).forEach(gaugePtn => getGaugeSetting(g_rootObj, gaugePtn, g_headerObj.difLabels.length, { scoreId: _scoreId }));
575
- };
576
-
577
590
  /**
578
591
  * 譜面番号固定かつ譜面ファイル分割時に初期色情報を他譜面へコピー
579
592
  * @param {object} _baseObj
@@ -625,15 +638,6 @@ const getFullMusicUrl = (_musicUrl = ``) => {
625
638
  return `${musicPath}${musicFile}`;
626
639
  };
627
640
 
628
- /**
629
- * 譜面ファイル読込後処理(譜面詳細情報取得用)
630
- * @param {number} _scoreId
631
- */
632
- const getScoreDetailData = _scoreId => {
633
- const keyCtrlPtn = `${g_headerObj.keyLabels[_scoreId]}_0`;
634
- storeBaseData(_scoreId, scoreConvert(g_rootObj, _scoreId, 0, ``, keyCtrlPtn, true), keyCtrlPtn);
635
- };
636
-
637
641
  /**
638
642
  * 譜面詳細データの格納
639
643
  * @param {number} _scoreId
@@ -1248,14 +1252,14 @@ const headerConvert = _dosObj => {
1248
1252
 
1249
1253
  difs.forEach(dif => {
1250
1254
  const difDetails = dif.split(`,`);
1251
- const lifeData = (_type, _default) =>
1252
- difDetails[difpos[_type]] || g_presetObj.gauge?.[_type] || _default;
1255
+ const lifeData = (_type) =>
1256
+ difDetails[difpos[_type]] || g_presetObj.gauge?.[_type] || g_gaugeDefObj.Original[_type];
1253
1257
 
1254
1258
  // ライフ:ノルマ、回復量、ダメージ量、初期値の設定
1255
- obj.lifeBorders.push(lifeData(`Border`, `x`));
1256
- obj.lifeRecoverys.push(lifeData(`Recovery`, 6));
1257
- obj.lifeDamages.push(lifeData(`Damage`, 40));
1258
- obj.lifeInits.push(lifeData(`Init`, 25));
1259
+ obj.lifeBorders.push(lifeData(`Border`));
1260
+ obj.lifeRecoverys.push(lifeData(`Recovery`));
1261
+ obj.lifeDamages.push(lifeData(`Damage`));
1262
+ obj.lifeInits.push(lifeData(`Init`));
1259
1263
 
1260
1264
  // キー数
1261
1265
  const keyLabel = difDetails[difpos.Key] || g_keyObj.initKeyLabel;
@@ -1386,10 +1390,9 @@ const headerConvert = _dosObj => {
1386
1390
  }
1387
1391
 
1388
1392
  // ゲージ初期設定(最大ライフ反映)
1389
- g_gaugeOptionObj.defaultList.forEach(type => {
1390
- const pos = g_gaugeOptionObj[`dmg${toCapitalize(type)}`].findIndex(val => val === C_LFE_MAXLIFE);
1391
- g_gaugeOptionObj[`dmg${toCapitalize(type)}`][pos] = obj.maxLifeVal;
1392
- });
1393
+ Object.values(g_gaugeDefObj)
1394
+ .filter(def => def.Damage === C_LFE_MAXLIFE)
1395
+ .forEach(def => def.Damage = obj.maxLifeVal);
1393
1396
 
1394
1397
  // フリーズアローのデフォルト色セットの利用有無 (true: 使用, false: 矢印色を優先してセット)
1395
1398
  obj.defaultFrzColorUse = setBoolVal(_dosObj.defaultFrzColorUse ?? g_presetObj.frzColors, true);
@@ -1423,27 +1426,6 @@ const headerConvert = _dosObj => {
1423
1426
  'Type0': [!obj.defaultColorgrd[0], obj.defaultColorgrd[1]],
1424
1427
  };
1425
1428
 
1426
- // カスタムゲージ設定(共通設定ファイル)
1427
- addGaugeFulls(g_gaugeOptionObj.survival);
1428
- addGaugeFulls(g_gaugeOptionObj.border);
1429
-
1430
- if (g_presetObj.gaugeList !== undefined) {
1431
- Object.keys(g_presetObj.gaugeList).forEach(key => {
1432
- g_gaugeOptionObj.customDefault.push(key);
1433
- g_gaugeOptionObj.varCustomDefault.push(boolToSwitch(g_presetObj.gaugeList[key] === `V`));
1434
- });
1435
- g_gaugeOptionObj.custom = g_gaugeOptionObj.customDefault.concat();
1436
- g_gaugeOptionObj.varCustom = g_gaugeOptionObj.varCustomDefault.concat();
1437
- addGaugeFulls(g_gaugeOptionObj.customDefault);
1438
- }
1439
-
1440
- // カスタムゲージ設定、初期色設定(譜面ヘッダー)の譜面別設定
1441
- Object.assign(obj, resetBaseColorList(obj, _dosObj));
1442
- for (let j = 0; j < obj.difLabels.length; j++) {
1443
- Object.assign(g_gaugeOptionObj, resetCustomGauge(_dosObj, { scoreId: j }));
1444
- Object.assign(obj, resetBaseColorList(obj, _dosObj, { scoreId: j }));
1445
- }
1446
-
1447
1429
  // ダミー譜面の設定
1448
1430
  if (hasVal(_dosObj.dummyId)) {
1449
1431
  obj.dummyScoreNos = _dosObj.dummyId.split(`$`);
@@ -2088,45 +2070,40 @@ const setColorList = (_data, _colorInit, _colorInitLength,
2088
2070
  /**
2089
2071
  * 複合カスタムゲージの定義設定
2090
2072
  * |customGauge=_Original::F::Original,_Normal::V::Normal,Escape::V|
2073
+ *
2074
+ * g_gaugeSelObj[scoreId]に「名前→上書きプロパティ」を書き込む。
2075
+ * g_gaugeSelObj[scoreId].__order(選択順)と、名前ごとの上書き(Variable)を書き込む
2091
2076
  * @param {object} _dosObj
2092
2077
  * @param {string} [object.scoreId=0]
2093
- * @returns {object} ※Object.assign(obj, resetCustomGauge(...))の形で呼び出しが必要
2078
+ * @returns {void} g_gaugeSelObj[scoreId]を直接更新する
2094
2079
  */
2095
2080
  const resetCustomGauge = (_dosObj, { scoreId = 0 } = {}) => {
2096
2081
 
2097
- const obj = {};
2098
- const scoreIdHeader = setScoreIdHeader(scoreId, g_stateObj.scoreLockFlg, false);
2082
+ const scoreIdHeader = (scoreId === 0 && hasVal(_dosObj[`customGauge1`]))
2083
+ ? 1 : setScoreIdHeader(scoreId, g_stateObj.scoreLockFlg, false);
2099
2084
  const dosCustomGauge = _dosObj[`customGauge${scoreIdHeader}`];
2100
- if (hasVal(dosCustomGauge)) {
2101
- if (g_gaugeOptionObj.defaultPlusList.includes(dosCustomGauge)) {
2102
- obj[`custom${scoreId}`] = g_gaugeOptionObj[dosCustomGauge].concat();
2103
- obj[`varCustom${scoreId}`] = g_gaugeOptionObj[`var${toCapitalize(dosCustomGauge)}`].concat();
2104
- if (g_gaugeOptionObj.defaultList.includes(dosCustomGauge)) {
2105
- obj[`defaultGauge${scoreId}`] = dosCustomGauge;
2106
- obj[`typeCustom${scoreId}`] = g_gaugeOptionObj[`type${toCapitalize(dosCustomGauge)}`].concat();
2107
- }
2108
- } else {
2109
- const customGauges = dosCustomGauge.split(`,`);
2110
-
2111
- obj[`custom${scoreId}`] = [];
2112
- obj[`varCustom${scoreId}`] = [];
2113
-
2114
- for (let j = 0; j < customGauges.length; j++) {
2115
- const customGaugeSets = customGauges[j].split(`::`);
2116
- obj[`custom${scoreId}`][j] = customGaugeSets[0];
2117
- obj[`varCustom${scoreId}`][j] = boolToSwitch(customGaugeSets[1] === `V`);
2118
- if (hasVal(customGaugeSets[2])) {
2119
- g_lblNameObj[`u_${customGaugeSets[0]}`] = customGaugeSets[2];
2120
- }
2121
- }
2122
- if (scoreId === 0) {
2123
- obj.custom = obj.custom0.concat();
2124
- obj.varCustom = obj.varCustom0.concat();
2125
- }
2126
- addGaugeFulls(obj[`custom${scoreId}`]);
2085
+ if (!hasVal(dosCustomGauge)) return;
2086
+
2087
+ g_gaugeSelObj[scoreId] = structuredClone(g_gaugeSelObj.default ?? { __order: [] });
2088
+ if (g_gaugeOptionObj.defaultPlusList.includes(dosCustomGauge)) {
2089
+ // customDefault: cloneした時点でdefaultの並び・上書きがそのまま入っているので何もしない
2090
+ // survival/border: 選択順(名前)だけをsurvival/border配列に差し替える(値上書きはdefault由来のまま)
2091
+ if (dosCustomGauge !== `customDefault`) {
2092
+ g_gaugeSelObj[scoreId].__order = g_gaugeOptionObj[dosCustomGauge].concat();
2127
2093
  }
2094
+ return;
2128
2095
  }
2129
- return obj;
2096
+ // インライン指定(例: customGauge=Escape::V::エスケープ,Normal::F)
2097
+ g_gaugeSelObj[scoreId].__order = [];
2098
+ dosCustomGauge.split(`,`).forEach(gaugeSet => {
2099
+ const [name, variableFlag, dispName] = gaugeSet.split(`::`);
2100
+ g_gaugeSelObj[scoreId].__order.push(name);
2101
+ g_gaugeSelObj[scoreId][name] = { ...g_gaugeSelObj[scoreId][name], Variable: boolToSwitch(variableFlag === `V`) };
2102
+ if (hasVal(dispName)) {
2103
+ g_lblNameObj[`u_${name}`] = dispName;
2104
+ }
2105
+ });
2106
+ addGaugeFulls(g_gaugeSelObj[scoreId].__order);
2130
2107
  };
2131
2108
 
2132
2109
  /**
@@ -2138,39 +2115,16 @@ const resetCustomGauge = (_dosObj, { scoreId = 0 } = {}) => {
2138
2115
  */
2139
2116
  const getGaugeSetting = (_dosObj, _name, _difLength, { scoreId = 0 } = {}) => {
2140
2117
 
2141
- const obj = {
2142
- lifeBorders: [],
2143
- lifeRecoverys: [],
2144
- lifeDamages: [],
2145
- lifeInits: []
2146
- };
2147
- /** ゲージ設定再作成フラグ */
2148
- let gaugeCreateFlg = false;
2149
-
2150
2118
  /** ゲージ設定上書きフラグ */
2151
2119
  const gaugeUpdateFlg = g_stateObj.scoreLockFlg && scoreId > 0;
2152
-
2153
- /**
2154
- * ゲージ別個別配列への値格納
2155
- * この時点では各種ゲージ設定は文字列のまま。setGauge関数にて数式に変換される
2156
- * @param {number} _scoreId
2157
- * @param {string[]} _gaugeDetails
2158
- * @returns {boolean}
2159
- */
2160
- const setGaugeDetails = (_scoreId, _gaugeDetails) => {
2161
-
2162
- obj.lifeBorders[_scoreId] = _gaugeDetails[0] === `x` ? `x` : _gaugeDetails[0];
2163
- obj.lifeRecoverys[_scoreId] = _gaugeDetails[1];
2164
- obj.lifeDamages[_scoreId] = _gaugeDetails[2];
2165
- obj.lifeInits[_scoreId] = _gaugeDetails[3];
2166
-
2167
- if (gaugeUpdateFlg && hasVal(g_gaugeOptionObj[`gauge${_name}s`])) {
2168
- // ゲージ上書き時は_gaugeDetails(obj)の値を優先し、デフォルト値で穴埋めする
2169
- Object.keys(obj).forEach(key => g_gaugeOptionObj[`gauge${_name}s`][key] =
2170
- fillMissingArrayElem(g_gaugeOptionObj[`gauge${_name}s`][key] || [], obj[key]));
2171
- return false;
2172
- }
2173
- return true;
2120
+ const gauges = hasVal(_dosObj[`gauge${_name}`]) ? splitLF2(_dosObj[`gauge${_name}`]) : [];
2121
+
2122
+ const registerGaugeDetails = (_scoreId) => {
2123
+ const gaugeDetails = getGaugeDetailList(_scoreId);
2124
+ if (!hasVal(gaugeDetails)) return; // baseも譜面別ヘッダーもどちらも無ければ何もしない
2125
+ const [border, recovery, damage, init] = gaugeDetails;
2126
+ g_gaugeSelObj[_scoreId] ??= structuredClone(g_gaugeSelObj.default ?? { __order: [] });
2127
+ g_gaugeSelObj[_scoreId][_name] = { ...g_gaugeSelObj[_scoreId][_name], Border: border, Recovery: recovery, Damage: damage, Init: init };
2174
2128
  };
2175
2129
 
2176
2130
  /**
@@ -2179,47 +2133,70 @@ const getGaugeSetting = (_dosObj, _name, _difLength, { scoreId = 0 } = {}) => {
2179
2133
  * @param {number[]} _defaultGaugeList
2180
2134
  * @returns {number[]}
2181
2135
  */
2182
- const getGaugeDetailList = (_scoreId, _defaultGaugeList) => {
2183
- if (_scoreId > 0) {
2184
- const idHeader = setScoreIdHeader(_scoreId, g_stateObj.scoreLockFlg, false);
2136
+ const getGaugeDetailList = (_scoreId) => {
2137
+ const idHeader = (_scoreId === 0) ? 1 : setScoreIdHeader(_scoreId, g_stateObj.scoreLockFlg, false);
2138
+ if (hasVal(idHeader)) {
2185
2139
  const dosId = (idHeader || 0) - 1;
2186
2140
  const headerName = `gauge${_name}${idHeader}`;
2187
2141
  if (hasVal(_dosObj[headerName])) {
2188
- const gauges = splitLF2(_dosObj[headerName]);
2189
- return (gauges[dosId] || gauges[0])?.split(`,`);
2142
+ const detailGauges = splitLF2(_dosObj[headerName]);
2143
+ return (detailGauges[dosId] || detailGauges[0])?.split(`,`);
2190
2144
  }
2191
2145
  }
2192
- return _defaultGaugeList;
2146
+ return (gauges[_scoreId] || gauges[0])?.split(`,`);
2193
2147
  };
2194
2148
 
2195
- if (hasVal(_dosObj[`gauge${_name}`])) {
2196
-
2197
- const gauges = splitLF2(_dosObj[`gauge${_name}`]);
2198
- if (gaugeUpdateFlg) {
2199
- gaugeCreateFlg = setGaugeDetails(scoreId, (gauges[scoreId] || gauges[0])?.split(`,`));
2200
- } else {
2201
- for (let j = 0; j < _difLength; j++) {
2202
- gaugeCreateFlg = setGaugeDetails(j, getGaugeDetailList(j, (gauges[j] || gauges[0]).split(`,`)));
2203
- }
2149
+ if (gaugeUpdateFlg) {
2150
+ registerGaugeDetails(scoreId);
2151
+ } else {
2152
+ for (let j = 0; j < _difLength; j++) {
2153
+ registerGaugeDetails(j);
2204
2154
  }
2155
+ }
2156
+ };
2205
2157
 
2206
- } else if (g_presetObj.gaugeCustom?.[_name] !== undefined) {
2158
+ /**
2159
+ * 【参照用】g_gaugeOptionObjの旧プロパティを参照できるようにする関数
2160
+ * (initXXX/rcvXXX/dmgXXX/clearXXX、typeXXX/varXXXも参考として)に展開する。
2161
+ * - カスタムスクリプト側で既存ゲージの既定値を参照するための補助関数。本体からの呼び出しはない。
2162
+ */
2163
+ const restoreLegacyGaugeReference = () => {
2164
+ [`survival`, `border`].forEach(type => {
2165
+ const cap = toCapitalize(type);
2166
+ const names = g_gaugeOptionObj[type];
2167
+ g_gaugeOptionObj[`init${cap}`] = names.map(name => g_gaugeDefObj[name]?.Init);
2168
+ g_gaugeOptionObj[`rcv${cap}`] = names.map(name => g_gaugeDefObj[name]?.Recovery);
2169
+ g_gaugeOptionObj[`dmg${cap}`] = names.map(name => g_gaugeDefObj[name]?.Damage);
2170
+ g_gaugeOptionObj[`clear${cap}`] = names.map(name =>
2171
+ (g_gaugeDefObj[name]?.Border === `x` ? 0 : g_gaugeDefObj[name]?.Border));
2172
+ g_gaugeOptionObj[`var${cap}`] = names.map(name => g_gaugeDefObj[name]?.Variable);
2173
+ g_gaugeOptionObj[`type${cap}`] = names.map(name =>
2174
+ (g_gaugeDefObj[name]?.Border === `x` ? C_LFE_SURVIVAL : C_LFE_BORDER));
2175
+ });
2176
+ };
2207
2177
 
2208
- const gaugeDetails = [
2209
- g_presetObj.gaugeCustom[_name].Border, g_presetObj.gaugeCustom[_name].Recovery,
2210
- g_presetObj.gaugeCustom[_name].Damage, g_presetObj.gaugeCustom[_name].Init,
2211
- ];
2212
- if (gaugeUpdateFlg) {
2213
- gaugeCreateFlg = setGaugeDetails(scoreId, gaugeDetails);
2214
- } else {
2215
- for (let j = 0; j < _difLength; j++) {
2216
- gaugeCreateFlg = setGaugeDetails(j, getGaugeDetailList(j, gaugeDetails));
2217
- }
2218
- }
2219
- }
2220
- if (gaugeCreateFlg) {
2221
- g_gaugeOptionObj[`gauge${_name}s`] = obj;
2222
- }
2178
+ /**
2179
+ * 【反映用】カスタムスクリプトが旧形式で作った個別ゲージ設定
2180
+ * - g_gaugeOptionObj[`gauge${_name}s`] = { lifeBorders, lifeRecoverys, lifeDamages, lifeInits }
2181
+ * (それぞれscoreId順の配列)を、新プロパティ g_gaugeSelObj[scoreId][_name] へ変換して反映する
2182
+ * - 本体からの呼び出しは無いため、カスタムスクリプト側で呼び出しする想定
2183
+ * @param {string} _name ゲージ名
2184
+ */
2185
+ const applyLegacyGaugeOverride = (_name) => {
2186
+ const legacyObj = g_gaugeOptionObj[`gauge${_name}s`];
2187
+ if (!hasVal(legacyObj)) return;
2188
+ legacyObj.lifeRecoverys.forEach((recovery, scoreId) => {
2189
+ if (!hasVal(recovery)) return;
2190
+ g_gaugeSelObj[scoreId] ??= structuredClone(g_gaugeSelObj.default ?? { __order: [] });
2191
+ g_gaugeSelObj[scoreId][_name] = {
2192
+ ...g_gaugeSelObj[scoreId][_name],
2193
+ Border: legacyObj.lifeBorders[scoreId],
2194
+ Recovery: recovery,
2195
+ Damage: legacyObj.lifeDamages[scoreId],
2196
+ Init: legacyObj.lifeInits[scoreId],
2197
+ };
2198
+ });
2199
+ delete g_gaugeOptionObj[`gauge${_name}s`]; // 反映済みの旧データは残さない
2223
2200
  };
2224
2201
 
2225
2202
  /**
@@ -2692,7 +2669,8 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList?.split(`,`)
2692
2669
  _dosObj[`layerTrans${newKey}`] = _dosObj[`layerTrans${newKey}`]?.replaceAll(`,`, `___`);
2693
2670
  newKeyMultiParam(newKey, `layerTrans`, toSplitArrayStr, {
2694
2671
  loopFunc: (k, keyheader) => {
2695
- g_keyObj[`${keyheader}_${k + dfPtnNum}`][0] = g_keyObj[`${keyheader}_${k + dfPtnNum}`]?.[0]?.map(val => val.replaceAll(`___`, `,`));
2672
+ g_keyObj[`${keyheader}_${k + dfPtnNum}`][0] =
2673
+ g_keyObj[`${keyheader}_${k + dfPtnNum}`]?.[0]?.map(val => val.replaceAll(`___`, `,`));
2696
2674
  },
2697
2675
  });
2698
2676
  }