@yipe/dice 0.2.13 → 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 +143 -27
- package/dist/builder/index.cjs.map +1 -1
- package/dist/builder/index.d.cts +44 -6
- package/dist/builder/index.d.ts +44 -6
- package/dist/builder/index.js +142 -28
- 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.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PMF, i as DiceQuery, L as LRUCache } from '../pmf-
|
|
1
|
+
import { P as PMF, C as CritConfig, i as DiceQuery, L as LRUCache } from '../pmf-CYaEbY7m.cjs';
|
|
2
2
|
|
|
3
3
|
type ExpressionNode = DieNode | ConstantNode | SumNode | AddNode | KeepNode | D20RollNode | HalfNode | MaxOfNode;
|
|
4
4
|
type DieNode = {
|
|
@@ -138,6 +138,8 @@ declare class RollBuilder {
|
|
|
138
138
|
addRoll(count?: number): RollBuilder;
|
|
139
139
|
scaleDice(scale: number): RollBuilder;
|
|
140
140
|
doubleDice(): RollBuilder;
|
|
141
|
+
alwaysHits(): AlwaysHitBuilder;
|
|
142
|
+
alwaysCrits(): AlwaysCritBuilder;
|
|
141
143
|
copy(): RollBuilder;
|
|
142
144
|
d4: () => RollBuilder;
|
|
143
145
|
d6: () => RollBuilder;
|
|
@@ -182,19 +184,54 @@ declare class MaxOfRollBuilder extends RollBuilder {
|
|
|
182
184
|
get lastConfig(): any;
|
|
183
185
|
getSubRollConfigs(): readonly RollConfig[];
|
|
184
186
|
toExpression(): string;
|
|
185
|
-
private findDieInAST;
|
|
186
187
|
toAST(): ExpressionNode;
|
|
187
188
|
toPMF(eps?: number): PMF;
|
|
188
189
|
copy(): MaxOfRollBuilder;
|
|
189
190
|
}
|
|
191
|
+
declare class AlwaysHitBuilder extends RollBuilder {
|
|
192
|
+
readonly attackConfig: CritConfig;
|
|
193
|
+
constructor(baseRoll: RollBuilder, attackConfig?: CritConfig);
|
|
194
|
+
onHit(val: number): AttackBuilder;
|
|
195
|
+
onHit(val: RollBuilder): AttackBuilder;
|
|
196
|
+
onHit(count: number, die: RollBuilder): AttackBuilder;
|
|
197
|
+
onHit(count: number, sides: number): AttackBuilder;
|
|
198
|
+
onHit(count: number, die: RollBuilder, modifier: number): AttackBuilder;
|
|
199
|
+
onHit(count: number, sides: number, modifier: number): AttackBuilder;
|
|
200
|
+
get critThreshold(): number;
|
|
201
|
+
critOn(critThreshold: number): AlwaysHitBuilder;
|
|
202
|
+
alwaysCrits(): AlwaysCritBuilder;
|
|
203
|
+
toExpression(): string;
|
|
204
|
+
toPMF(): PMF;
|
|
205
|
+
copy(): AlwaysHitBuilder;
|
|
206
|
+
}
|
|
207
|
+
declare class AlwaysCritBuilder extends RollBuilder {
|
|
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;
|
|
221
|
+
get critThreshold(): number;
|
|
222
|
+
critOn(critThreshold: number): AlwaysCritBuilder;
|
|
223
|
+
toExpression(): string;
|
|
224
|
+
toPMF(): PMF;
|
|
225
|
+
copy(): AlwaysCritBuilder;
|
|
226
|
+
}
|
|
190
227
|
|
|
191
228
|
type ActionEffect = RollBuilder;
|
|
192
229
|
declare class AttackBuilder implements CheckBuilder {
|
|
193
|
-
readonly check: ACBuilder;
|
|
230
|
+
readonly check: ACBuilder | AlwaysHitBuilder | AlwaysCritBuilder;
|
|
194
231
|
private readonly hitEffect?;
|
|
195
232
|
private readonly critEffect?;
|
|
196
233
|
private readonly missEffect?;
|
|
197
|
-
constructor(check: ACBuilder, hitEffect?: ActionEffect, critEffect?: ActionEffect | null, missEffect?: ActionEffect);
|
|
234
|
+
constructor(check: ACBuilder | AlwaysHitBuilder | AlwaysCritBuilder, hitEffect?: ActionEffect, critEffect?: ActionEffect | null, missEffect?: ActionEffect);
|
|
198
235
|
onCrit(val: number): AttackBuilder;
|
|
199
236
|
onCrit(val: RollBuilder): AttackBuilder;
|
|
200
237
|
onCrit(count: number, die: RollBuilder): AttackBuilder;
|
|
@@ -209,7 +246,7 @@ declare class AttackBuilder implements CheckBuilder {
|
|
|
209
246
|
onMiss(count: number, sides: number, modifier: number): AttackBuilder;
|
|
210
247
|
noCrit(): AttackBuilder;
|
|
211
248
|
toExpression(): string;
|
|
212
|
-
resolveProbabilities(check: ACBuilder, eps?: number): {
|
|
249
|
+
resolveProbabilities(check: ACBuilder | AlwaysHitBuilder | AlwaysCritBuilder, eps?: number): {
|
|
213
250
|
pSuccess: number;
|
|
214
251
|
pHit: number;
|
|
215
252
|
pCrit: number;
|
|
@@ -236,6 +273,7 @@ declare class ACBuilder extends RollBuilder {
|
|
|
236
273
|
onHit(count: number, sides: number, modifier: number): AttackBuilder;
|
|
237
274
|
get critThreshold(): number;
|
|
238
275
|
critOn(threshold: number): ACBuilder;
|
|
276
|
+
alwaysCrits(): AlwaysCritBuilder;
|
|
239
277
|
toExpression(): string;
|
|
240
278
|
toPMF(eps?: number): PMF;
|
|
241
279
|
copy(): ACBuilder;
|
|
@@ -299,4 +337,4 @@ declare const flat: (n: number) => RollBuilder;
|
|
|
299
337
|
declare const roll: RollFactory;
|
|
300
338
|
declare const builderPMFCache: LRUCache<string, PMF>;
|
|
301
339
|
|
|
302
|
-
export { ACBuilder, type AttackConfig, type AttackResolution, type CheckBuilder, DCBuilder, HalfRollBuilder, type KeepMode, MaxOfRollBuilder, type Resolution, RollBuilder, type RollConfig, type RollFactory, type RollType, SaveBuilder, type SaveOutcome, type SaveResolution, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
|
|
340
|
+
export { ACBuilder, AlwaysCritBuilder, AlwaysHitBuilder, type AttackConfig, type AttackResolution, type CheckBuilder, DCBuilder, HalfRollBuilder, type KeepMode, MaxOfRollBuilder, type Resolution, RollBuilder, type RollConfig, type RollFactory, type RollType, SaveBuilder, type SaveOutcome, type SaveResolution, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
|
package/dist/builder/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PMF, i as DiceQuery, L as LRUCache } from '../pmf-
|
|
1
|
+
import { P as PMF, C as CritConfig, i as DiceQuery, L as LRUCache } from '../pmf-CYaEbY7m.js';
|
|
2
2
|
|
|
3
3
|
type ExpressionNode = DieNode | ConstantNode | SumNode | AddNode | KeepNode | D20RollNode | HalfNode | MaxOfNode;
|
|
4
4
|
type DieNode = {
|
|
@@ -138,6 +138,8 @@ declare class RollBuilder {
|
|
|
138
138
|
addRoll(count?: number): RollBuilder;
|
|
139
139
|
scaleDice(scale: number): RollBuilder;
|
|
140
140
|
doubleDice(): RollBuilder;
|
|
141
|
+
alwaysHits(): AlwaysHitBuilder;
|
|
142
|
+
alwaysCrits(): AlwaysCritBuilder;
|
|
141
143
|
copy(): RollBuilder;
|
|
142
144
|
d4: () => RollBuilder;
|
|
143
145
|
d6: () => RollBuilder;
|
|
@@ -182,19 +184,54 @@ declare class MaxOfRollBuilder extends RollBuilder {
|
|
|
182
184
|
get lastConfig(): any;
|
|
183
185
|
getSubRollConfigs(): readonly RollConfig[];
|
|
184
186
|
toExpression(): string;
|
|
185
|
-
private findDieInAST;
|
|
186
187
|
toAST(): ExpressionNode;
|
|
187
188
|
toPMF(eps?: number): PMF;
|
|
188
189
|
copy(): MaxOfRollBuilder;
|
|
189
190
|
}
|
|
191
|
+
declare class AlwaysHitBuilder extends RollBuilder {
|
|
192
|
+
readonly attackConfig: CritConfig;
|
|
193
|
+
constructor(baseRoll: RollBuilder, attackConfig?: CritConfig);
|
|
194
|
+
onHit(val: number): AttackBuilder;
|
|
195
|
+
onHit(val: RollBuilder): AttackBuilder;
|
|
196
|
+
onHit(count: number, die: RollBuilder): AttackBuilder;
|
|
197
|
+
onHit(count: number, sides: number): AttackBuilder;
|
|
198
|
+
onHit(count: number, die: RollBuilder, modifier: number): AttackBuilder;
|
|
199
|
+
onHit(count: number, sides: number, modifier: number): AttackBuilder;
|
|
200
|
+
get critThreshold(): number;
|
|
201
|
+
critOn(critThreshold: number): AlwaysHitBuilder;
|
|
202
|
+
alwaysCrits(): AlwaysCritBuilder;
|
|
203
|
+
toExpression(): string;
|
|
204
|
+
toPMF(): PMF;
|
|
205
|
+
copy(): AlwaysHitBuilder;
|
|
206
|
+
}
|
|
207
|
+
declare class AlwaysCritBuilder extends RollBuilder {
|
|
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;
|
|
221
|
+
get critThreshold(): number;
|
|
222
|
+
critOn(critThreshold: number): AlwaysCritBuilder;
|
|
223
|
+
toExpression(): string;
|
|
224
|
+
toPMF(): PMF;
|
|
225
|
+
copy(): AlwaysCritBuilder;
|
|
226
|
+
}
|
|
190
227
|
|
|
191
228
|
type ActionEffect = RollBuilder;
|
|
192
229
|
declare class AttackBuilder implements CheckBuilder {
|
|
193
|
-
readonly check: ACBuilder;
|
|
230
|
+
readonly check: ACBuilder | AlwaysHitBuilder | AlwaysCritBuilder;
|
|
194
231
|
private readonly hitEffect?;
|
|
195
232
|
private readonly critEffect?;
|
|
196
233
|
private readonly missEffect?;
|
|
197
|
-
constructor(check: ACBuilder, hitEffect?: ActionEffect, critEffect?: ActionEffect | null, missEffect?: ActionEffect);
|
|
234
|
+
constructor(check: ACBuilder | AlwaysHitBuilder | AlwaysCritBuilder, hitEffect?: ActionEffect, critEffect?: ActionEffect | null, missEffect?: ActionEffect);
|
|
198
235
|
onCrit(val: number): AttackBuilder;
|
|
199
236
|
onCrit(val: RollBuilder): AttackBuilder;
|
|
200
237
|
onCrit(count: number, die: RollBuilder): AttackBuilder;
|
|
@@ -209,7 +246,7 @@ declare class AttackBuilder implements CheckBuilder {
|
|
|
209
246
|
onMiss(count: number, sides: number, modifier: number): AttackBuilder;
|
|
210
247
|
noCrit(): AttackBuilder;
|
|
211
248
|
toExpression(): string;
|
|
212
|
-
resolveProbabilities(check: ACBuilder, eps?: number): {
|
|
249
|
+
resolveProbabilities(check: ACBuilder | AlwaysHitBuilder | AlwaysCritBuilder, eps?: number): {
|
|
213
250
|
pSuccess: number;
|
|
214
251
|
pHit: number;
|
|
215
252
|
pCrit: number;
|
|
@@ -236,6 +273,7 @@ declare class ACBuilder extends RollBuilder {
|
|
|
236
273
|
onHit(count: number, sides: number, modifier: number): AttackBuilder;
|
|
237
274
|
get critThreshold(): number;
|
|
238
275
|
critOn(threshold: number): ACBuilder;
|
|
276
|
+
alwaysCrits(): AlwaysCritBuilder;
|
|
239
277
|
toExpression(): string;
|
|
240
278
|
toPMF(eps?: number): PMF;
|
|
241
279
|
copy(): ACBuilder;
|
|
@@ -299,4 +337,4 @@ declare const flat: (n: number) => RollBuilder;
|
|
|
299
337
|
declare const roll: RollFactory;
|
|
300
338
|
declare const builderPMFCache: LRUCache<string, PMF>;
|
|
301
339
|
|
|
302
|
-
export { ACBuilder, type AttackConfig, type AttackResolution, type CheckBuilder, DCBuilder, HalfRollBuilder, type KeepMode, MaxOfRollBuilder, type Resolution, RollBuilder, type RollConfig, type RollFactory, type RollType, SaveBuilder, type SaveOutcome, type SaveResolution, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
|
|
340
|
+
export { ACBuilder, AlwaysCritBuilder, AlwaysHitBuilder, type AttackConfig, type AttackResolution, type CheckBuilder, DCBuilder, HalfRollBuilder, type KeepMode, MaxOfRollBuilder, type Resolution, RollBuilder, type RollConfig, type RollFactory, type RollType, SaveBuilder, type SaveOutcome, type SaveResolution, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
|
package/dist/builder/index.js
CHANGED
|
@@ -2657,14 +2657,6 @@ var RollBuilder = class _RollBuilder {
|
|
|
2657
2657
|
const scaleInt = Math.floor(scale);
|
|
2658
2658
|
if (scaleInt !== scale) throw new Error("Scale must be an integer");
|
|
2659
2659
|
if (scaleInt <= 0) throw new Error("Scale must be > 0");
|
|
2660
|
-
if (scaleInt > 1) {
|
|
2661
|
-
const configs = this.getSubRollConfigs();
|
|
2662
|
-
if (configs.length === 1 && configs[0].keep && configs[0].count === 1) {
|
|
2663
|
-
const config = configs[0];
|
|
2664
|
-
const newConfig = { ...config, count: scaleInt };
|
|
2665
|
-
return new _RollBuilder([newConfig]);
|
|
2666
|
-
}
|
|
2667
|
-
}
|
|
2668
2660
|
const newConfigs = this.getSubRollConfigs().map((config) => {
|
|
2669
2661
|
if (!config.sides || config.sides <= 0) return config;
|
|
2670
2662
|
return { ...config, count: config.count * scaleInt };
|
|
@@ -2674,6 +2666,12 @@ var RollBuilder = class _RollBuilder {
|
|
|
2674
2666
|
doubleDice() {
|
|
2675
2667
|
return this.scaleDice(2);
|
|
2676
2668
|
}
|
|
2669
|
+
alwaysHits() {
|
|
2670
|
+
return new AlwaysHitBuilder(this);
|
|
2671
|
+
}
|
|
2672
|
+
alwaysCrits() {
|
|
2673
|
+
return new AlwaysCritBuilder(this);
|
|
2674
|
+
}
|
|
2677
2675
|
copy() {
|
|
2678
2676
|
return new this.constructor(this.getSubRollConfigs());
|
|
2679
2677
|
}
|
|
@@ -2937,17 +2935,6 @@ var MaxOfRollBuilder = class _MaxOfRollBuilder extends RollBuilder {
|
|
|
2937
2935
|
}
|
|
2938
2936
|
return `max${this.count}(?d?)`;
|
|
2939
2937
|
}
|
|
2940
|
-
findDieInAST(node) {
|
|
2941
|
-
if (node.type === "die") return node;
|
|
2942
|
-
if (node.child) return this.findDieInAST(node.child);
|
|
2943
|
-
if (node.children) {
|
|
2944
|
-
for (const child of node.children) {
|
|
2945
|
-
const result = this.findDieInAST(child.node || child);
|
|
2946
|
-
if (result) return result;
|
|
2947
|
-
}
|
|
2948
|
-
}
|
|
2949
|
-
return null;
|
|
2950
|
-
}
|
|
2951
2938
|
toAST() {
|
|
2952
2939
|
if (this.diceCount && this.diceSides) {
|
|
2953
2940
|
const sumChild = {
|
|
@@ -2976,7 +2963,7 @@ var MaxOfRollBuilder = class _MaxOfRollBuilder extends RollBuilder {
|
|
|
2976
2963
|
child: sumChild
|
|
2977
2964
|
};
|
|
2978
2965
|
}
|
|
2979
|
-
} catch
|
|
2966
|
+
} catch {
|
|
2980
2967
|
}
|
|
2981
2968
|
throw new Error(
|
|
2982
2969
|
`MaxOfRollBuilder.toAST(): Unsupported innerRoll configuration`
|
|
@@ -2989,6 +2976,88 @@ var MaxOfRollBuilder = class _MaxOfRollBuilder extends RollBuilder {
|
|
|
2989
2976
|
return new _MaxOfRollBuilder(this.innerRoll.copy(), this.count);
|
|
2990
2977
|
}
|
|
2991
2978
|
};
|
|
2979
|
+
var AlwaysHitBuilder = class _AlwaysHitBuilder extends RollBuilder {
|
|
2980
|
+
constructor(baseRoll, attackConfig) {
|
|
2981
|
+
super(baseRoll.getSubRollConfigs());
|
|
2982
|
+
__publicField(this, "attackConfig");
|
|
2983
|
+
if (attackConfig) {
|
|
2984
|
+
this.attackConfig = { ...attackConfig };
|
|
2985
|
+
} else {
|
|
2986
|
+
this.attackConfig = { critThreshold: 20 };
|
|
2987
|
+
}
|
|
2988
|
+
}
|
|
2989
|
+
onHit(...args) {
|
|
2990
|
+
const damageRoll = RollBuilder.fromArgs(...args);
|
|
2991
|
+
return new AttackBuilder(this, damageRoll);
|
|
2992
|
+
}
|
|
2993
|
+
get critThreshold() {
|
|
2994
|
+
return this.attackConfig.critThreshold;
|
|
2995
|
+
}
|
|
2996
|
+
// TODO - move this to AC Builder… or if we create a DC builder that has critOn, throw an error?
|
|
2997
|
+
critOn(critThreshold) {
|
|
2998
|
+
const newConfig = { critThreshold };
|
|
2999
|
+
return new _AlwaysHitBuilder(this, newConfig);
|
|
3000
|
+
}
|
|
3001
|
+
alwaysCrits() {
|
|
3002
|
+
return new AlwaysCritBuilder(this, void 0, true);
|
|
3003
|
+
}
|
|
3004
|
+
// Legacy expressions
|
|
3005
|
+
toExpression() {
|
|
3006
|
+
const configs = this.getSubRollConfigs();
|
|
3007
|
+
return new RollBuilder(configs).toExpression();
|
|
3008
|
+
}
|
|
3009
|
+
toPMF() {
|
|
3010
|
+
const rollType = this.rollType;
|
|
3011
|
+
const rerollOne = this.baseReroll > 0;
|
|
3012
|
+
return d20RollPMF(rollType, rerollOne);
|
|
3013
|
+
}
|
|
3014
|
+
copy() {
|
|
3015
|
+
const baseCopy = new RollBuilder(this.getSubRollConfigs());
|
|
3016
|
+
const critThreshold = this.critThreshold;
|
|
3017
|
+
const newConfig = { critThreshold };
|
|
3018
|
+
return new _AlwaysHitBuilder(baseCopy, newConfig);
|
|
3019
|
+
}
|
|
3020
|
+
};
|
|
3021
|
+
var AlwaysCritBuilder = class _AlwaysCritBuilder extends RollBuilder {
|
|
3022
|
+
constructor(baseRoll, attackConfig, fromAlwaysHit = false) {
|
|
3023
|
+
super(baseRoll.getSubRollConfigs());
|
|
3024
|
+
__publicField(this, "attackConfig");
|
|
3025
|
+
__publicField(this, "fromAlwaysHit");
|
|
3026
|
+
if (attackConfig) {
|
|
3027
|
+
this.attackConfig = { ...attackConfig };
|
|
3028
|
+
} else {
|
|
3029
|
+
this.attackConfig = { critThreshold: 20 };
|
|
3030
|
+
}
|
|
3031
|
+
this.fromAlwaysHit = fromAlwaysHit || baseRoll instanceof AlwaysHitBuilder;
|
|
3032
|
+
}
|
|
3033
|
+
onHit(...args) {
|
|
3034
|
+
const damageRoll = RollBuilder.fromArgs(...args);
|
|
3035
|
+
return new AttackBuilder(this, damageRoll);
|
|
3036
|
+
}
|
|
3037
|
+
get critThreshold() {
|
|
3038
|
+
return this.attackConfig.critThreshold;
|
|
3039
|
+
}
|
|
3040
|
+
critOn(critThreshold) {
|
|
3041
|
+
const newConfig = { critThreshold, ac: this.attackConfig.ac };
|
|
3042
|
+
return new _AlwaysCritBuilder(this, newConfig, this.fromAlwaysHit);
|
|
3043
|
+
}
|
|
3044
|
+
// Legacy expressions
|
|
3045
|
+
toExpression() {
|
|
3046
|
+
const configs = this.getSubRollConfigs();
|
|
3047
|
+
return new RollBuilder(configs).toExpression();
|
|
3048
|
+
}
|
|
3049
|
+
toPMF() {
|
|
3050
|
+
const rollType = this.rollType;
|
|
3051
|
+
const rerollOne = this.baseReroll > 0;
|
|
3052
|
+
return d20RollPMF(rollType, rerollOne);
|
|
3053
|
+
}
|
|
3054
|
+
copy() {
|
|
3055
|
+
const baseCopy = new RollBuilder(this.getSubRollConfigs());
|
|
3056
|
+
const critThreshold = this.critThreshold;
|
|
3057
|
+
const newConfig = { critThreshold, ac: this.attackConfig.ac };
|
|
3058
|
+
return new _AlwaysCritBuilder(baseCopy, newConfig, this.fromAlwaysHit);
|
|
3059
|
+
}
|
|
3060
|
+
};
|
|
2992
3061
|
|
|
2993
3062
|
// src/builder/factory.ts
|
|
2994
3063
|
var rollFn = (count, sidesOrDie, modifier) => {
|
|
@@ -3522,9 +3591,9 @@ var AttackBuilder = class _AttackBuilder {
|
|
|
3522
3591
|
crit = this.hitEffect?.copy().doubleDice() ?? RollBuilder.fromArgs(0);
|
|
3523
3592
|
}
|
|
3524
3593
|
const critThreshold = this.check.critThreshold;
|
|
3525
|
-
if (critThreshold <
|
|
3594
|
+
if (critThreshold < 1 || critThreshold > 20) {
|
|
3526
3595
|
throw new Error(
|
|
3527
|
-
`Invalid crit threshold: ${critThreshold}. Must be between
|
|
3596
|
+
`Invalid crit threshold: ${critThreshold}. Must be between 1 and 20.`
|
|
3528
3597
|
);
|
|
3529
3598
|
}
|
|
3530
3599
|
if (critThreshold === 20) {
|
|
@@ -3541,11 +3610,46 @@ var AttackBuilder = class _AttackBuilder {
|
|
|
3541
3610
|
return `${checkPart} * ${effectPart}`;
|
|
3542
3611
|
}
|
|
3543
3612
|
resolveProbabilities(check, eps = 0) {
|
|
3544
|
-
const ac = check.attackConfig.ac;
|
|
3545
3613
|
const rollType = check.rollType;
|
|
3546
3614
|
const rerollOne = check.baseReroll > 0;
|
|
3547
3615
|
const critThreshold = check.critThreshold;
|
|
3548
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
|
+
}
|
|
3641
|
+
if (check instanceof AlwaysHitBuilder) {
|
|
3642
|
+
let pCrit = 0;
|
|
3643
|
+
for (const [r, rec] of d202) {
|
|
3644
|
+
const pr = typeof rec === "number" ? rec : rec.p;
|
|
3645
|
+
if (pr <= 0) continue;
|
|
3646
|
+
if (r >= critThreshold) pCrit += pr;
|
|
3647
|
+
}
|
|
3648
|
+
const pHit = 1 - pCrit;
|
|
3649
|
+
const pMiss = 0;
|
|
3650
|
+
return { pSuccess: 1, pHit, pCrit, pMiss };
|
|
3651
|
+
}
|
|
3652
|
+
const ac = check.attackConfig.ac;
|
|
3549
3653
|
const staticMod = this.check.modifier;
|
|
3550
3654
|
const bonusDicePMFs = this.check.getBonusDicePMFs(this.check, eps);
|
|
3551
3655
|
const bonusPMF = bonusDicePMFs.length ? PMF.convolveMany(bonusDicePMFs, eps) : PMF.delta(0, eps);
|
|
@@ -3555,14 +3659,14 @@ var AttackBuilder = class _AttackBuilder {
|
|
|
3555
3659
|
for (const [r, rec] of d202) {
|
|
3556
3660
|
const pr = typeof rec === "number" ? rec : rec.p;
|
|
3557
3661
|
if (pr <= 0) continue;
|
|
3558
|
-
if (r >= critThreshold) {
|
|
3559
|
-
pcrit += pr;
|
|
3560
|
-
continue;
|
|
3561
|
-
}
|
|
3562
3662
|
if (r === 1) {
|
|
3563
3663
|
pmiss += pr;
|
|
3564
3664
|
continue;
|
|
3565
3665
|
}
|
|
3666
|
+
if (r >= critThreshold) {
|
|
3667
|
+
pcrit += pr;
|
|
3668
|
+
continue;
|
|
3669
|
+
}
|
|
3566
3670
|
const need = ac - staticMod - r;
|
|
3567
3671
|
const pBonusHit = bonusPMF.tailProbGE(need);
|
|
3568
3672
|
phit += pr * pBonusHit;
|
|
@@ -3643,6 +3747,16 @@ var ACBuilder = class _ACBuilder extends RollBuilder {
|
|
|
3643
3747
|
};
|
|
3644
3748
|
return new _ACBuilder(this, this.attackConfig.ac, newConfig);
|
|
3645
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
|
+
}
|
|
3646
3760
|
// Legacy expressions
|
|
3647
3761
|
toExpression() {
|
|
3648
3762
|
const configs = this.getSubRollConfigs();
|
|
@@ -3830,6 +3944,6 @@ RollBuilder.prototype.dc = function(saveDC) {
|
|
|
3830
3944
|
return new DCBuilder(this).dc(saveDC);
|
|
3831
3945
|
};
|
|
3832
3946
|
|
|
3833
|
-
export { ACBuilder, DCBuilder, HalfRollBuilder, MaxOfRollBuilder, RollBuilder, SaveBuilder, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
|
|
3947
|
+
export { ACBuilder, AlwaysCritBuilder, AlwaysHitBuilder, DCBuilder, HalfRollBuilder, MaxOfRollBuilder, RollBuilder, SaveBuilder, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
|
|
3834
3948
|
//# sourceMappingURL=index.js.map
|
|
3835
3949
|
//# sourceMappingURL=index.js.map
|