@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.d.cts
CHANGED
|
@@ -139,6 +139,7 @@ declare class RollBuilder {
|
|
|
139
139
|
scaleDice(scale: number): RollBuilder;
|
|
140
140
|
doubleDice(): RollBuilder;
|
|
141
141
|
alwaysHits(): AlwaysHitBuilder;
|
|
142
|
+
alwaysCrits(): AlwaysCritBuilder;
|
|
142
143
|
copy(): RollBuilder;
|
|
143
144
|
d4: () => RollBuilder;
|
|
144
145
|
d6: () => RollBuilder;
|
|
@@ -198,18 +199,30 @@ declare class AlwaysHitBuilder extends RollBuilder {
|
|
|
198
199
|
onHit(count: number, sides: number, modifier: number): AttackBuilder;
|
|
199
200
|
get critThreshold(): number;
|
|
200
201
|
critOn(critThreshold: number): AlwaysHitBuilder;
|
|
202
|
+
alwaysCrits(): AlwaysCritBuilder;
|
|
201
203
|
toExpression(): string;
|
|
202
204
|
toPMF(): PMF;
|
|
203
205
|
copy(): AlwaysHitBuilder;
|
|
204
206
|
}
|
|
205
207
|
declare class AlwaysCritBuilder extends RollBuilder {
|
|
206
|
-
readonly attackConfig: CritConfig
|
|
207
|
-
|
|
208
|
+
readonly attackConfig: CritConfig & {
|
|
209
|
+
ac?: number;
|
|
210
|
+
};
|
|
211
|
+
readonly fromAlwaysHit: boolean;
|
|
212
|
+
constructor(baseRoll: RollBuilder, attackConfig?: CritConfig & {
|
|
213
|
+
ac?: number;
|
|
214
|
+
}, fromAlwaysHit?: boolean);
|
|
215
|
+
onHit(val: number): AttackBuilder;
|
|
216
|
+
onHit(val: RollBuilder): AttackBuilder;
|
|
217
|
+
onHit(count: number, die: RollBuilder): AttackBuilder;
|
|
218
|
+
onHit(count: number, sides: number): AttackBuilder;
|
|
219
|
+
onHit(count: number, die: RollBuilder, modifier: number): AttackBuilder;
|
|
220
|
+
onHit(count: number, sides: number, modifier: number): AttackBuilder;
|
|
208
221
|
get critThreshold(): number;
|
|
209
|
-
critOn(critThreshold: number):
|
|
222
|
+
critOn(critThreshold: number): AlwaysCritBuilder;
|
|
210
223
|
toExpression(): string;
|
|
211
224
|
toPMF(): PMF;
|
|
212
|
-
copy():
|
|
225
|
+
copy(): AlwaysCritBuilder;
|
|
213
226
|
}
|
|
214
227
|
|
|
215
228
|
type ActionEffect = RollBuilder;
|
|
@@ -260,6 +273,7 @@ declare class ACBuilder extends RollBuilder {
|
|
|
260
273
|
onHit(count: number, sides: number, modifier: number): AttackBuilder;
|
|
261
274
|
get critThreshold(): number;
|
|
262
275
|
critOn(threshold: number): ACBuilder;
|
|
276
|
+
alwaysCrits(): AlwaysCritBuilder;
|
|
263
277
|
toExpression(): string;
|
|
264
278
|
toPMF(eps?: number): PMF;
|
|
265
279
|
copy(): ACBuilder;
|
package/dist/builder/index.d.ts
CHANGED
|
@@ -139,6 +139,7 @@ declare class RollBuilder {
|
|
|
139
139
|
scaleDice(scale: number): RollBuilder;
|
|
140
140
|
doubleDice(): RollBuilder;
|
|
141
141
|
alwaysHits(): AlwaysHitBuilder;
|
|
142
|
+
alwaysCrits(): AlwaysCritBuilder;
|
|
142
143
|
copy(): RollBuilder;
|
|
143
144
|
d4: () => RollBuilder;
|
|
144
145
|
d6: () => RollBuilder;
|
|
@@ -198,18 +199,30 @@ declare class AlwaysHitBuilder extends RollBuilder {
|
|
|
198
199
|
onHit(count: number, sides: number, modifier: number): AttackBuilder;
|
|
199
200
|
get critThreshold(): number;
|
|
200
201
|
critOn(critThreshold: number): AlwaysHitBuilder;
|
|
202
|
+
alwaysCrits(): AlwaysCritBuilder;
|
|
201
203
|
toExpression(): string;
|
|
202
204
|
toPMF(): PMF;
|
|
203
205
|
copy(): AlwaysHitBuilder;
|
|
204
206
|
}
|
|
205
207
|
declare class AlwaysCritBuilder extends RollBuilder {
|
|
206
|
-
readonly attackConfig: CritConfig
|
|
207
|
-
|
|
208
|
+
readonly attackConfig: CritConfig & {
|
|
209
|
+
ac?: number;
|
|
210
|
+
};
|
|
211
|
+
readonly fromAlwaysHit: boolean;
|
|
212
|
+
constructor(baseRoll: RollBuilder, attackConfig?: CritConfig & {
|
|
213
|
+
ac?: number;
|
|
214
|
+
}, fromAlwaysHit?: boolean);
|
|
215
|
+
onHit(val: number): AttackBuilder;
|
|
216
|
+
onHit(val: RollBuilder): AttackBuilder;
|
|
217
|
+
onHit(count: number, die: RollBuilder): AttackBuilder;
|
|
218
|
+
onHit(count: number, sides: number): AttackBuilder;
|
|
219
|
+
onHit(count: number, die: RollBuilder, modifier: number): AttackBuilder;
|
|
220
|
+
onHit(count: number, sides: number, modifier: number): AttackBuilder;
|
|
208
221
|
get critThreshold(): number;
|
|
209
|
-
critOn(critThreshold: number):
|
|
222
|
+
critOn(critThreshold: number): AlwaysCritBuilder;
|
|
210
223
|
toExpression(): string;
|
|
211
224
|
toPMF(): PMF;
|
|
212
|
-
copy():
|
|
225
|
+
copy(): AlwaysCritBuilder;
|
|
213
226
|
}
|
|
214
227
|
|
|
215
228
|
type ActionEffect = RollBuilder;
|
|
@@ -260,6 +273,7 @@ declare class ACBuilder extends RollBuilder {
|
|
|
260
273
|
onHit(count: number, sides: number, modifier: number): AttackBuilder;
|
|
261
274
|
get critThreshold(): number;
|
|
262
275
|
critOn(threshold: number): ACBuilder;
|
|
276
|
+
alwaysCrits(): AlwaysCritBuilder;
|
|
263
277
|
toExpression(): string;
|
|
264
278
|
toPMF(eps?: number): PMF;
|
|
265
279
|
copy(): ACBuilder;
|
package/dist/builder/index.js
CHANGED
|
@@ -2669,6 +2669,9 @@ var RollBuilder = class _RollBuilder {
|
|
|
2669
2669
|
alwaysHits() {
|
|
2670
2670
|
return new AlwaysHitBuilder(this);
|
|
2671
2671
|
}
|
|
2672
|
+
alwaysCrits() {
|
|
2673
|
+
return new AlwaysCritBuilder(this);
|
|
2674
|
+
}
|
|
2672
2675
|
copy() {
|
|
2673
2676
|
return new this.constructor(this.getSubRollConfigs());
|
|
2674
2677
|
}
|
|
@@ -2960,7 +2963,7 @@ var MaxOfRollBuilder = class _MaxOfRollBuilder extends RollBuilder {
|
|
|
2960
2963
|
child: sumChild
|
|
2961
2964
|
};
|
|
2962
2965
|
}
|
|
2963
|
-
} catch
|
|
2966
|
+
} catch {
|
|
2964
2967
|
}
|
|
2965
2968
|
throw new Error(
|
|
2966
2969
|
`MaxOfRollBuilder.toAST(): Unsupported innerRoll configuration`
|
|
@@ -2995,6 +2998,9 @@ var AlwaysHitBuilder = class _AlwaysHitBuilder extends RollBuilder {
|
|
|
2995
2998
|
const newConfig = { critThreshold };
|
|
2996
2999
|
return new _AlwaysHitBuilder(this, newConfig);
|
|
2997
3000
|
}
|
|
3001
|
+
alwaysCrits() {
|
|
3002
|
+
return new AlwaysCritBuilder(this, void 0, true);
|
|
3003
|
+
}
|
|
2998
3004
|
// Legacy expressions
|
|
2999
3005
|
toExpression() {
|
|
3000
3006
|
const configs = this.getSubRollConfigs();
|
|
@@ -3012,23 +3018,28 @@ var AlwaysHitBuilder = class _AlwaysHitBuilder extends RollBuilder {
|
|
|
3012
3018
|
return new _AlwaysHitBuilder(baseCopy, newConfig);
|
|
3013
3019
|
}
|
|
3014
3020
|
};
|
|
3015
|
-
var AlwaysCritBuilder = class extends RollBuilder {
|
|
3016
|
-
constructor(baseRoll, attackConfig) {
|
|
3021
|
+
var AlwaysCritBuilder = class _AlwaysCritBuilder extends RollBuilder {
|
|
3022
|
+
constructor(baseRoll, attackConfig, fromAlwaysHit = false) {
|
|
3017
3023
|
super(baseRoll.getSubRollConfigs());
|
|
3018
3024
|
__publicField(this, "attackConfig");
|
|
3025
|
+
__publicField(this, "fromAlwaysHit");
|
|
3019
3026
|
if (attackConfig) {
|
|
3020
3027
|
this.attackConfig = { ...attackConfig };
|
|
3021
3028
|
} else {
|
|
3022
3029
|
this.attackConfig = { critThreshold: 20 };
|
|
3023
3030
|
}
|
|
3031
|
+
this.fromAlwaysHit = fromAlwaysHit || baseRoll instanceof AlwaysHitBuilder;
|
|
3032
|
+
}
|
|
3033
|
+
onHit(...args) {
|
|
3034
|
+
const damageRoll = RollBuilder.fromArgs(...args);
|
|
3035
|
+
return new AttackBuilder(this, damageRoll);
|
|
3024
3036
|
}
|
|
3025
3037
|
get critThreshold() {
|
|
3026
3038
|
return this.attackConfig.critThreshold;
|
|
3027
3039
|
}
|
|
3028
|
-
// TODO - move this to AC Builder… or if we create a DC builder that has critOn, throw an error?
|
|
3029
3040
|
critOn(critThreshold) {
|
|
3030
|
-
const newConfig = { critThreshold };
|
|
3031
|
-
return new
|
|
3041
|
+
const newConfig = { critThreshold, ac: this.attackConfig.ac };
|
|
3042
|
+
return new _AlwaysCritBuilder(this, newConfig, this.fromAlwaysHit);
|
|
3032
3043
|
}
|
|
3033
3044
|
// Legacy expressions
|
|
3034
3045
|
toExpression() {
|
|
@@ -3043,8 +3054,8 @@ var AlwaysCritBuilder = class extends RollBuilder {
|
|
|
3043
3054
|
copy() {
|
|
3044
3055
|
const baseCopy = new RollBuilder(this.getSubRollConfigs());
|
|
3045
3056
|
const critThreshold = this.critThreshold;
|
|
3046
|
-
const newConfig = { critThreshold };
|
|
3047
|
-
return new
|
|
3057
|
+
const newConfig = { critThreshold, ac: this.attackConfig.ac };
|
|
3058
|
+
return new _AlwaysCritBuilder(baseCopy, newConfig, this.fromAlwaysHit);
|
|
3048
3059
|
}
|
|
3049
3060
|
};
|
|
3050
3061
|
|
|
@@ -3580,9 +3591,9 @@ var AttackBuilder = class _AttackBuilder {
|
|
|
3580
3591
|
crit = this.hitEffect?.copy().doubleDice() ?? RollBuilder.fromArgs(0);
|
|
3581
3592
|
}
|
|
3582
3593
|
const critThreshold = this.check.critThreshold;
|
|
3583
|
-
if (critThreshold <
|
|
3594
|
+
if (critThreshold < 1 || critThreshold > 20) {
|
|
3584
3595
|
throw new Error(
|
|
3585
|
-
`Invalid crit threshold: ${critThreshold}. Must be between
|
|
3596
|
+
`Invalid crit threshold: ${critThreshold}. Must be between 1 and 20.`
|
|
3586
3597
|
);
|
|
3587
3598
|
}
|
|
3588
3599
|
if (critThreshold === 20) {
|
|
@@ -3599,13 +3610,34 @@ var AttackBuilder = class _AttackBuilder {
|
|
|
3599
3610
|
return `${checkPart} * ${effectPart}`;
|
|
3600
3611
|
}
|
|
3601
3612
|
resolveProbabilities(check, eps = 0) {
|
|
3602
|
-
if (check instanceof AlwaysCritBuilder) {
|
|
3603
|
-
return { pSuccess: 1, pHit: 0, pCrit: 1, pMiss: 0 };
|
|
3604
|
-
}
|
|
3605
3613
|
const rollType = check.rollType;
|
|
3606
3614
|
const rerollOne = check.baseReroll > 0;
|
|
3607
3615
|
const critThreshold = check.critThreshold;
|
|
3608
3616
|
const d202 = d20RollPMF(rollType, rerollOne);
|
|
3617
|
+
if (check instanceof AlwaysCritBuilder) {
|
|
3618
|
+
if (check.fromAlwaysHit) {
|
|
3619
|
+
return { pSuccess: 1, pHit: 0, pCrit: 1, pMiss: 0 };
|
|
3620
|
+
}
|
|
3621
|
+
const ac2 = check.attackConfig.ac ?? 0;
|
|
3622
|
+
const staticMod2 = this.check.modifier;
|
|
3623
|
+
const bonusDicePMFs2 = this.check.getBonusDicePMFs(this.check, eps);
|
|
3624
|
+
const bonusPMF2 = bonusDicePMFs2.length ? PMF.convolveMany(bonusDicePMFs2, eps) : PMF.delta(0, eps);
|
|
3625
|
+
let pcrit2 = 0;
|
|
3626
|
+
let pmiss2 = 0;
|
|
3627
|
+
for (const [r, rec] of d202) {
|
|
3628
|
+
const pr = typeof rec === "number" ? rec : rec.p;
|
|
3629
|
+
if (pr <= 0) continue;
|
|
3630
|
+
if (r === 1) {
|
|
3631
|
+
pmiss2 += pr;
|
|
3632
|
+
continue;
|
|
3633
|
+
}
|
|
3634
|
+
const need = ac2 - staticMod2 - r;
|
|
3635
|
+
const pBonusHit = bonusPMF2.tailProbGE(need);
|
|
3636
|
+
pcrit2 += pr * pBonusHit;
|
|
3637
|
+
pmiss2 += pr * (1 - pBonusHit);
|
|
3638
|
+
}
|
|
3639
|
+
return { pSuccess: pcrit2, pHit: 0, pCrit: pcrit2, pMiss: pmiss2 };
|
|
3640
|
+
}
|
|
3609
3641
|
if (check instanceof AlwaysHitBuilder) {
|
|
3610
3642
|
let pCrit = 0;
|
|
3611
3643
|
for (const [r, rec] of d202) {
|
|
@@ -3627,14 +3659,14 @@ var AttackBuilder = class _AttackBuilder {
|
|
|
3627
3659
|
for (const [r, rec] of d202) {
|
|
3628
3660
|
const pr = typeof rec === "number" ? rec : rec.p;
|
|
3629
3661
|
if (pr <= 0) continue;
|
|
3630
|
-
if (r >= critThreshold) {
|
|
3631
|
-
pcrit += pr;
|
|
3632
|
-
continue;
|
|
3633
|
-
}
|
|
3634
3662
|
if (r === 1) {
|
|
3635
3663
|
pmiss += pr;
|
|
3636
3664
|
continue;
|
|
3637
3665
|
}
|
|
3666
|
+
if (r >= critThreshold) {
|
|
3667
|
+
pcrit += pr;
|
|
3668
|
+
continue;
|
|
3669
|
+
}
|
|
3638
3670
|
const need = ac - staticMod - r;
|
|
3639
3671
|
const pBonusHit = bonusPMF.tailProbGE(need);
|
|
3640
3672
|
phit += pr * pBonusHit;
|
|
@@ -3715,6 +3747,16 @@ var ACBuilder = class _ACBuilder extends RollBuilder {
|
|
|
3715
3747
|
};
|
|
3716
3748
|
return new _ACBuilder(this, this.attackConfig.ac, newConfig);
|
|
3717
3749
|
}
|
|
3750
|
+
alwaysCrits() {
|
|
3751
|
+
return new AlwaysCritBuilder(
|
|
3752
|
+
this,
|
|
3753
|
+
{
|
|
3754
|
+
critThreshold: this.attackConfig.critThreshold,
|
|
3755
|
+
ac: this.attackConfig.ac
|
|
3756
|
+
},
|
|
3757
|
+
false
|
|
3758
|
+
);
|
|
3759
|
+
}
|
|
3718
3760
|
// Legacy expressions
|
|
3719
3761
|
toExpression() {
|
|
3720
3762
|
const configs = this.getSubRollConfigs();
|