mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-12 03:31:07 +01:00
parent
3176438293
commit
ad9e0aa558
9 changed files with 153 additions and 40 deletions
|
|
@ -407,7 +407,11 @@
|
||||||
"rerollDice": "Reroll Dice"
|
"rerollDice": "Reroll Dice"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"CLASS": {
|
||||||
|
"Feature": {
|
||||||
|
"rallyDice": "Bardic Rally Dice"
|
||||||
|
}
|
||||||
|
},
|
||||||
"CONFIG": {
|
"CONFIG": {
|
||||||
"ActionType": {
|
"ActionType": {
|
||||||
"passive": "Passive",
|
"passive": "Passive",
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
if (this.roll) {
|
if (this.roll) {
|
||||||
context.roll = this.roll;
|
context.roll = this.roll;
|
||||||
context.rollType = this.roll?.constructor.name;
|
context.rollType = this.roll?.constructor.name;
|
||||||
|
context.rallyDie = this.roll.rallyChoices;
|
||||||
context.experiences = Object.keys(this.config.data.experiences).map(id => ({
|
context.experiences = Object.keys(this.config.data.experiences).map(id => ({
|
||||||
id,
|
id,
|
||||||
...this.config.data.experiences[id]
|
...this.config.data.experiences[id]
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
physical: bonusField('DAGGERHEART.GENERAL.Damage.physicalDamage'),
|
physical: bonusField('DAGGERHEART.GENERAL.Damage.physicalDamage'),
|
||||||
magical: bonusField('DAGGERHEART.GENERAL.Damage.magicalDamage'),
|
magical: bonusField('DAGGERHEART.GENERAL.Damage.magicalDamage'),
|
||||||
primaryWeapon: bonusField('DAGGERHEART.GENERAL.Damage.primaryWeapon'),
|
primaryWeapon: bonusField('DAGGERHEART.GENERAL.Damage.primaryWeapon'),
|
||||||
secondaryWeapon: bonusField('DAGGERHEART.GENERAL.Damage.primaryWeapon')
|
secondaryWeapon: bonusField('DAGGERHEART.GENERAL.Damage.secondaryWeapon')
|
||||||
}),
|
}),
|
||||||
healing: bonusField('DAGGERHEART.GENERAL.Healing.healingAmount'),
|
healing: bonusField('DAGGERHEART.GENERAL.Healing.healingAmount'),
|
||||||
range: new fields.SchemaField({
|
range: new fields.SchemaField({
|
||||||
|
|
@ -121,7 +121,13 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
initial: 0,
|
initial: 0,
|
||||||
label: 'DAGGERHEART.GENERAL.Range.other'
|
label: 'DAGGERHEART.GENERAL.Range.other'
|
||||||
})
|
})
|
||||||
})
|
}),
|
||||||
|
rally: new fields.ArrayField(
|
||||||
|
new fields.StringField(),
|
||||||
|
{
|
||||||
|
label: 'DAGGERHEART.CLASS.Feature.rallyDice'
|
||||||
|
}
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
companion: new ForeignDocumentUUIDField({ type: 'Actor', nullable: true, initial: null }),
|
companion: new ForeignDocumentUUIDField({ type: 'Actor', nullable: true, initial: null }),
|
||||||
rules: new fields.SchemaField({
|
rules: new fields.SchemaField({
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,11 @@ const stressDamageReductionRule = localizationPath =>
|
||||||
|
|
||||||
const bonusField = label =>
|
const bonusField = label =>
|
||||||
new fields.SchemaField({
|
new fields.SchemaField({
|
||||||
bonus: new fields.NumberField({ integer: true, initial: 0, label }),
|
bonus: new fields.NumberField({ integer: true, initial: 0, label: `${game.i18n.localize(label)} Value` }),
|
||||||
dice: new fields.ArrayField(new fields.StringField())
|
dice: new fields.ArrayField(
|
||||||
|
new fields.StringField(),
|
||||||
|
{ label: `${game.i18n.localize(label)} Dice` }
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
export { attributeField, resourceField, stressDamageReductionRule, bonusField };
|
export { attributeField, resourceField, stressDamageReductionRule, bonusField };
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,13 @@ export default class D20Roll extends DHRoll {
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasAdvantage() {
|
get hasAdvantage() {
|
||||||
return this.options.roll.advantage === this.constructor.ADV_MODE.ADVANTAGE;
|
const adv = this.options.roll.advantage.type ?? this.options.roll.advantage;
|
||||||
|
return adv === this.constructor.ADV_MODE.ADVANTAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasDisadvantage() {
|
get hasDisadvantage() {
|
||||||
return this.options.roll.advantage === this.constructor.ADV_MODE.DISADVANTAGE;
|
const adv = this.options.roll.advantage.type ?? this.options.roll.advantage;
|
||||||
|
return adv === this.constructor.ADV_MODE.DISADVANTAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static applyKeybindings(config) {
|
static applyKeybindings(config) {
|
||||||
|
|
@ -91,7 +93,7 @@ export default class D20Roll extends DHRoll {
|
||||||
configureModifiers() {
|
configureModifiers() {
|
||||||
this.applyAdvantage();
|
this.applyAdvantage();
|
||||||
|
|
||||||
this.baseTerms = foundry.utils.deepClone(this.terms);
|
this.baseTerms = foundry.utils.deepClone(this.dice);
|
||||||
|
|
||||||
this.options.roll.modifiers = this.applyBaseBonus();
|
this.options.roll.modifiers = this.applyBaseBonus();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,12 @@ import { setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs';
|
||||||
|
|
||||||
export default class DualityRoll extends D20Roll {
|
export default class DualityRoll extends D20Roll {
|
||||||
_advantageFaces = 6;
|
_advantageFaces = 6;
|
||||||
|
_advantageNumber = 1;
|
||||||
|
_rallyIndex;
|
||||||
|
|
||||||
constructor(formula, data = {}, options = {}) {
|
constructor(formula, data = {}, options = {}) {
|
||||||
super(formula, data, options);
|
super(formula, data, options);
|
||||||
|
this.rallyChoices = this.setRallyChoices();
|
||||||
}
|
}
|
||||||
|
|
||||||
static messageType = 'dualityRoll';
|
static messageType = 'dualityRoll';
|
||||||
|
|
@ -51,6 +54,35 @@ export default class DualityRoll extends D20Roll {
|
||||||
this._advantageFaces = this.getFaces(faces);
|
this._advantageFaces = this.getFaces(faces);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get advantageNumber() {
|
||||||
|
return this._advantageNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
set advantageNumber(value) {
|
||||||
|
this._advantageNumber = Number(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
setRallyChoices() {
|
||||||
|
return this.data?.parent?.effects.reduce((a,c) => {
|
||||||
|
const change = c.changes.find(ch => ch.key === 'system.bonuses.rally');
|
||||||
|
if(change) a.push({ value: c.id, label: change.value });
|
||||||
|
return a;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
get dRally() {
|
||||||
|
if(!this.rallyFaces) return null;
|
||||||
|
if(this.hasDisadvantage || this.hasAdvantage)
|
||||||
|
return this.dice[3];
|
||||||
|
else
|
||||||
|
return this.dice[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
get rallyFaces() {
|
||||||
|
const rallyChoice = this.rallyChoices?.find(r => r.value === this._rallyIndex)?.label;
|
||||||
|
return rallyChoice ? this.getFaces(rallyChoice) : null;
|
||||||
|
}
|
||||||
|
|
||||||
get isCritical() {
|
get isCritical() {
|
||||||
if (!this.dHope._evaluated || !this.dFear._evaluated) return;
|
if (!this.dHope._evaluated || !this.dFear._evaluated) return;
|
||||||
return this.dHope.total === this.dFear.total;
|
return this.dHope.total === this.dFear.total;
|
||||||
|
|
@ -66,10 +98,6 @@ export default class DualityRoll extends D20Roll {
|
||||||
return this.dHope.total < this.dFear.total;
|
return this.dHope.total < this.dFear.total;
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasBarRally() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
get totalLabel() {
|
get totalLabel() {
|
||||||
const label = this.withHope
|
const label = this.withHope
|
||||||
? 'DAGGERHEART.GENERAL.hope'
|
? 'DAGGERHEART.GENERAL.hope'
|
||||||
|
|
@ -98,24 +126,20 @@ export default class DualityRoll extends D20Roll {
|
||||||
}
|
}
|
||||||
|
|
||||||
applyAdvantage() {
|
applyAdvantage() {
|
||||||
const dieFaces = this.advantageFaces,
|
if (this.hasAdvantage || this.hasDisadvantage) {
|
||||||
bardRallyFaces = this.hasBarRally,
|
const dieFaces = this.advantageFaces,
|
||||||
advDie = new foundry.dice.terms.Die({ faces: dieFaces });
|
advDie = new foundry.dice.terms.Die({ faces: dieFaces, number: this.advantageNumber });
|
||||||
if (this.hasAdvantage || this.hasDisadvantage || bardRallyFaces)
|
if(this.advantageNumber > 1) advDie.modifiers = ['kh'];
|
||||||
this.terms.push(new foundry.dice.terms.OperatorTerm({ operator: this.hasDisadvantage ? '-' : '+' }));
|
this.terms.push(
|
||||||
if (bardRallyFaces) {
|
new foundry.dice.terms.OperatorTerm({ operator: this.hasDisadvantage ? '-' : '+' }),
|
||||||
const rallyDie = new foundry.dice.terms.Die({ faces: bardRallyFaces });
|
advDie
|
||||||
if (this.hasAdvantage) {
|
);
|
||||||
this.terms.push(
|
}
|
||||||
new foundry.dice.terms.PoolTerm({
|
if(this.rallyFaces)
|
||||||
terms: [advDie.formula, rallyDie.formula],
|
this.terms.push(
|
||||||
modifiers: ['kh']
|
new foundry.dice.terms.OperatorTerm({ operator: this.hasDisadvantage ? '-' : '+' }),
|
||||||
})
|
new foundry.dice.terms.Die({ faces: this.rallyFaces })
|
||||||
);
|
);
|
||||||
} else if (this.hasDisadvantage) {
|
|
||||||
this.terms.push(advDie, new foundry.dice.terms.OperatorTerm({ operator: '+' }), rallyDie);
|
|
||||||
}
|
|
||||||
} else if (this.hasAdvantage || this.hasDisadvantage) this.terms.push(advDie);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
applyBaseBonus() {
|
applyBaseBonus() {
|
||||||
|
|
@ -138,6 +162,7 @@ export default class DualityRoll extends D20Roll {
|
||||||
|
|
||||||
static postEvaluate(roll, config = {}) {
|
static postEvaluate(roll, config = {}) {
|
||||||
super.postEvaluate(roll, config);
|
super.postEvaluate(roll, config);
|
||||||
|
|
||||||
config.roll.hope = {
|
config.roll.hope = {
|
||||||
dice: roll.dHope.denomination,
|
dice: roll.dHope.denomination,
|
||||||
value: roll.dHope.total
|
value: roll.dHope.total
|
||||||
|
|
@ -146,12 +171,19 @@ export default class DualityRoll extends D20Roll {
|
||||||
dice: roll.dFear.denomination,
|
dice: roll.dFear.denomination,
|
||||||
value: roll.dFear.total
|
value: roll.dFear.total
|
||||||
};
|
};
|
||||||
|
config.roll.rally = {
|
||||||
|
dice: roll.dRally?.denomination,
|
||||||
|
value: roll.dRally?.total
|
||||||
|
};
|
||||||
config.roll.result = {
|
config.roll.result = {
|
||||||
duality: roll.withHope ? 1 : roll.withFear ? -1 : 0,
|
duality: roll.withHope ? 1 : roll.withFear ? -1 : 0,
|
||||||
total: roll.dHope.total + roll.dFear.total,
|
total: roll.dHope.total + roll.dFear.total,
|
||||||
label: roll.totalLabel
|
label: roll.totalLabel
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if(roll._rallyIndex && roll.data?.parent)
|
||||||
|
roll.data.parent.deleteEmbeddedDocuments('ActiveEffect', [roll._rallyIndex]);
|
||||||
|
|
||||||
setDiceSoNiceForDualityRoll(roll, config.roll.advantage.type);
|
setDiceSoNiceForDualityRoll(roll, config.roll.advantage.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,4 +32,26 @@ export default class DHToken extends TokenDocument {
|
||||||
|
|
||||||
return bars.concat(values);
|
return bars.concat(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static _getTrackedAttributesFromSchema(schema, _path=[]) {
|
||||||
|
const attributes = {bar: [], value: []};
|
||||||
|
for ( const [name, field] of Object.entries(schema.fields) ) {
|
||||||
|
const p = _path.concat([name]);
|
||||||
|
if ( field instanceof foundry.data.fields.NumberField ) attributes.value.push(p);
|
||||||
|
if ( field instanceof foundry.data.fields.ArrayField ) attributes.value.push(p);
|
||||||
|
const isSchema = field instanceof foundry.data.fields.SchemaField;
|
||||||
|
const isModel = field instanceof foundry.data.fields.EmbeddedDataField;
|
||||||
|
if ( isSchema || isModel ) {
|
||||||
|
const schema = isModel ? field.model.schema : field;
|
||||||
|
const isBar = schema.has && schema.has("value") && schema.has("max");
|
||||||
|
if ( isBar ) attributes.bar.push(p);
|
||||||
|
else {
|
||||||
|
const inner = this.getTrackedAttributes(schema, p);
|
||||||
|
attributes.bar.push(...inner.bar);
|
||||||
|
attributes.value.push(...inner.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset class="modifier-container one-column">
|
<fieldset class="modifier-container {{#if (eq @root.rollType 'DualityRoll')}}two-columns{{else}}one-column{{/if}}">
|
||||||
<legend>Modifiers</legend>
|
<legend>Modifiers</legend>
|
||||||
<div class="nest-inputs">
|
<div class="nest-inputs">
|
||||||
<button class="advantage-chip flex1 {{#if (eq advantage 1)}}selected{{/if}}" data-action="updateIsAdvantage" data-advantage="1">
|
<button class="advantage-chip flex1 {{#if (eq advantage 1)}}selected{{/if}}" data-action="updateIsAdvantage" data-advantage="1">
|
||||||
|
|
@ -107,13 +107,27 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<span class="label">{{localize "DAGGERHEART.GENERAL.Disadvantage.full"}}</span>
|
<span class="label">{{localize "DAGGERHEART.GENERAL.Disadvantage.full"}}</span>
|
||||||
</button>
|
</button>
|
||||||
{{#unless (eq @root.rollType 'D20Roll')}}
|
</div>
|
||||||
<select name="roll.dice.advantageFaces">
|
{{#unless (eq @root.rollType 'D20Roll')}}
|
||||||
|
<div class="nest-inputs">
|
||||||
|
<select name="roll.dice.advantageNumber"{{#unless advantage}} disabled{{/unless}}>
|
||||||
|
{{#times 10}}
|
||||||
|
<option value="{{add this 1}}" {{#if (eq @root.roll.advantageNumber (add this 1))}} selected{{/if}}>{{add this 1}}</option>
|
||||||
|
{{/times}}
|
||||||
|
</select>
|
||||||
|
<select name="roll.dice.advantageFaces"{{#unless advantage}} disabled{{/unless}}>
|
||||||
{{selectOptions diceOptions selected=@root.roll.dAdvantage.denomination}}
|
{{selectOptions diceOptions selected=@root.roll.dAdvantage.denomination}}
|
||||||
</select>
|
</select>
|
||||||
{{/unless}}
|
</div>
|
||||||
</div>
|
{{/unless}}
|
||||||
<input type="text" value="{{extraFormula}}" name="extraFormula" placeholder="Situational Bonus">
|
{{#if @root.rallyDie.length}}
|
||||||
|
<span class="formula-label">{{localize "DAGGERHEART.CLASS.Feature.rallyDice"}}</span>
|
||||||
|
<select name="roll.dice._rallyIndex">
|
||||||
|
{{selectOptions @root.rallyDie blank="" selected=@root.roll._rallyIndex}}
|
||||||
|
</select>
|
||||||
|
{{/if}}
|
||||||
|
{{#if (eq @root.rollType 'DualityRoll')}}<span class="formula-label">Situational Bonus</span>{{/if}}
|
||||||
|
<input type="text" value="{{extraFormula}}" name="extraFormula" placeholder="{{#if (eq @root.rollType 'DualityRoll')}}Ex: 1d6 + 5{{else}}Situational Bonus{{/if}}">
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
<span class="formula-label"><b>Formula:</b> {{@root.formula}}</span>
|
<span class="formula-label"><b>Formula:</b> {{@root.formula}}</span>
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,11 @@
|
||||||
{{localize "DAGGERHEART.GENERAL.Disadvantage.full"}}
|
{{localize "DAGGERHEART.GENERAL.Disadvantage.full"}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{#if roll.rally.dice}}
|
||||||
|
<div class="duality-modifier">
|
||||||
|
{{localize "DAGGERHEART.CLASS.Feature.rallyDice"}} {{roll.rally.dice}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div class="dice-result">
|
<div class="dice-result">
|
||||||
<div class="dice-formula">{{roll.formula}}</div>
|
<div class="dice-formula">{{roll.formula}}</div>
|
||||||
|
|
@ -38,7 +43,7 @@
|
||||||
<div class="dice-title">{{localize "DAGGERHEART.GENERAL.hope"}}</div>
|
<div class="dice-title">{{localize "DAGGERHEART.GENERAL.hope"}}</div>
|
||||||
<div class="dice-inner-container hope" title="{{localize "DAGGERHEART.GENERAL.hope"}}">
|
<div class="dice-inner-container hope" title="{{localize "DAGGERHEART.GENERAL.hope"}}">
|
||||||
<div class="dice-wrapper">
|
<div class="dice-wrapper">
|
||||||
<img class="dice" src="../icons/svg/d12-grey.svg"/>
|
<img class="dice" src="../icons/svg/{{roll.hope.dice}}-grey.svg"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="dice-value">{{roll.hope.value}}</div>
|
<div class="dice-value">{{roll.hope.value}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -49,7 +54,7 @@
|
||||||
<div class="dice-title">{{localize "DAGGERHEART.GENERAL.fear"}}</div>
|
<div class="dice-title">{{localize "DAGGERHEART.GENERAL.fear"}}</div>
|
||||||
<div class="dice-inner-container fear" title="{{localize "DAGGERHEART.GENERAL.fear"}}">
|
<div class="dice-inner-container fear" title="{{localize "DAGGERHEART.GENERAL.fear"}}">
|
||||||
<div class="dice-wrapper">
|
<div class="dice-wrapper">
|
||||||
<img class="dice" src="../icons/svg/d12-grey.svg"/>
|
<img class="dice" src="../icons/svg/{{roll.fear.dice}}-grey.svg"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="dice-value">{{roll.fear.value}}</div>
|
<div class="dice-value">{{roll.fear.value}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -72,7 +77,7 @@
|
||||||
<div class="dice-container">
|
<div class="dice-container">
|
||||||
<div class="dice-inner-container {{#if (eq roll.advantage.type 1)}}advantage{{else}}disadvantage{{/if}}">
|
<div class="dice-inner-container {{#if (eq roll.advantage.type 1)}}advantage{{else}}disadvantage{{/if}}">
|
||||||
<div class="dice-wrapper">
|
<div class="dice-wrapper">
|
||||||
<img class="dice" src="../icons/svg/d6-grey.svg"/>
|
<img class="dice" src="../icons/svg/{{roll.advantage.dice}}-grey.svg"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="dice-value">{{roll.advantage.value}}</div>
|
<div class="dice-value">{{roll.advantage.value}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -82,6 +87,30 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{#if roll.rally.dice}}
|
||||||
|
<div class="dice">
|
||||||
|
<header class="part-header flexrow">
|
||||||
|
<span class="part-formula">
|
||||||
|
<span>1{{roll.rally.dice}}</span>
|
||||||
|
</span>
|
||||||
|
<span class="part-total">{{roll.rally.value}}</span>
|
||||||
|
</header>
|
||||||
|
<div class="flexrow">
|
||||||
|
<ol class="dice-rolls">
|
||||||
|
<li class="roll die {{roll.rally.dice}}">
|
||||||
|
<div class="dice-container">
|
||||||
|
<div class="dice-inner-container">
|
||||||
|
<div class="dice-wrapper">
|
||||||
|
<img class="dice" src="../icons/svg/{{roll.rally.dice}}-grey.svg"/>
|
||||||
|
</div>
|
||||||
|
<div class="dice-value">{{roll.rally.value}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
{{#each roll.extra as | extra | }}
|
{{#each roll.extra as | extra | }}
|
||||||
<div class="dice">
|
<div class="dice">
|
||||||
<header class="part-header flexrow">
|
<header class="part-header flexrow">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue