Attempt to add HUD core
This commit is contained in:
192
module/utils.mjs
192
module/utils.mjs
@@ -16,6 +16,14 @@ export default class CthulhuEternalUtils {
|
||||
config: true,
|
||||
onChange: _ => window.location.reload()
|
||||
});
|
||||
game.settings.register("fvtt-cthulhu-eternal", "roll-opposed-store", {
|
||||
name: "Roll Opposed Store",
|
||||
hint: "Whether to store opposed roll results for later use",
|
||||
default: { roll1: null, roll2: null },
|
||||
scope: "world",
|
||||
type: Object,
|
||||
config: false
|
||||
});
|
||||
}
|
||||
|
||||
static async loadCompendiumData(compendium) {
|
||||
@@ -180,6 +188,53 @@ export default class CthulhuEternalUtils {
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static removeChatMessageId(messageId) {
|
||||
if (messageId) {
|
||||
game.messages.get(messageId)?.delete();
|
||||
}
|
||||
}
|
||||
|
||||
static findChatMessageId(current) {
|
||||
return HawkmoonUtility.getChatMessageId(HawkmoonUtility.findChatMessage(current));
|
||||
}
|
||||
|
||||
static getChatMessageId(node) {
|
||||
return node?.attributes.getNamedItem('data-message-id')?.value;
|
||||
}
|
||||
|
||||
static findChatMessage(current) {
|
||||
return HawkmoonUtility.findNodeMatching(current, it => it.classList.contains('chat-message') && it.attributes.getNamedItem('data-message-id'))
|
||||
}
|
||||
|
||||
static findNodeMatching(current, predicate) {
|
||||
if (current) {
|
||||
if (predicate(current)) {
|
||||
return current;
|
||||
}
|
||||
return HawkmoonUtility.findNodeMatching(current.parentElement, predicate);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getWeaponSkill(actor, weapon, era) {
|
||||
let skill
|
||||
if (weapon.system.hasDirectSkill) {
|
||||
let skillName = weapon.name
|
||||
skill = { type: "skill", name: skillName, system: { base: 0, bonus: weapon.system.directSkillValue, skillTotal: weapon.system.directSkillValue } }
|
||||
} else {
|
||||
let skillName = game.i18n.localize(SYSTEM.WEAPON_SKILL_MAPPING[era][weapon.system.weaponType])
|
||||
skill = actor.items.find(i => i.type === "skill" && i.name.toLowerCase() === skillName.toLowerCase())
|
||||
if (!skill) {
|
||||
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.NoWeaponSkill"))
|
||||
return
|
||||
}
|
||||
}
|
||||
return skill
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async applySANType(rollMessage, event) {
|
||||
let rollData = rollMessage.getFlag("fvtt-cthulhu-eternal", "rollData")
|
||||
if (!rollData) {
|
||||
@@ -248,6 +303,134 @@ export default class CthulhuEternalUtils {
|
||||
})
|
||||
}
|
||||
|
||||
static async opposedRollManagement(rollMessage, event) {
|
||||
let rollData = rollMessage.getFlag("fvtt-cthulhu-eternal", "rollData")
|
||||
if (!rollData) {
|
||||
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.noRollDataFound"))
|
||||
return
|
||||
}
|
||||
|
||||
// Get the store
|
||||
let store = game.settings.get("fvtt-cthulhu-eternal", "roll-opposed-store")
|
||||
if (!store.roll1) {
|
||||
store.roll1 = {
|
||||
rollData: rollData,
|
||||
messageId: rollMessage.id
|
||||
}
|
||||
await game.settings.set("fvtt-cthulhu-eternal", "roll-opposed-store", store)
|
||||
ui.notifications.info(game.i18n.localize("CTHULHUETERNAL.Notifications.opposedRollFirstStored"))
|
||||
}
|
||||
else if (!store.roll2) {
|
||||
store.roll2 = {
|
||||
rollData: rollData,
|
||||
messageId: rollMessage.id
|
||||
}
|
||||
await game.settings.set("fvtt-cthulhu-eternal", "roll-opposed-store", store)
|
||||
ui.notifications.info(game.i18n.localize("CTHULHUETERNAL.Notifications.opposedRollSecondStored"))
|
||||
// Now perform the opposed roll resolution
|
||||
await this.resolveOpposedRolls(store.roll1, store.roll2)
|
||||
// Clear the store
|
||||
store.roll1 = null
|
||||
store.roll2 = null
|
||||
await game.settings.set("fvtt-cthulhu-eternal", "roll-opposed-store", store)
|
||||
}
|
||||
else {
|
||||
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.opposedRollStoreFull"))
|
||||
}
|
||||
}
|
||||
|
||||
static async resolveOpposedRolls(roll1, roll2) {
|
||||
// Get actors
|
||||
let actor1 = game.actors.get(roll1.rollData.actorId)
|
||||
let actor2 = game.actors.get(roll2.rollData.actorId)
|
||||
if (!actor1 || !actor2) {
|
||||
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.noActorFound"))
|
||||
return
|
||||
}
|
||||
// Determine winner
|
||||
let winner = null
|
||||
let loser = null
|
||||
// If there critical success/failure, apply them first (remark : this d100 results)
|
||||
roll1.rollData.rollCompare = roll1.rollData.rollResult
|
||||
roll2.rollData.rollCompare = roll2.rollData.rollResult
|
||||
if (roll1.rollData.resultType === "successCritical") {
|
||||
roll1.rollData.rollCompare = -roll1.rollData.rollResult
|
||||
}
|
||||
if (roll2.rollData.resultType === "failureCritical") {
|
||||
roll2.rollData.rollCompare = 100 + roll2.rollData.rollResult
|
||||
}
|
||||
if (roll2.rollData.resultType === "successCritical") {
|
||||
roll2.rollData.rollCompare = -roll2.rollData.rollResult
|
||||
}
|
||||
if (roll1.rollData.resultType === "failureCritical") {
|
||||
roll1.rollData.rollCompare = roll1.rollData.rollResult * 2
|
||||
}
|
||||
if (roll1.rollData.isSuccess && roll2.rollData.isFailure) {
|
||||
winner = { actor: actor1, rollData: roll1.rollData, messageId: roll1.messageId }
|
||||
loser = { actor: actor2, rollData: roll2.rollData, messageId: roll2.messageId }
|
||||
}
|
||||
else if (roll2.rollData.isSuccess && roll1.rollData.isFailure) {
|
||||
winner = { actor: actor2, rollData: roll2.rollData, messageId: roll2.messageId }
|
||||
loser = { actor: actor1, rollData: roll1.rollData, messageId: roll1.messageId }
|
||||
}
|
||||
else if (roll1.rollData.rollCompare < roll2.rollData.rollCompare) {
|
||||
winner = { actor: actor1, rollData: roll1.rollData, messageId: roll1.messageId }
|
||||
loser = { actor: actor2, rollData: roll2.rollData, messageId: roll2.messageId }
|
||||
}
|
||||
else {
|
||||
winner = { actor: actor2, rollData: roll2.rollData, messageId: roll2.messageId }
|
||||
loser = { actor: actor1, rollData: roll1.rollData, messageId: roll1.messageId }
|
||||
}
|
||||
|
||||
console.log("Opposed roll result", winner, loser)
|
||||
|
||||
// Check if winner was attacking with a weapon that can apply damage
|
||||
let canApplyDamage = winner && winner.rollData?.weapon && winner.rollData.weapon.system
|
||||
|
||||
// Prepare data for the template
|
||||
let msgData = {
|
||||
winner: {
|
||||
actor: {
|
||||
name: winner.actor.name,
|
||||
img: winner.actor.img
|
||||
},
|
||||
rollData: {
|
||||
rollResult: winner.rollData.rollResult || winner.rollData.total,
|
||||
isCritical: winner.rollData.isCritical,
|
||||
weapon: winner.rollData.weapon
|
||||
}
|
||||
},
|
||||
loser: {
|
||||
actor: {
|
||||
name: loser.actor.name,
|
||||
img: loser.actor.img
|
||||
},
|
||||
rollData: {
|
||||
rollResult: loser.rollData.rollResult || loser.rollData.total,
|
||||
isCritical: loser.rollData.isCritical
|
||||
}
|
||||
},
|
||||
canApplyDamage: canApplyDamage
|
||||
}
|
||||
|
||||
// Render the template
|
||||
let content = await foundry.applications.handlebars.renderTemplate(
|
||||
"systems/fvtt-cthulhu-eternal/templates/chat-opposed-result.hbs",
|
||||
msgData
|
||||
)
|
||||
|
||||
// Display the result in chat
|
||||
let chatMsg = await ChatMessage.create({
|
||||
speaker: ChatMessage.getSpeaker({ actor: winner.actor.id }),
|
||||
content: content
|
||||
})
|
||||
|
||||
// Store the winner's roll data for damage roll if applicable
|
||||
if (canApplyDamage) {
|
||||
await chatMsg.setFlag("fvtt-cthulhu-eternal", "rollData", winner.rollData)
|
||||
}
|
||||
}
|
||||
|
||||
static translateRangeUnit(range) {
|
||||
if (typeof range === 'string') {
|
||||
return game.i18n.localize(`CTHULHUETERNAL.Label.${range}`)
|
||||
@@ -285,6 +468,7 @@ export default class CthulhuEternalUtils {
|
||||
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Label.noActorFound"))
|
||||
return
|
||||
}
|
||||
|
||||
console.log("Damage roll data", rollData)
|
||||
rollData.weapon.resultType = rollData.resultType // Keep the result type from the roll message
|
||||
rollData.weapon.selectiveFireChoice = rollData.selectiveFireChoice // Keep the selected fire choice from the roll message
|
||||
@@ -357,6 +541,10 @@ export default class CthulhuEternalUtils {
|
||||
roll.toMessage()
|
||||
|
||||
actor.system.modifyWP(-dialogContext.wpCost)
|
||||
|
||||
// Delete the initial roll message
|
||||
await rollMessage.delete()
|
||||
|
||||
}
|
||||
|
||||
static setupCSSRootVariables() {
|
||||
@@ -395,6 +583,10 @@ export default class CthulhuEternalUtils {
|
||||
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.noActorFound"))
|
||||
return
|
||||
}
|
||||
console.log("Applying wounds", woundData)
|
||||
// Remove the chat message
|
||||
this.removeChatMessageId(message.id)
|
||||
|
||||
// Get the targetted actorId from the HTML select event
|
||||
let targetCombatantId = event.target.value
|
||||
let combatant = game.combat.combatants.get(targetCombatantId)
|
||||
|
||||
Reference in New Issue
Block a user