Added basic chat-message.hbs

This commit is contained in:
WBHarry 2025-07-28 22:50:08 +02:00
parent 094e0740dd
commit 078ca3262d
5 changed files with 140 additions and 45 deletions

View file

@ -129,6 +129,7 @@ Hooks.once('init', () => {
CONFIG.ChatMessage.dataModels = models.chatMessages.config;
CONFIG.ChatMessage.documentClass = documents.DhChatMessage;
CONFIG.ChatMessage.template = 'systems/daggerheart/templates/ui/chat/chat-message.hbs';
CONFIG.Canvas.rulerClass = placeables.DhRuler;
CONFIG.Canvas.layers.templates.layerClass = placeables.DhTemplateLayer;

View file

@ -1,4 +1,4 @@
import { emitAsGM, GMUpdateEvent } from "../../systemRegistration/socket.mjs";
import { emitAsGM, GMUpdateEvent } from '../../systemRegistration/socket.mjs';
export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLog {
constructor(options) {
@ -15,6 +15,11 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
this.setupHooks();
}
/** @inheritDoc */
static DEFAULT_OPTIONS = {
classes: ['daggerheart']
};
addChatListeners = async (app, html, data) => {
html.querySelectorAll('.duality-action-damage').forEach(element =>
element.addEventListener('click', event => this.onRollDamage(event, data.message))
@ -100,22 +105,24 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
if (message.system.source.item && message.system.source.action) {
const action = this.getAction(actor, message.system.source.item, message.system.source.action);
if (!action || !action?.hasSave) return;
action.rollSave(token.actor, event, message).then(result => emitAsGM(
GMUpdateEvent.UpdateSaveMessage,
action.updateSaveMessage.bind(action, result, message, token.id),
{
action: action.uuid,
message: message._id,
token: token.id,
result
}
));
action.rollSave(token.actor, event, message).then(result =>
emitAsGM(
GMUpdateEvent.UpdateSaveMessage,
action.updateSaveMessage.bind(action, result, message, token.id),
{
action: action.uuid,
message: message._id,
token: token.id,
result
}
)
);
}
}
async onRollAllSave(event, message) {
event.stopPropagation();
if(!game.user.isGM) return;
if (!game.user.isGM) return;
const targets = event.target.parentElement.querySelectorAll(
'.target-section > [data-token] .target-save-container'
);
@ -124,16 +131,17 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
targets.forEach(async el => {
const tokenId = el.closest('[data-token]')?.dataset.token,
token = game.canvas.tokens.get(tokenId);
if(!token.actor) return;
if(game.user === token.actor.owner)
el.dispatchEvent(new PointerEvent('click', { shiftKey: true }));
if (!token.actor) return;
if (game.user === token.actor.owner) el.dispatchEvent(new PointerEvent('click', { shiftKey: true }));
else {
token.actor.owner.query('reactionRoll', {
actionId: action.uuid,
actorId: token.actor.uuid,
event,
message
}).then(result => action.updateSaveMessage(result, message, token.id));
token.actor.owner
.query('reactionRoll', {
actionId: action.uuid,
actorId: token.actor.uuid,
event,
message
})
.then(result => action.updateSaveMessage(result, message, token.id));
}
});
}
@ -172,7 +180,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
return {
isHit,
targets: isHit
? message.system.targets.filter(t => t.hit === true).map(target => game.canvas.tokens.documentCollection.find(t => t.actor.uuid === target.actorId))
? message.system.targets
.filter(t => t.hit === true)
.map(target => game.canvas.tokens.documentCollection.find(t => t.actor.uuid === target.actorId))
: Array.from(game.user.targets)
};
}
@ -234,10 +244,8 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
});
}
if(message.system.hasHealing)
target.actor.takeHealing(damages);
else
target.actor.takeDamage(damages);
if (message.system.hasHealing) target.actor.takeHealing(damages);
else target.actor.takeDamage(damages);
}
}

View file

@ -6,8 +6,10 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
_source: this.system._source
});
const actor = game.actors.get(this.speaker.actor);
const actorData = actor ?? { img: 'icons/svg/mystery-man.svg', name: '' };
/* We can change to fully implementing the renderHTML function if needed, instead of augmenting it. */
const html = await super.renderHTML();
const html = await super.renderHTML({ actor: actorData });
this.applyPermission(html);
if (this.type === 'dualityRoll') {

View file

@ -1,18 +1,64 @@
@import '../utils/colors.less';
@import '../utils/fonts.less';
@import '../utils/mixin.less';
.dh-chat-message {
background-image: url('../assets/parchments/dh-parchment-dark.png');
border: none !important;
padding: 8px 0;
.message-header {
padding: 0 8px 8px;
color: @beige;
.message-sender,
.message-metadata {
font-family: @font-body;
}
}
}
@import '../utils/colors.less';
@import '../utils/fonts.less';
@import '../utils/mixin.less';
.theme-light {
.daggerheart.chat-sidebar .chat-log {
.chat-message {
background-image: url('../assets/parchments/dh-parchment-light.png');
}
}
}
.daggerheart.chat-sidebar {
.chat-log {
.chat-message {
border: none !important;
padding: 8px 0;
background-image: url('../assets/parchments/dh-parchment-dark.png');
.message-header {
padding: 0 8px 8px;
.message-header-section {
width: 100%;
display: flex;
.message-metadata {
font-family: @font-body;
}
}
.message-sub-header {
width: 100%;
display: flex;
gap: 8px;
.actor-img {
flex: none;
border-radius: 50%;
width: 60px;
height: 60px;
}
.message-sub-header-container {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 4px 0;
color: @beige;
h4 {
font-size: 20px;
font-weight: bold;
margin-bottom: 0;
font-family: @font-body;
color: @golden;
}
}
}
}
}
}
}

View file

@ -0,0 +1,38 @@
<li class="chat-message message flexcol {{cssClass}}" data-message-id="{{message._id}}"
{{#if borderColor}}style="border-color:{{borderColor}}"{{/if}}>
<header class="message-header flexrow">
<div class="message-sub-header">
<img class="actor-img" src="{{actor.img}}" />
<div class="message-sub-header-container">
<h4>{{ifThen message.title message.title alias}}</h4>
<div>{{actor.name}}</div>
</div>
</div>
<div class="message-header-section">
<span class="message-metadata">
<time class="message-timestamp">{{timeSince message.timestamp}}</time>
{{#if canDelete}}
<a aria-label="{{localize 'Delete'}}" class="message-delete" data-action="deleteMessage">
<i class="fa-solid fa-trash" inert></i>
</a>
{{/if}}
{{#if canClose}}
<a aria-label="{{ localize "CHAT.Dismiss" }}" class="message-dismiss" data-action="dismissMessage">
<i class="fa-solid fa-xmark" inert></i>
</a>
{{/if}}
</span>
{{#if isWhisper}}
<span class="whisper-to">{{localize 'CHAT.To'}}: {{whisperTo}}</span>
{{/if}}
{{#if message.flavor}}
<span class="flavor-text">{{{message.flavor}}}</span>
{{/if}}
</div>
</header>
<div class="message-content">
{{{message.content}}}
</div>
</li>