Begin damage

This commit is contained in:
Aurélien LEBOURGEOIS 2025-06-18 17:35:32 +02:00
parent 7cc92d153b
commit 1c90024a5d
11 changed files with 159 additions and 104 deletions

View file

@ -9,15 +9,26 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
/* We can change to fully implementing the renderHTML function if needed, instead of augmenting it. */
const html = await super.renderHTML();
console.log(this.system)
if (
this.type === 'dualityRoll'
) {
html.classList.add('duality');
const dualityResult = this.system.dualityResult;
if (dualityResult === DHDualityRoll.dualityResult.hope) html.classList.add('hope');
/* const dualityResult = this.system.dualityResult; */
switch (this.system.roll.result.duality) {
case 1:
html.classList.add('hope');
break;
case -1:
html.classList.add('fear');
break;
default:
html.classList.add('critical');
break;
}
/* if (dualityResult === DHDualityRoll.dualityResult.hope) html.classList.add('hope');
else if (dualityResult === DHDualityRoll.dualityResult.fear) html.classList.add('fear');
else html.classList.add('critical');
else html.classList.add('critical'); */
}
return html;

View file

@ -125,6 +125,10 @@ export class D20Roll extends DHRoll {
this.terms[0].faces = faces;
}
get dAdvantage() {
return this.dice[2];
}
get isCritical() {
if ( !this.d20._evaluated ) return;
return this.d20.total >= this.constructor.CRITICAL_TRESHOLD;
@ -156,21 +160,6 @@ export class D20Roll extends DHRoll {
else config.advantage = this.ADV_MODE.NORMAL;
}
static async postEvaluate(roll, config={}) {
if (config.targets?.length) {
targets = config.targets.map(target => {
const difficulty = config.roll.difficulty ?? target.difficulty ?? target.evasion
target.hit = roll.total >= difficulty;
return target;
});
} else if(config.roll.difficulty) roll.success = roll.total >= config.roll.difficulty;
// config.roll.advantage = {
// dice: roll.dHope.faces,
// value: roll.dHope.total
// }
config.roll.total = roll.total;
}
createBaseDice() {
if ( this.terms[0] instanceof foundry.dice.terms.Die ) return;
this.terms[0] = new foundry.dice.terms.Die({ faces: 20 });
@ -193,7 +182,15 @@ export class D20Roll extends DHRoll {
this.applyBaseBonus();
this.options.experiences?.forEach(m => {
if(this.options.actor.experiences?.[m]) this.terms.push(...this.formatModifier(this.options.actor.experiences[m].total));
if(this.options.actor.experiences?.[m]) this.options.roll.modifiers.push(
{
label: this.options.actor.experiences[m].description,
value: this.options.actor.experiences[m].total
}
);
})
this.options.roll.modifiers?.forEach(m => {
this.terms.push(...this.formatModifier(m.value));
})
if(this.options.extraFormula) this.terms.push(new foundry.dice.terms.OperatorTerm({operator: '+'}), ...this.constructor.parse(this.options.extraFormula, this.getRollData()));
@ -204,14 +201,36 @@ export class D20Roll extends DHRoll {
applyBaseBonus() {
// if(this.options.action) {
if(this.options.type === "attack") this.terms.push(...this.formatModifier(this.options.actor.system.attack.modifier));
this.options.roll.modifiers?.forEach(m => {
/* this.options.roll.modifiers?.forEach(m => {
this.terms.push(...this.formatModifier(m));
})
}) */
// }
}
static async postEvaluate(roll, config={}) {
if (config.targets?.length) {
targets = config.targets.map(target => {
const difficulty = config.roll.difficulty ?? target.difficulty ?? target.evasion
target.hit = roll.total >= difficulty;
return target;
});
} else if(config.roll.difficulty) roll.success = roll.total >= config.roll.difficulty;
// config.roll.advantage = {
// dice: roll.dHope.faces,
// value: roll.dHope.total
// }
config.roll.total = roll.total;
config.roll.formula = roll.formula;
config.roll.advantage = {
type: config.advantage,
dice: roll.dAdvantage?.denomination,
value: roll.dAdvantage?.total
}
config.roll.modifierTotal = config.roll.modifiers.reduce((a,c) => a + c.value, 0);
}
getRollData() {
return {...this.options.actor.getRollData(), ...(this.options.action?.getRollData() ?? {})}
return this.options.actor.getRollData();
}
formatModifier(modifier) {
@ -259,6 +278,10 @@ export class DualityRoll extends D20Roll {
// this.#fearDice = `d${face}`;
}
get dAdvantage() {
return this.dice[2];
}
get isCritical() {
if ( !this.dHope._evaluated || !this.dFear._evaluated ) return;
return this.dHope.total === this.dFear.total;
@ -274,6 +297,23 @@ export class DualityRoll extends D20Roll {
return this.dHope.total < this.dFear.total;
}
get hasBarRally() {
return null;
}
get totalLabel() {
const label =
this.withHope
? 'DAGGERHEART.General.Hope'
: this.withFear
? 'DAGGERHEART.General.Fear'
: 'DAGGERHEART.General.CriticalSuccess';
return game.i18n.localize(label);
}
createBaseDice() {
if ( this.dice[0] instanceof CONFIG.Dice.daggerheart.DualityDie && this.dice[1] instanceof CONFIG.Dice.daggerheart.DualityDie ) return;
if ( !(this.dice[0] instanceof CONFIG.Dice.daggerheart.DualityDie) ) this.terms[0] = new CONFIG.Dice.daggerheart.DualityDie();
@ -283,7 +323,7 @@ export class DualityRoll extends D20Roll {
applyAdvantage() {
const dieFaces = 6,
bardRallyFaces = null,
bardRallyFaces = this.hasBarRally,
advDie = new foundry.dice.terms.Die({faces: dieFaces});
// console.log(this.hasAdvantage, this.hasDisadvantage)
if(this.hasAdvantage || this.hasDisadvantage || bardRallyFaces) this.terms.push(new foundry.dice.terms.OperatorTerm({operator:'+'}));
@ -304,24 +344,33 @@ export class DualityRoll extends D20Roll {
// if(this.options.action) {
// console.log(this.options, this.options.actor.system.traits[this.options.roll.trait].bonus)
// console.log(this.options.actor.system);
if(this.options.roll?.trait) this.terms.push(...this.formatModifier(this.options.actor.traits[this.options.roll.trait].total));
this.options.roll.modifiers?.forEach(m => {
this.terms.push(...this.formatModifier(m.value));
})
/* if(this.options.roll?.trait) this.terms.push(...this.formatModifier(this.options.actor.traits[this.options.roll.trait].total)); */
if(!this.options.roll.modifiers) this.options.roll.modifiers = [];
if(this.options.roll?.trait) this.options.roll.modifiers.push(
{
label: `DAGGERHEART.Abilities.${this.options.roll.trait}.name`,
value: this.options.actor.traits[this.options.roll.trait].total
}
);
// } else if(this.options.trait) this.terms.push(...this.formatModifier(this.options.actor.system.traits[this.options.roll.trait].total));
}
static async postEvaluate(roll, config={}) {
console.log(roll,config)
super.postEvaluate(roll, config);
config.roll.hope = {
dice: roll.dHope.faces,
dice: roll.dHope.denomination,
value: roll.dHope.total
}
config.roll.fear = {
dice: roll.dFear.faces,
dice: roll.dFear.denomination,
value: roll.dFear.total
}
config.roll.dualityResult = roll.withHope ? 1 : roll.withFear ? 2 : 0;
config.roll.result = {
duality: roll.withHope ? 1 : roll.withFear ? -1 : 0,
total: roll.dHope.total + roll.dFear.total,
label: roll.totalLabel
}
}
}

View file

@ -288,16 +288,15 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
const abilityLabel = game.i18n.localize(abilities[button.dataset.attribute].label);
const config = {
event: event,
title: game.i18n.format('DAGGERHEART.Chat.DualityRoll.AbilityCheckTitle', {
ability: abilityLabel
}),
title: game.i18n.format('DAGGERHEART.Chat.DualityRoll.AbilityCheckTitle', { ability: abilityLabel }),
roll: {
label: abilityLabel,
modifier: button.dataset.value
trait: button.dataset.attribute
/* label: abilityLabel,
modifier: button.dataset.value */
},
chatMessage: {
/* chatMessage: {
template: 'systems/daggerheart/templates/chat/duality-roll.hbs'
}
} */
};
this.document.diceRoll(config);

View file

@ -140,6 +140,10 @@ export class DHBaseAction extends foundry.abstract.DataModel {
return foundry.utils.getProperty(this.parent, this.systemPath).indexOf(this);
}
get id() {
return this._id;
}
get item() {
return this.parent.parent;
}
@ -190,8 +194,8 @@ export class DHBaseAction extends foundry.abstract.DataModel {
event,
title: this.item.name,
source: {
itemId: this.item._id,
actionId: this._id
item: this.item._id,
action: this._id
},
type: this.type,
hasDamage: !!this.damage?.parts?.length,
@ -238,7 +242,7 @@ export class DHBaseAction extends foundry.abstract.DataModel {
...config,
roll: {
// modifier: modifierValue,
modifier: [],
modifiers: [],
trait: this.roll?.trait,
label: game.i18n.localize(abilities[this.roll.trait].label),
type: this.actionType,

View file

@ -17,18 +17,18 @@ export default class DHDualityRoll extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
title: new fields.StringField(),
origin: new fields.StringField({ required: true }),
/* origin: new fields.StringField({ required: true }), */
roll: new fields.DataField({}),
modifiers: new fields.ArrayField(
/* modifiers: new fields.ArrayField(
new fields.SchemaField({
value: new fields.NumberField({ integer: true }),
label: new fields.StringField({})
})
),
hope: diceField(),
), */
/* hope: diceField(),
fear: diceField(),
advantageState: new fields.BooleanField({ nullable: true, initial: null }),
advantage: diceField(),
advantageState: new fields.BooleanField({ nullable: true, initial: null }), */
/* advantage: diceField(), */
targets: new fields.ArrayField(
new fields.SchemaField({
id: new fields.StringField({}),
@ -41,14 +41,15 @@ export default class DHDualityRoll extends foundry.abstract.TypeDataModel {
),
hasDamage: new fields.BooleanField({ initial: false }),
hasEffect: new fields.BooleanField({ initial: false }),
action: new fields.SchemaField({
itemId: new fields.StringField(),
actionId: new fields.StringField()
source: new fields.SchemaField({
actor: new fields.StringField(),
item: new fields.StringField(),
action: new fields.StringField()
})
};
}
get diceTotal() {
/* get diceTotal() {
return this.hope.value + this.fear.value;
}
@ -89,5 +90,5 @@ export default class DHDualityRoll extends foundry.abstract.TypeDataModel {
prepareDerivedData() {
this.hope.discarded = this.hope.value < this.fear.value;
this.fear.discarded = this.fear.value < this.hope.value;
}
} */
}

View file

@ -6,6 +6,10 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
this.config = config;
this.config.experiences = [];
/* this.diceOptions = [
{ id:12, value: 'd12' },
{ id:20, value: 'd20' }
]; */
}
static DEFAULT_OPTIONS = {
@ -45,7 +49,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
context.experiences = Object.keys(this.config.actor.experiences).map(id => ({ id, ...this.config.actor.experiences[id] }));
context.selectedExperiences = this.config.experiences;
context.advantage = this.config.advantage;
context.diceOptions = [{id:12, value: 'd12'},{id:20, value: 'd20'}]
/* context.diceOptions = this.diceOptions; */
if(this.config.costs?.length) {
const updatedCosts = this.config.action.calcCosts(this.config.costs);
context.costs = updatedCosts
@ -56,6 +60,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
static updateRollConfiguration(event, _, formData) {
const { ...rest } = foundry.utils.expandObject(formData.object);
console.log(formData.object, rest)
this.config.costs = foundry.utils.mergeObject(this.config.costs, rest.costs);
this.render();
}

View file

@ -266,10 +266,11 @@ export default class DhpActor extends Actor {
*/
async diceRoll(config, action) {
// console.log(config)
config.source = {...(config.source ?? {}), actor: this.id};
const newConfig = {
// data: {
...config,
action,
/* action, */
actor: this.getRollData(),
// },
// options: {

View file

@ -54,11 +54,13 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
onRollDamage = async (event, message) => {
event.stopPropagation();
const actor = game.actors.get(message.system.origin);
console.log(message.system)
const actor = game.actors.get(message.system.source.actor);
console.log(message.system)
if (!actor || !game.user.isGM) return true;
if(message.system.action?.itemId && message.system.action?.actionId) {
const item = actor.items.get(message.system.action?.itemId),
action = item?.system?.actions?.find(a => a._id === message.system.action.actionId);
if(message.system.source.item && message.system.source.action) {
const item = actor.items.get(message.system.source.item),
action = item?.system?.actions?.find(a => a._id === message.system.source.action);
if(!item || !action || !action?.rollDamage) return;
await action.rollDamage(event, message);
} else {
@ -73,11 +75,11 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
onApplyEffect = async (event, message) => {
event.stopPropagation();
const actor = game.actors.get(message.system.origin);
const actor = game.actors.get(message.system.source.actor);
if (!actor || !game.user.isGM) return true;
if(message.system.action?.itemId && message.system.action?.actionId) {
const item = actor.items.get(message.system.action?.itemId),
action = item?.system?.actions?.find(a => a._id === message.system.action.actionId);
if(message.system.source.item && message.system.source.action) {
const item = actor.items.get(message.system.source.item),
action = item?.system?.actions?.find(a => a._id === message.system.source.action);
if(!item || !action) return;
await action.applyEffects(event, message);
}
@ -155,7 +157,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
event.stopPropagation();
const action = message.system.actions[Number.parseInt(event.currentTarget.dataset.index)];
const actor = game.actors.get(message.system.origin);
const actor = game.actors.get(message.system.source.actor);
await actor.useAction(action);
};
}

View file

@ -1736,6 +1736,10 @@
border-radius: 0 6px 0 0;
margin-left: -8px;
}
.theme-colorful .chat-message.duality .message-content .dice-result .dice-actions .duality-action.duality-action-effect {
border-top-left-radius: 6px;
margin-left: initial;
}
.theme-colorful .chat-message.duality .message-content .dice-result .dice-actions .duality-result {
border-radius: 6px 0 0 0;
margin-right: -8px;
@ -1939,6 +1943,9 @@ div.daggerheart.views.multiclass {
.daggerheart.views.roll-selection .roll-selection-container i {
filter: invert(0%) sepia(100%) saturate(0%) hue-rotate(21deg) brightness(17%) contrast(103%);
}
.daggerheart.views.roll-selection #roll-selection-costSelection footer {
display: none;
}
.daggerheart.views.roll-selection .roll-dialog-container .disadvantage,
.daggerheart.views.roll-selection .roll-dialog-container .advantage {
border: 2px solid #708090;

View file

@ -1,17 +1,17 @@
<div class="dice-roll daggerheart chat roll" data-action="expandRoll">
<div class="dice-flavor">{{title}}</div>
<div class="duality-modifiers">
{{#each modifiers}}
{{#each roll.modifiers}}
<div class="duality-modifier">
{{label}}
{{localize label}} {{#if (gte value 0)}}+{{/if}}{{value}}
</div>
{{/each}}
{{#if (eq advantage 1)}}
{{#if (eq roll.advantage.type 1)}}
<div class="duality-modifier">
{{localize "DAGGERHEART.General.Advantage.Full"}}
</div>
{{/if}}
{{#if (eq advantage -1)}}
{{#if (eq roll.advantage.type -1)}}
<div class="duality-modifier">
{{localize "DAGGERHEART.General.Disadvantage.Full"}}
</div>
@ -29,7 +29,7 @@
|
<span>1{{roll.fear.dice}}</span>
</span>
<span class="part-total">{{diceTotal}}</span>
<span class="part-total">{{roll.result.total}}</span>
</header>
<div class="flexrow">
<ol class="dice-rolls duality">
@ -58,23 +58,23 @@
</ol>
</div>
</div>
{{#if (eq advantage 1)}}
{{#if roll.advantage.type}}
<div class="dice">
<header class="part-header flexrow">
<span class="part-formula">
<span>1{{advantage.dice}}</span>
<span>1{{roll.advantage.dice}}</span>
</span>
<span class="part-total">{{advantage.value}}</span>
<span class="part-total">{{roll.advantage.value}}</span>
</header>
<div class="flexrow">
<ol class="dice-rolls">
<li class="roll die {{advantage.dice}}">
<li class="roll die {{roll.advantage.dice}}">
<div class="dice-container">
<div class="dice-inner-container advantage">
<div class="dice-inner-container {{#if (eq roll.advantage.type 1)}}advantage{{else}}disadvantage{{/if}}">
<div class="dice-wrapper">
<img class="dice" src="../icons/svg/d6-grey.svg"/>
</div>
<div class="dice-value">{{advantage.value}}</div>
<div class="dice-value">{{roll.advantage.value}}</div>
</div>
</div>
</li>
@ -82,36 +82,12 @@
</div>
</div>
{{/if}}
{{#if (eq advantage -1)}}
<div class="dice">
<header class="part-header flexrow">
<span class="part-formula">
<span>1{{advantage.dice}}</span>
</span>
<span class="part-total">{{advantage.value}}</span>
</header>
<div class="flexrow">
<ol class="dice-rolls">
<li class="roll die {{advantage.dice}}">
<div class="dice-container">
<div class="dice-inner-container disadvantage">
<div class="dice-wrapper">
<img class="dice" src="../icons/svg/d6-grey.svg"/>
</div>
<div class="dice-value">{{advantage.value}}</div>
</div>
</div>
</li>
</ol>
</div>
</div>
{{/if}}
{{#if modifierTotal.value}}<div class="duality-modifier">{{modifierTotal.label}}</div>{{/if}}
{{#if roll.modifierTotal}}<div class="duality-modifier">{{#if (gt roll.modifierTotal 0)}}+{{/if}}{{roll.modifierTotal}}</div>{{/if}}
</section>
</div>
</div>
<div class="dice-total duality {{#if roll.fear.discarded}}hope{{else}}{{#if roll.hope.discarded}}fear{{else}}critical{{/if}}{{/if}}">
<div class="dice-total-label">{{totalLabel}}</div>
<div class="dice-total duality {{#if (eq roll.result.duality 1)}}hope{{else}}{{#if (eq roll.result.duality -1)}}fear{{else}}critical{{/if}}{{/if}}">
<div class="dice-total-label">{{roll.result.label}}</div>
<div class="dice-total-value">
{{roll.total}}
</div>
@ -136,7 +112,7 @@
<button class="duality-action{{#if hasDamage}} duality-action-effect{{/if}}" data-value="{{roll.total}}"><span>{{localize "DAGGERHEART.Chat.AttackRoll.ApplyEffect"}}</span></button>
{{/if}}
<div class="duality-result">
<div>{{roll.total}} {{#if (eq roll.dualityResult 1)}}With Hope{{else}}{{#if (eq roll.dualityResult 2)}}With Fear{{else}}Critical Success{{/if}}{{/if}}</div>
<div>{{roll.total}} {{#if (eq roll.result.duality 1)}}With Hope{{else}}{{#if (eq roll.result.duality -1)}}With Fear{{else}}Critical Success{{/if}}{{/if}}</div>
</div>
</div>
</div>

View file

@ -16,7 +16,7 @@
<button class="disadvantage flex1 {{#if (eq advantage -1)}}selected{{/if}}" data-action="updateIsAdvantage" data-advantage="-1">{{localize "DAGGERHEART.General.Disadvantage.Full"}}</button>
</div>
{{!-- {{#if (not isNpc)}} --}}
<div class="form-group">
{{!-- <div class="form-group">
<label>Hope</label>
<div class="form-fields">
<select name="hope">
@ -31,7 +31,7 @@
{{selectOptions diceOptions selected=fear valueAttr="value" labelAttr="name" localize=true}}
</select>
</div>
</div>
</div> --}}
{{!-- {{/if}} --}}
</div>
<footer>