Files
fvtt-cthulhu-eternal/module/documents/actor.mjs
2025-10-01 11:24:41 +02:00

124 lines
4.1 KiB
JavaScript

import CthulhuEternalUtils from "../utils.mjs"
export default class CthulhuEternalActor extends Actor {
static async create(data, options) {
// Case of compendium global import
if (data instanceof Array) {
return super.create(data, options);
}
// If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic
if (data.items) {
let actor = super.create(data, options);
return actor;
}
if (data.type === 'protagonist') {
let era = game.settings.get("fvtt-cthulhu-eternal", "settings-era")
const skills = await CthulhuEternalUtils.loadCompendium("fvtt-cthulhu-eternal.skills")
data.items = data.items || []
for (let skill of skills) {
if (skill.system.settings === era) {
data.items.push(skill.toObject())
}
}
data.items.push({
type: "weapon", img: "systems/fvtt-cthulhu-eternal/assets/icons/icon_fist.svg",
name: game.i18n.localize("CTHULHUETERNAL.Label.Unarmed"), system: { damage: "1d4-1", weaponType: "unarmed" }
})
}
return super.create(data, options);
}
_onUpdate(changed, options, userId) {
if (changed?.system?.wp?.exhausted) {
ChatMessage.create({
user: userId,
speaker: { alias: this.name },
rollMode: "selfroll",
content: game.i18n.localize("CTHULHUETERNAL.ChatMessage.exhausted"),
type: CONST.CHAT_MESSAGE_STYLES.OTHER
})
}
return super._onUpdate(changed, options, userId)
}
applyWounds(woundData) {
let updates = {}
// Get available armor
let armors = this.items.filter(i => i.type === "armor" && i.system.equipped)
let totalArmor = 0
for (let armor of armors) {
totalArmor += armor.system.protection
}
let effectiveWounds = Math.max(woundData.rollResult - totalArmor, 0)
if (woundData.isLethal) {
effectiveWounds = this.system.hp.value // Killed!
}
// Apply armor reduction
let hp = Math.max(this.system.hp.value - effectiveWounds, 0)
if (this.system.hp.value !== hp) {
updates[`system.hp.value`] = hp
}
if (Object.keys(updates).length > 0) {
this.update(updates)
}
// Chat message for GM only
if (game.user.isGM) {
let armorText = totalArmor > 0 ? game.i18n.format("CTHULHUETERNAL.Chat.armorAbsorbed", { armor: totalArmor }) : game.i18n.localize("CTHULHUETERNAL.Chat.noArmor")
ChatMessage.create({
user: game.user.id,
speaker: { alias: this.name },
rollMode: "gmroll",
content: game.i18n.format("CTHULHUETERNAL.Chat.woundsApplied", { name: this.name, effectiveWounds, armorText }),
})
}
}
async createEmbeddedDocuments(embeddedName, data, operation) {
let newData = []
if (embeddedName === "Item") {
for (let i of data) {
if (i.type === "skill") {
if (this.items.find(item => item.name.toLowerCase() === i.name.toLowerCase())) {
ui.notifications.warn(game.i18n.localize("CTHULHUETERNAL.Notifications.skillAlreadyExists"))
continue
}
}
if (i.type === "bond") {
if (!i.system?.bondType) {
return super.createEmbeddedDocuments(embeddedName, data, operation)
}
if (i.system.bondType === "individual") {
i.system.value = this.system.characteristics.cha.value
} else {
i.system.value = Math.floor(this.system.resources.permanentRating / 2)
}
}
newData.push(i)
}
return super.createEmbeddedDocuments(embeddedName, newData, operation)
}
return super.createEmbeddedDocuments(embeddedName, data, operation)
}
async _preCreate(data, options, user) {
await super._preCreate(data, options, user)
// Configure prototype token settings
const prototypeToken = {}
if (this.type === "protagonist") {
Object.assign(prototypeToken, {
sight: { enabled: true },
actorLink: true,
disposition: CONST.TOKEN_DISPOSITIONS.FRIENDLY,
})
this.updateSource({ prototypeToken })
}
}
}