[PR] Adding the ability to target downtime actions. (#1475)

* Adding the ability to target downtime actions.

* No longer using an arbitrary 100 healing. Changing the action's parent
This commit is contained in:
Nick Salyzyn 2025-12-29 13:55:13 -07:00 committed by GitHub
parent e8c541c002
commit 3b7b6258a1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 69 additions and 16 deletions

View file

@ -1801,7 +1801,9 @@
"label": "Long Rest: Bonus Long Rest Moves",
"hint": "The number of extra Long Rest Moves the character can take during a Long Rest."
}
}
},
"target": "Target",
"targetSelf": "Self"
},
"maxLoadout": {
"label": "Max Loadout Cards Bonus"

View file

@ -181,12 +181,17 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
.filter(x => category.moves[x].selected)
.flatMap(key => {
const move = category.moves[key];
const needsTarget = move.actions.filter(x => x.target?.type && x.target.type !== 'self').length > 0;
return [...Array(move.selected).keys()].map(_ => ({
...move,
movePath: `${categoryKey}.moves.${key}`
movePath: `${categoryKey}.moves.${key}`,
needsTarget: needsTarget
}));
});
});
const characters = game.actors.filter(x => x.type === 'character')
.filter(x => x.testUserPermission(game.user, 'LIMITED'))
.filter(x => x.uuid !== this.actor.uuid);
const cls = getDocumentClass('ChatMessage');
const msg = {
@ -206,7 +211,9 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
`DAGGERHEART.APPLICATIONS.Downtime.${this.shortrest ? 'shortRest' : 'longRest'}.title`
),
actor: { name: this.actor.name, img: this.actor.img },
moves: moves
moves: moves,
characters: characters,
selfId: this.actor.uuid
}
),
flags: {

View file

@ -134,7 +134,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
async actionUseButton(event, message) {
const { moveIndex, actionIndex, movePath } = event.currentTarget.dataset;
const parent = await foundry.utils.fromUuid(message.system.actor);
const targetUuid = event.currentTarget.closest('.action-use-button-parent').querySelector('select')?.value;
const parent = await foundry.utils.fromUuid(targetUuid || message.system.actor)
const actionType = message.system.moves[moveIndex].actions[actionIndex];
const cls = game.system.api.models.actions.actionsTypes[actionType.type];
const action = new cls(
@ -146,7 +148,8 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
type: CONFIG.DH.ITEM.originItemType.restMove,
itemPath: movePath,
actionIndex: actionIndex
}
},
targetUuid: targetUuid
},
{ parent: parent.system }
);

View file

@ -232,7 +232,7 @@ export const defaultRestOptions = {
actionType: 'action',
chatDisplay: false,
target: {
type: 'self'
type: 'friendly'
},
damage: {
parts: [
@ -298,7 +298,7 @@ export const defaultRestOptions = {
actionType: 'action',
chatDisplay: false,
target: {
type: 'self'
type: 'friendly'
},
damage: {
parts: [
@ -341,7 +341,7 @@ export const defaultRestOptions = {
actionType: 'action',
chatDisplay: false,
target: {
type: 'self'
type: 'friendly'
},
damage: {
parts: [
@ -407,7 +407,7 @@ export const defaultRestOptions = {
actionType: 'action',
chatDisplay: false,
target: {
type: 'self'
type: 'friendly'
},
damage: {
parts: [

View file

@ -33,7 +33,8 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
initial: 'action',
nullable: false,
required: true
})
}),
targetUuid: new fields.StringField({ initial: undefined })
};
this.extraSchemas.forEach(s => {
@ -241,7 +242,8 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
selectedRollMode: game.settings.get('core', 'rollMode'),
data: this.getRollData(),
evaluate: this.hasRoll,
resourceUpdates: new ResourceUpdateMap(this.actor)
resourceUpdates: new ResourceUpdateMap(this.actor),
targetUuid: this.targetUuid
};
DHBaseAction.applyKeybindings(config);

View file

@ -25,9 +25,12 @@ export default class TargetField extends fields.SchemaField {
config.hasTarget = true;
let targets;
// If the Action is configured as self-targeted, set targets as the owner. Probably better way than to fallback to getDependentTokens
if (this.target?.type === CONFIG.DH.GENERAL.targetTypes.self.id)
if (this.target?.type === CONFIG.DH.GENERAL.targetTypes.self.id) {
targets = [this.actor.token ?? this.actor.prototypeToken];
else {
} else if (config.targetUuid) {
const actor = fromUuidSync(config.targetUuid);
targets = [actor.token ?? actor.prototypeToken];
} else {
targets = Array.from(game.user.targets);
if (this.target.type !== CONFIG.DH.GENERAL.targetTypes.any.id) {
targets = targets.filter(target => TargetField.isTargetFriendly(this.actor, target, this.target.type));

View file

@ -99,12 +99,35 @@
}
}
.action-use-button-parent {
width: 100%;
.action-use-target {
display:flex;
align-items: center;
justify-content: space-between;
gap: 4px;
width: 100%;
padding: 4px 8px 10px 40px;
font-size: var(--font-size-12);
label {
font-weight: bold;
}
select {
flex: 1;
}
}
}
.action-use-button {
width: -webkit-fill-available;
margin: 0 8px;
font-weight: 600;
height: 40px;
}
}
}
}

View file

@ -15,9 +15,22 @@
</div>
</details>
{{#each move.actions as | action index |}}
<button class="action-use-button" data-move-index="{{@../key}}" data-action-index="{{index}}" data-move-path="{{../movePath}}" >
<span>{{localize action.name}}</span>
</button>
<div class="action-use-button-parent">
<button class="action-use-button" data-move-index="{{@../key}}" data-action-index="{{index}}" data-move-path="{{../movePath}}" >
<span>{{localize action.name}}</span>
</button>
{{#if move.needsTarget}}
<div class="action-use-target">
<label>{{localize "DAGGERHEART.GENERAL.Bonuses.rest.target"}}:</label>
<select>
<option value="{{../../selfId}}">{{localize "DAGGERHEART.GENERAL.Bonuses.rest.targetSelf"}}</option>
{{#each ../../characters as | character |}}
<option value="{{character.uuid}}">{{character.name}}</option>
{{/each}}
</select>
</div>
{{/if}}
</div>
{{/each}}
{{/each}}
</ul>