ダメージ軽減と確率計算 (26.1.2)
| 数学的性質 | 値 |
|---|---|
| 合計ダメージ単位 | $\text{amount} \times 100$ |
| 基本整数除算 | $\lfloor (\text{amount} \times 100) / \text{percent} \rfloor$ |
| 剰余(余り) | $(\text{amount} \times 100) \pmod{\text{percent}}$ |
| 確率判定 | random.nextInt(percent) < remainder |
| 整数範囲 | $\ge 0$(全体初期値: 200、上書き: 0 = 継承) |
| ゼロダメージ保証 | 無限モードまたは確率的吸収成功時に確実に$0$ダメージ |
🛡️ なぜダメージインターセプトなのか(100%ワールドセーブ安全)?
Durability Multiplier is engineered to never mutate item NBT or DataComponents stored in world save files.
なぜ DataComponents.MAX_DAMAGE を直接変更しないのか?
- ワールド汚染ゼロ: 最大耐久度を書き換えると、変更された値がインベントリやチェスト、セーブデータに永続化されます。Modを削除したりルールを変更した際に、アイテムが壊れたまま残ってしまいます。
- 即時反映:
/gamerule ig:dm_percent_globalを変更すると、アイテムの再生成やインベントリ走査を必要とせず、ワールド内の全アイテムに即座に反映されます。 - 金床・修繕のバランス維持: 金床の修理コストや修繕(Mending)によるXP吸収はバニラの標準耐久度に基づいて計算され、整数のオーバーフローや修理ペナルティは発生しません。
代わりに、Modは実行時にItemStackDurabilityMixinを通じてダメージイベントを動的に傍受し、確率的ダメージスケーリング(バニラの**耐久力(Unbreaking)**エンチャントと全く同じ方式)を適用します。
📐 正確なスケーリングアルゴリズム
アイテムが使用された際(ブロック破壊や攻撃で通常1のoriginalAmountダメージが発生):
java
public static int calculateScaledDamage(int originalAmount, int percent, RandomSource random) {
if (originalAmount <= 0)
return 0;
if (percent <= 0 || percent == 100)
return originalAmount;
int totalDamageUnits = originalAmount * 100;
int baseDamage = totalDamageUnits / percent;
int remainder = totalDamageUnits % percent;
if (remainder > 0 && random.nextInt(percent) < remainder) {
baseDamage++;
}
return baseDamage;
}🎲 確率分布マトリクス
1耐久値消費イベントの場合 (originalAmount = 1)
| パーセント | 実効倍率 | 基本除算 (100 / P) | 余り (100 % P) | 1回ごとの被ダメ確率 | 1回ごとの期待ダメージ | 相対耐久度 |
|---|---|---|---|---|---|---|
| 25% | $0.25\times$ | 4 | 0 | $100%$ (4ダメージ) | $4.00$ | $0.25\times$ (消耗4倍) |
| 50% | $0.50\times$ | 2 | 0 | $100%$ (2ダメージ) | $2.00$ | $0.50\times$ (消耗2倍) |
| 75% | $0.75\times$ | 1 | 25 | $100%$ (1) + $33.3%$ (+1) | $1.33$ | $0.75\times$ (消耗1.33倍) |
| 100% | $1.00\times$ (バニラ) | 1 | 0 | $100%$ (1ダメージ) | $1.00$ | $1.00\times$ (標準) |
| 150% | $1.50\times$ | 0 | 100 | $\frac{100}{150} \approx 66.67%$ (1ダメージ) | $0.67$ | $1.50\times$ |
| 200% | $2.00\times$ | 0 | 100 | $\frac{100}{200} = 50.00%$ (1ダメージ) | $0.50$ | $2.00\times$ |
| 300% | $3.00\times$ | 0 | 100 | $\frac{100}{300} \approx 33.33%$ (1ダメージ) | $0.33$ | $3.00\times$ |
| 500% | $5.00\times$ | 0 | 100 | $\frac{100}{500} = 20.00%$ (1ダメージ) | $0.20$ | $5.00\times$ |
| 1000% | $10.00\times$ | 0 | 100 | $\frac{100}{1000} = 10.00%$ (1ダメージ) | $0.10$ | $10.00\times$ |
📈 独立した乱数ロールと大数の法則
ダメージ吸収は攻撃や採掘ごとに独立して判定されるため(バニラの耐久力と同様):
- **500% (5倍)**時、各ヒットは独立して$20%$の確率で1ダメージ、$80%$の確率で0ダメージとなります。
- 短時間の試行では、2回でダメージを受けることもあれば8回受長持ちすることもあります。
- ツールの全寿命(例:ダイヤの斧の1,561回)を通してみると、破壊可能ブロック総数は数学的に**$\approx 7,805$回**(きっかり5倍)に収束します。
アイテムのバニラ耐久度を$N$、設定パーセントを$P$($P \ge 100$)とすると、破損までの使用回数$U$は以下の期待値を持つ負の二項分布に従います:
$$\mathbb{E}[U] = N \times \frac{P}{100}$$
何千回もの使用を通じて、大数の法則により総耐久度は正確にバニラ耐久度の$\frac{P}{100}$倍へと収束します。
