@yipe/dice 0.2.15 → 0.2.16
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 +59 -17
- package/dist/builder/index.cjs.map +1 -1
- package/dist/builder/index.d.cts +18 -4
- package/dist/builder/index.d.ts +18 -4
- package/dist/builder/index.js +59 -17
- package/dist/builder/index.js.map +1 -1
- package/package.json +1 -1
package/dist/builder/index.cjs
CHANGED
|
@@ -2671,6 +2671,9 @@ var RollBuilder = class _RollBuilder {
|
|
|
2671
2671
|
alwaysHits() {
|
|
2672
2672
|
return new AlwaysHitBuilder(this);
|
|
2673
2673
|
}
|
|
2674
|
+
alwaysCrits() {
|
|
2675
|
+
return new AlwaysCritBuilder(this);
|
|
2676
|
+
}
|
|
2674
2677
|
copy() {
|
|
2675
2678
|
return new this.constructor(this.getSubRollConfigs());
|
|
2676
2679
|
}
|
|
@@ -2962,7 +2965,7 @@ var MaxOfRollBuilder = class _MaxOfRollBuilder extends RollBuilder {
|
|
|
2962
2965
|
child: sumChild
|
|
2963
2966
|
};
|
|
2964
2967
|
}
|
|
2965
|
-
} catch
|
|
2968
|
+
} catch {
|
|
2966
2969
|
}
|
|
2967
2970
|
throw new Error(
|
|
2968
2971
|
`MaxOfRollBuilder.toAST(): Unsupported innerRoll configuration`
|
|
@@ -2997,6 +3000,9 @@ var AlwaysHitBuilder = class _AlwaysHitBuilder extends RollBuilder {
|
|
|
2997
3000
|
const newConfig = { critThreshold };
|
|
2998
3001
|
return new _AlwaysHitBuilder(this, newConfig);
|
|
2999
3002
|
}
|
|
3003
|
+
alwaysCrits() {
|
|
3004
|
+
return new AlwaysCritBuilder(this, void 0, true);
|
|
3005
|
+
}
|
|
3000
3006
|
// Legacy expressions
|
|
3001
3007
|
toExpression() {
|
|
3002
3008
|
const configs = this.getSubRollConfigs();
|
|
@@ -3014,23 +3020,28 @@ var AlwaysHitBuilder = class _AlwaysHitBuilder extends RollBuilder {
|
|
|
3014
3020
|
return new _AlwaysHitBuilder(baseCopy, newConfig);
|
|
3015
3021
|
}
|
|
3016
3022
|
};
|
|
3017
|
-
var AlwaysCritBuilder = class extends RollBuilder {
|
|
3018
|
-
constructor(baseRoll, attackConfig) {
|
|
3023
|
+
var AlwaysCritBuilder = class _AlwaysCritBuilder extends RollBuilder {
|
|
3024
|
+
constructor(baseRoll, attackConfig, fromAlwaysHit = false) {
|
|
3019
3025
|
super(baseRoll.getSubRollConfigs());
|
|
3020
3026
|
__publicField(this, "attackConfig");
|
|
3027
|
+
__publicField(this, "fromAlwaysHit");
|
|
3021
3028
|
if (attackConfig) {
|
|
3022
3029
|
this.attackConfig = { ...attackConfig };
|
|
3023
3030
|
} else {
|
|
3024
3031
|
this.attackConfig = { critThreshold: 20 };
|
|
3025
3032
|
}
|
|
3033
|
+
this.fromAlwaysHit = fromAlwaysHit || baseRoll instanceof AlwaysHitBuilder;
|
|
3034
|
+
}
|
|
3035
|
+
onHit(...args) {
|
|
3036
|
+
const damageRoll = RollBuilder.fromArgs(...args);
|
|
3037
|
+
return new AttackBuilder(this, damageRoll);
|
|
3026
3038
|
}
|
|
3027
3039
|
get critThreshold() {
|
|
3028
3040
|
return this.attackConfig.critThreshold;
|
|
3029
3041
|
}
|
|
3030
|
-
// TODO - move this to AC Builder… or if we create a DC builder that has critOn, throw an error?
|
|
3031
3042
|
critOn(critThreshold) {
|
|
3032
|
-
const newConfig = { critThreshold };
|
|
3033
|
-
return new
|
|
3043
|
+
const newConfig = { critThreshold, ac: this.attackConfig.ac };
|
|
3044
|
+
return new _AlwaysCritBuilder(this, newConfig, this.fromAlwaysHit);
|
|
3034
3045
|
}
|
|
3035
3046
|
// Legacy expressions
|
|
3036
3047
|
toExpression() {
|
|
@@ -3045,8 +3056,8 @@ var AlwaysCritBuilder = class extends RollBuilder {
|
|
|
3045
3056
|
copy() {
|
|
3046
3057
|
const baseCopy = new RollBuilder(this.getSubRollConfigs());
|
|
3047
3058
|
const critThreshold = this.critThreshold;
|
|
3048
|
-
const newConfig = { critThreshold };
|
|
3049
|
-
return new
|
|
3059
|
+
const newConfig = { critThreshold, ac: this.attackConfig.ac };
|
|
3060
|
+
return new _AlwaysCritBuilder(baseCopy, newConfig, this.fromAlwaysHit);
|
|
3050
3061
|
}
|
|
3051
3062
|
};
|
|
3052
3063
|
|
|
@@ -3582,9 +3593,9 @@ var AttackBuilder = class _AttackBuilder {
|
|
|
3582
3593
|
crit = this.hitEffect?.copy().doubleDice() ?? RollBuilder.fromArgs(0);
|
|
3583
3594
|
}
|
|
3584
3595
|
const critThreshold = this.check.critThreshold;
|
|
3585
|
-
if (critThreshold <
|
|
3596
|
+
if (critThreshold < 1 || critThreshold > 20) {
|
|
3586
3597
|
throw new Error(
|
|
3587
|
-
`Invalid crit threshold: ${critThreshold}. Must be between
|
|
3598
|
+
`Invalid crit threshold: ${critThreshold}. Must be between 1 and 20.`
|
|
3588
3599
|
);
|
|
3589
3600
|
}
|
|
3590
3601
|
if (critThreshold === 20) {
|
|
@@ -3601,13 +3612,34 @@ var AttackBuilder = class _AttackBuilder {
|
|
|
3601
3612
|
return `${checkPart} * ${effectPart}`;
|
|
3602
3613
|
}
|
|
3603
3614
|
resolveProbabilities(check, eps = 0) {
|
|
3604
|
-
if (check instanceof AlwaysCritBuilder) {
|
|
3605
|
-
return { pSuccess: 1, pHit: 0, pCrit: 1, pMiss: 0 };
|
|
3606
|
-
}
|
|
3607
3615
|
const rollType = check.rollType;
|
|
3608
3616
|
const rerollOne = check.baseReroll > 0;
|
|
3609
3617
|
const critThreshold = check.critThreshold;
|
|
3610
3618
|
const d202 = d20RollPMF(rollType, rerollOne);
|
|
3619
|
+
if (check instanceof AlwaysCritBuilder) {
|
|
3620
|
+
if (check.fromAlwaysHit) {
|
|
3621
|
+
return { pSuccess: 1, pHit: 0, pCrit: 1, pMiss: 0 };
|
|
3622
|
+
}
|
|
3623
|
+
const ac2 = check.attackConfig.ac ?? 0;
|
|
3624
|
+
const staticMod2 = this.check.modifier;
|
|
3625
|
+
const bonusDicePMFs2 = this.check.getBonusDicePMFs(this.check, eps);
|
|
3626
|
+
const bonusPMF2 = bonusDicePMFs2.length ? PMF.convolveMany(bonusDicePMFs2, eps) : PMF.delta(0, eps);
|
|
3627
|
+
let pcrit2 = 0;
|
|
3628
|
+
let pmiss2 = 0;
|
|
3629
|
+
for (const [r, rec] of d202) {
|
|
3630
|
+
const pr = typeof rec === "number" ? rec : rec.p;
|
|
3631
|
+
if (pr <= 0) continue;
|
|
3632
|
+
if (r === 1) {
|
|
3633
|
+
pmiss2 += pr;
|
|
3634
|
+
continue;
|
|
3635
|
+
}
|
|
3636
|
+
const need = ac2 - staticMod2 - r;
|
|
3637
|
+
const pBonusHit = bonusPMF2.tailProbGE(need);
|
|
3638
|
+
pcrit2 += pr * pBonusHit;
|
|
3639
|
+
pmiss2 += pr * (1 - pBonusHit);
|
|
3640
|
+
}
|
|
3641
|
+
return { pSuccess: pcrit2, pHit: 0, pCrit: pcrit2, pMiss: pmiss2 };
|
|
3642
|
+
}
|
|
3611
3643
|
if (check instanceof AlwaysHitBuilder) {
|
|
3612
3644
|
let pCrit = 0;
|
|
3613
3645
|
for (const [r, rec] of d202) {
|
|
@@ -3629,14 +3661,14 @@ var AttackBuilder = class _AttackBuilder {
|
|
|
3629
3661
|
for (const [r, rec] of d202) {
|
|
3630
3662
|
const pr = typeof rec === "number" ? rec : rec.p;
|
|
3631
3663
|
if (pr <= 0) continue;
|
|
3632
|
-
if (r >= critThreshold) {
|
|
3633
|
-
pcrit += pr;
|
|
3634
|
-
continue;
|
|
3635
|
-
}
|
|
3636
3664
|
if (r === 1) {
|
|
3637
3665
|
pmiss += pr;
|
|
3638
3666
|
continue;
|
|
3639
3667
|
}
|
|
3668
|
+
if (r >= critThreshold) {
|
|
3669
|
+
pcrit += pr;
|
|
3670
|
+
continue;
|
|
3671
|
+
}
|
|
3640
3672
|
const need = ac - staticMod - r;
|
|
3641
3673
|
const pBonusHit = bonusPMF.tailProbGE(need);
|
|
3642
3674
|
phit += pr * pBonusHit;
|
|
@@ -3717,6 +3749,16 @@ var ACBuilder = class _ACBuilder extends RollBuilder {
|
|
|
3717
3749
|
};
|
|
3718
3750
|
return new _ACBuilder(this, this.attackConfig.ac, newConfig);
|
|
3719
3751
|
}
|
|
3752
|
+
alwaysCrits() {
|
|
3753
|
+
return new AlwaysCritBuilder(
|
|
3754
|
+
this,
|
|
3755
|
+
{
|
|
3756
|
+
critThreshold: this.attackConfig.critThreshold,
|
|
3757
|
+
ac: this.attackConfig.ac
|
|
3758
|
+
},
|
|
3759
|
+
false
|
|
3760
|
+
);
|
|
3761
|
+
}
|
|
3720
3762
|
// Legacy expressions
|
|
3721
3763
|
toExpression() {
|
|
3722
3764
|
const configs = this.getSubRollConfigs();
|