@yipe/dice 0.2.12 → 0.2.15
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/dist/builder/index.cjs +106 -23
- package/dist/builder/index.cjs.map +1 -1
- package/dist/builder/index.d.cts +30 -6
- package/dist/builder/index.d.ts +30 -6
- package/dist/builder/index.js +105 -24
- package/dist/builder/index.js.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js.map +1 -1
- package/dist/{pmf-D1p2Re-J.d.cts → pmf-CYaEbY7m.d.cts} +4 -1
- package/dist/{pmf-D1p2Re-J.d.ts → pmf-CYaEbY7m.d.ts} +4 -1
- package/package.json +1 -1
package/dist/builder/index.cjs
CHANGED
|
@@ -2659,14 +2659,6 @@ var RollBuilder = class _RollBuilder {
|
|
|
2659
2659
|
const scaleInt = Math.floor(scale);
|
|
2660
2660
|
if (scaleInt !== scale) throw new Error("Scale must be an integer");
|
|
2661
2661
|
if (scaleInt <= 0) throw new Error("Scale must be > 0");
|
|
2662
|
-
if (scaleInt > 1) {
|
|
2663
|
-
const configs = this.getSubRollConfigs();
|
|
2664
|
-
if (configs.length === 1 && configs[0].keep && configs[0].count === 1) {
|
|
2665
|
-
const config = configs[0];
|
|
2666
|
-
const newConfig = { ...config, count: scaleInt };
|
|
2667
|
-
return new _RollBuilder([newConfig]);
|
|
2668
|
-
}
|
|
2669
|
-
}
|
|
2670
2662
|
const newConfigs = this.getSubRollConfigs().map((config) => {
|
|
2671
2663
|
if (!config.sides || config.sides <= 0) return config;
|
|
2672
2664
|
return { ...config, count: config.count * scaleInt };
|
|
@@ -2676,6 +2668,9 @@ var RollBuilder = class _RollBuilder {
|
|
|
2676
2668
|
doubleDice() {
|
|
2677
2669
|
return this.scaleDice(2);
|
|
2678
2670
|
}
|
|
2671
|
+
alwaysHits() {
|
|
2672
|
+
return new AlwaysHitBuilder(this);
|
|
2673
|
+
}
|
|
2679
2674
|
copy() {
|
|
2680
2675
|
return new this.constructor(this.getSubRollConfigs());
|
|
2681
2676
|
}
|
|
@@ -2939,17 +2934,6 @@ var MaxOfRollBuilder = class _MaxOfRollBuilder extends RollBuilder {
|
|
|
2939
2934
|
}
|
|
2940
2935
|
return `max${this.count}(?d?)`;
|
|
2941
2936
|
}
|
|
2942
|
-
findDieInAST(node) {
|
|
2943
|
-
if (node.type === "die") return node;
|
|
2944
|
-
if (node.child) return this.findDieInAST(node.child);
|
|
2945
|
-
if (node.children) {
|
|
2946
|
-
for (const child of node.children) {
|
|
2947
|
-
const result = this.findDieInAST(child.node || child);
|
|
2948
|
-
if (result) return result;
|
|
2949
|
-
}
|
|
2950
|
-
}
|
|
2951
|
-
return null;
|
|
2952
|
-
}
|
|
2953
2937
|
toAST() {
|
|
2954
2938
|
if (this.diceCount && this.diceSides) {
|
|
2955
2939
|
const sumChild = {
|
|
@@ -2991,6 +2975,80 @@ var MaxOfRollBuilder = class _MaxOfRollBuilder extends RollBuilder {
|
|
|
2991
2975
|
return new _MaxOfRollBuilder(this.innerRoll.copy(), this.count);
|
|
2992
2976
|
}
|
|
2993
2977
|
};
|
|
2978
|
+
var AlwaysHitBuilder = class _AlwaysHitBuilder extends RollBuilder {
|
|
2979
|
+
constructor(baseRoll, attackConfig) {
|
|
2980
|
+
super(baseRoll.getSubRollConfigs());
|
|
2981
|
+
__publicField(this, "attackConfig");
|
|
2982
|
+
if (attackConfig) {
|
|
2983
|
+
this.attackConfig = { ...attackConfig };
|
|
2984
|
+
} else {
|
|
2985
|
+
this.attackConfig = { critThreshold: 20 };
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2988
|
+
onHit(...args) {
|
|
2989
|
+
const damageRoll = RollBuilder.fromArgs(...args);
|
|
2990
|
+
return new AttackBuilder(this, damageRoll);
|
|
2991
|
+
}
|
|
2992
|
+
get critThreshold() {
|
|
2993
|
+
return this.attackConfig.critThreshold;
|
|
2994
|
+
}
|
|
2995
|
+
// TODO - move this to AC Builder… or if we create a DC builder that has critOn, throw an error?
|
|
2996
|
+
critOn(critThreshold) {
|
|
2997
|
+
const newConfig = { critThreshold };
|
|
2998
|
+
return new _AlwaysHitBuilder(this, newConfig);
|
|
2999
|
+
}
|
|
3000
|
+
// Legacy expressions
|
|
3001
|
+
toExpression() {
|
|
3002
|
+
const configs = this.getSubRollConfigs();
|
|
3003
|
+
return new RollBuilder(configs).toExpression();
|
|
3004
|
+
}
|
|
3005
|
+
toPMF() {
|
|
3006
|
+
const rollType = this.rollType;
|
|
3007
|
+
const rerollOne = this.baseReroll > 0;
|
|
3008
|
+
return d20RollPMF(rollType, rerollOne);
|
|
3009
|
+
}
|
|
3010
|
+
copy() {
|
|
3011
|
+
const baseCopy = new RollBuilder(this.getSubRollConfigs());
|
|
3012
|
+
const critThreshold = this.critThreshold;
|
|
3013
|
+
const newConfig = { critThreshold };
|
|
3014
|
+
return new _AlwaysHitBuilder(baseCopy, newConfig);
|
|
3015
|
+
}
|
|
3016
|
+
};
|
|
3017
|
+
var AlwaysCritBuilder = class extends RollBuilder {
|
|
3018
|
+
constructor(baseRoll, attackConfig) {
|
|
3019
|
+
super(baseRoll.getSubRollConfigs());
|
|
3020
|
+
__publicField(this, "attackConfig");
|
|
3021
|
+
if (attackConfig) {
|
|
3022
|
+
this.attackConfig = { ...attackConfig };
|
|
3023
|
+
} else {
|
|
3024
|
+
this.attackConfig = { critThreshold: 20 };
|
|
3025
|
+
}
|
|
3026
|
+
}
|
|
3027
|
+
get critThreshold() {
|
|
3028
|
+
return this.attackConfig.critThreshold;
|
|
3029
|
+
}
|
|
3030
|
+
// TODO - move this to AC Builder… or if we create a DC builder that has critOn, throw an error?
|
|
3031
|
+
critOn(critThreshold) {
|
|
3032
|
+
const newConfig = { critThreshold };
|
|
3033
|
+
return new AlwaysHitBuilder(this, newConfig);
|
|
3034
|
+
}
|
|
3035
|
+
// Legacy expressions
|
|
3036
|
+
toExpression() {
|
|
3037
|
+
const configs = this.getSubRollConfigs();
|
|
3038
|
+
return new RollBuilder(configs).toExpression();
|
|
3039
|
+
}
|
|
3040
|
+
toPMF() {
|
|
3041
|
+
const rollType = this.rollType;
|
|
3042
|
+
const rerollOne = this.baseReroll > 0;
|
|
3043
|
+
return d20RollPMF(rollType, rerollOne);
|
|
3044
|
+
}
|
|
3045
|
+
copy() {
|
|
3046
|
+
const baseCopy = new RollBuilder(this.getSubRollConfigs());
|
|
3047
|
+
const critThreshold = this.critThreshold;
|
|
3048
|
+
const newConfig = { critThreshold };
|
|
3049
|
+
return new AlwaysHitBuilder(baseCopy, newConfig);
|
|
3050
|
+
}
|
|
3051
|
+
};
|
|
2994
3052
|
|
|
2995
3053
|
// src/builder/factory.ts
|
|
2996
3054
|
var rollFn = (count, sidesOrDie, modifier) => {
|
|
@@ -3082,7 +3140,18 @@ function astFromRollConfigs(configs) {
|
|
|
3082
3140
|
const baseCount = Math.max(1, Math.floor(Math.abs(count || 1)));
|
|
3083
3141
|
const trials = Math.max(1, Math.floor(cfg.keep.total));
|
|
3084
3142
|
const k = Math.max(0, Math.floor(cfg.keep.count));
|
|
3085
|
-
if (
|
|
3143
|
+
if (k === 1 && cfg.keep.mode === "highest") {
|
|
3144
|
+
const perTrial = {
|
|
3145
|
+
type: "sum",
|
|
3146
|
+
count: baseCount,
|
|
3147
|
+
child: node
|
|
3148
|
+
};
|
|
3149
|
+
if (trials === 1) {
|
|
3150
|
+
node = perTrial;
|
|
3151
|
+
} else {
|
|
3152
|
+
node = { type: "maxOf", count: trials, child: perTrial };
|
|
3153
|
+
}
|
|
3154
|
+
} else if (trials === baseCount) {
|
|
3086
3155
|
const base = { type: "sum", count: trials, child: node };
|
|
3087
3156
|
node = {
|
|
3088
3157
|
type: "keep",
|
|
@@ -3098,8 +3167,6 @@ function astFromRollConfigs(configs) {
|
|
|
3098
3167
|
};
|
|
3099
3168
|
if (trials === 1) {
|
|
3100
3169
|
node = perTrial;
|
|
3101
|
-
} else if (k === 1 && cfg.keep.mode === "highest") {
|
|
3102
|
-
node = { type: "maxOf", count: trials, child: perTrial };
|
|
3103
3170
|
} else {
|
|
3104
3171
|
const trialPool = {
|
|
3105
3172
|
type: "sum",
|
|
@@ -3534,11 +3601,25 @@ var AttackBuilder = class _AttackBuilder {
|
|
|
3534
3601
|
return `${checkPart} * ${effectPart}`;
|
|
3535
3602
|
}
|
|
3536
3603
|
resolveProbabilities(check, eps = 0) {
|
|
3537
|
-
|
|
3604
|
+
if (check instanceof AlwaysCritBuilder) {
|
|
3605
|
+
return { pSuccess: 1, pHit: 0, pCrit: 1, pMiss: 0 };
|
|
3606
|
+
}
|
|
3538
3607
|
const rollType = check.rollType;
|
|
3539
3608
|
const rerollOne = check.baseReroll > 0;
|
|
3540
3609
|
const critThreshold = check.critThreshold;
|
|
3541
3610
|
const d202 = d20RollPMF(rollType, rerollOne);
|
|
3611
|
+
if (check instanceof AlwaysHitBuilder) {
|
|
3612
|
+
let pCrit = 0;
|
|
3613
|
+
for (const [r, rec] of d202) {
|
|
3614
|
+
const pr = typeof rec === "number" ? rec : rec.p;
|
|
3615
|
+
if (pr <= 0) continue;
|
|
3616
|
+
if (r >= critThreshold) pCrit += pr;
|
|
3617
|
+
}
|
|
3618
|
+
const pHit = 1 - pCrit;
|
|
3619
|
+
const pMiss = 0;
|
|
3620
|
+
return { pSuccess: 1, pHit, pCrit, pMiss };
|
|
3621
|
+
}
|
|
3622
|
+
const ac = check.attackConfig.ac;
|
|
3542
3623
|
const staticMod = this.check.modifier;
|
|
3543
3624
|
const bonusDicePMFs = this.check.getBonusDicePMFs(this.check, eps);
|
|
3544
3625
|
const bonusPMF = bonusDicePMFs.length ? PMF.convolveMany(bonusDicePMFs, eps) : PMF.delta(0, eps);
|
|
@@ -3824,6 +3905,8 @@ RollBuilder.prototype.dc = function(saveDC) {
|
|
|
3824
3905
|
};
|
|
3825
3906
|
|
|
3826
3907
|
exports.ACBuilder = ACBuilder;
|
|
3908
|
+
exports.AlwaysCritBuilder = AlwaysCritBuilder;
|
|
3909
|
+
exports.AlwaysHitBuilder = AlwaysHitBuilder;
|
|
3827
3910
|
exports.DCBuilder = DCBuilder;
|
|
3828
3911
|
exports.HalfRollBuilder = HalfRollBuilder;
|
|
3829
3912
|
exports.MaxOfRollBuilder = MaxOfRollBuilder;
|