First PC sheet, WIP
This commit is contained in:
@@ -7,7 +7,7 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet {
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["character"],
|
||||
position: {
|
||||
width: 750,
|
||||
width: 780,
|
||||
height: 780,
|
||||
},
|
||||
window: {
|
||||
@@ -15,14 +15,9 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet {
|
||||
},
|
||||
actions: {
|
||||
createEquipment: PrismRPGCharacterSheet.#onCreateEquipment,
|
||||
rangedAttackDefense: PrismRPGCharacterSheet.#onRangedAttackDefense,
|
||||
rollInitiative: PrismRPGCharacterSheet.#onRollInitiative,
|
||||
armorHitPointsPlus: PrismRPGCharacterSheet.#onArmorHitPointsPlus,
|
||||
armorHitPointsMinus: PrismRPGCharacterSheet.#onArmorHitPointsMinus,
|
||||
divinityPointsPlus: PrismRPGCharacterSheet.#onDivinityPointsPlus,
|
||||
divinityPointsMinus: PrismRPGCharacterSheet.#onDivinityPointsMinus,
|
||||
aetherPointsPlus: PrismRPGCharacterSheet.#onAetherPointsPlus,
|
||||
aetherPointsMinus: PrismRPGCharacterSheet.#onAetherPointsMinus,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -49,11 +44,6 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet {
|
||||
spells: {
|
||||
template: "systems/fvtt-prism-rpg/templates/character-spells.hbs",
|
||||
},
|
||||
/* Miracles disabled - Legacy from Lethal Fantasy
|
||||
miracles: {
|
||||
template: "systems/fvtt-prism-rpg/templates/character-miracles.hbs",
|
||||
},
|
||||
*/
|
||||
biography: {
|
||||
template: "systems/fvtt-prism-rpg/templates/character-biography.hbs",
|
||||
},
|
||||
@@ -79,11 +69,6 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet {
|
||||
if (this.actor.system.biodata.magicUser) {
|
||||
tabs.spells = { id: "spells", group: "sheet", icon: "fa-sharp-duotone fa-solid fa-wand-magic-sparkles", label: "PRISMRPG.Label.spells" }
|
||||
}
|
||||
/* Miracles disabled - Legacy from Lethal Fantasy
|
||||
if (this.actor.system.biodata.clericUser) {
|
||||
tabs.miracles = { id: "miracles", group: "sheet", icon: "fa-sharp-duotone fa-solid fa-hands-praying", label: "PRISMRPG.Label.miracles" }
|
||||
}
|
||||
*/
|
||||
for (const v of Object.values(tabs)) {
|
||||
v.active = this.tabGroups[v.group] === v.id
|
||||
v.cssClass = v.active ? "active" : ""
|
||||
@@ -128,13 +113,6 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet {
|
||||
context.spells = doc.itemTypes.spell
|
||||
context.hasSpells = context.spells.length > 0
|
||||
break
|
||||
/* Miracles disabled - Legacy from Lethal Fantasy
|
||||
case "miracles":
|
||||
context.tab = context.tabs.miracles
|
||||
context.miracles = doc.itemTypes.miracle
|
||||
context.hasMiracles = context.miracles.length > 0
|
||||
break
|
||||
*/
|
||||
case "combat":
|
||||
context.tab = context.tabs.combat
|
||||
context.weapons = doc.itemTypes.weapon
|
||||
@@ -172,19 +150,6 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet {
|
||||
}
|
||||
}
|
||||
|
||||
static async #onRangedAttackDefense(event, target) {
|
||||
// Future use : const hasTarget = false
|
||||
|
||||
let roll = await PrismRPGRoll.promptRangedDefense({
|
||||
actorId: this.actor.id,
|
||||
actorName: this.actor.name,
|
||||
actorImage: this.actor.img,
|
||||
})
|
||||
if (!roll) return null
|
||||
|
||||
await roll.toMessage({}, { rollMode: roll.options.rollMode })
|
||||
}
|
||||
|
||||
static async #onRollInitiative(event, target) {
|
||||
await this.document.system.rollInitiative()
|
||||
}
|
||||
@@ -201,34 +166,6 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet {
|
||||
this.actor.update({ "system.combat.armorHitPoints": Math.max(armorHP, 0) })
|
||||
}
|
||||
|
||||
static #onDivinityPointsPlus(event, target) {
|
||||
let points = this.actor.system.divinityPoints.value
|
||||
points += 1
|
||||
points = Math.min(points, this.actor.system.divinityPoints.max)
|
||||
this.actor.update({ "system.divinityPoints.value": points })
|
||||
}
|
||||
|
||||
static #onDivinityPointsMinus(event, target) {
|
||||
let points = this.actor.system.divinityPoints.value
|
||||
points -= 1
|
||||
points = Math.max(points, 0)
|
||||
this.actor.update({ "system.divinityPoints.value": points })
|
||||
}
|
||||
|
||||
static #onAetherPointsPlus(event, target) {
|
||||
let points = this.actor.system.aetherPoints.value
|
||||
points += 1
|
||||
points = Math.min(points, this.actor.system.aetherPoints.max)
|
||||
this.actor.update({ "system.aetherPoints.value": points })
|
||||
}
|
||||
|
||||
static #onAetherPointsMinus(event, target) {
|
||||
let points = this.actor.system.aetherPoints.value
|
||||
points -= 1
|
||||
points = Math.max(points, 0)
|
||||
this.actor.update({ "system.aetherPoints.value": points })
|
||||
}
|
||||
|
||||
static #onCreateEquipment(event, target) {
|
||||
}
|
||||
|
||||
@@ -269,9 +206,11 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet {
|
||||
|
||||
async _onRoll(event, target) {
|
||||
if (this.isEditMode) return
|
||||
const rollType = event.target.dataset.rollType
|
||||
let rollKey = event.target.dataset.rollKey;
|
||||
let rollDice = event.target.dataset?.rollDice;
|
||||
// Use closest to find the rollable element in case user clicked on a child
|
||||
const rollableElement = event.target.closest('.rollable') || event.target
|
||||
const rollType = rollableElement.dataset.rollType
|
||||
let rollKey = rollableElement.dataset.rollKey;
|
||||
let rollDice = rollableElement.dataset?.rollDice;
|
||||
|
||||
this.actor.prepareRoll(rollType, rollKey, rollDice)
|
||||
|
||||
|
||||
@@ -162,9 +162,11 @@ export default class PrismRPGMonsterSheet extends PrismRPGActorSheet {
|
||||
|
||||
async _onRoll(event, target) {
|
||||
if (this.isEditMode) return
|
||||
const rollType = event.target.dataset.rollType
|
||||
let rollKey = event.target.dataset.rollKey
|
||||
let rollDice = event.target.dataset?.rollDice || "0"
|
||||
// Use closest to find the rollable element in case user clicked on a child
|
||||
const rollableElement = event.target.closest('.rollable') || event.target
|
||||
const rollType = rollableElement.dataset.rollType
|
||||
let rollKey = rollableElement.dataset.rollKey
|
||||
let rollDice = rollableElement.dataset?.rollDice || "0"
|
||||
this.actor.system.prepareMonsterRoll(rollType, rollKey, rollDice)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,17 @@ export default class PrismRPGActor extends Actor {
|
||||
name: game.i18n.localize(`PRISMRPG.Label.${rollKey}`)
|
||||
}
|
||||
break
|
||||
case "sub-attribute":
|
||||
if (!this.system.subAttributes || !this.system.subAttributes[rollKey]) {
|
||||
ui.notifications.error(`Sub-attribute ${rollKey} not found`)
|
||||
return
|
||||
}
|
||||
rollTarget = {
|
||||
...foundry.utils.duplicate(this.system.subAttributes[rollKey]),
|
||||
rollKey: rollKey,
|
||||
name: game.i18n.localize(SYSTEM.SUB_ATTRIBUTES[rollKey].label)
|
||||
}
|
||||
break
|
||||
case "granted":
|
||||
rollTarget = {
|
||||
name: rollKey,
|
||||
@@ -112,6 +123,10 @@ export default class PrismRPGActor extends Actor {
|
||||
rollTarget = foundry.utils.duplicate(this.system.saves[rollKey])
|
||||
rollTarget.rollKey = rollKey
|
||||
rollTarget.rollDice = rollDice
|
||||
// Pass the characteristic value for D&D 5e modifier calculation
|
||||
rollTarget.characteristicValue = this.system.characteristics[rollKey].value
|
||||
// The save bonus is the proficiency modifier (value stored in saves)
|
||||
rollTarget.saveBonus = this.system.saves[rollKey].value
|
||||
break
|
||||
case "spell":
|
||||
rollTarget = this.items.find((i) => i.type === "spell" && i.id === rollKey)
|
||||
@@ -128,12 +143,16 @@ export default class PrismRPGActor extends Actor {
|
||||
ui.notifications.warn(game.i18n.localize("PRISMRPG.Notifications.rollFromWeapon"))
|
||||
return
|
||||
}
|
||||
// Get the primary attribute for D&D 5e style rolls
|
||||
const attrKey = rollTarget.system.primaryAttribute || "dex"
|
||||
rollTarget.characteristicValue = this.system.characteristics[attrKey].value
|
||||
rollTarget.proficiencyBonus = rollTarget.system.modifier
|
||||
break
|
||||
case "spell-attack":
|
||||
case "spell-power":
|
||||
case "miracle-attack":
|
||||
case "miracle-power":
|
||||
rollTarget = this.items.find((i) => (i.type === "miracle" || i.type == "spell") && i.id === rollKey)
|
||||
rollTarget = this.items.find((i) => (i.type === "miracle" || i.type === "spell") && i.id === rollKey)
|
||||
rollTarget.rollKey = rollKey
|
||||
break
|
||||
case "shield-roll": {
|
||||
|
||||
@@ -7,6 +7,15 @@ import { SYSTEM } from "../config/system.mjs"
|
||||
export default class PrismRPGRoll extends Roll {
|
||||
static CHAT_TEMPLATE = "systems/fvtt-prism-rpg/templates/chat-message.hbs"
|
||||
|
||||
/**
|
||||
* Calculate D&D 5e style ability modifier from ability score
|
||||
* @param {number} abilityScore The ability score value (3-18+)
|
||||
* @returns {number} The ability modifier
|
||||
*/
|
||||
static getAbilityModifier(abilityScore) {
|
||||
return Math.floor((abilityScore - 10) / 2)
|
||||
}
|
||||
|
||||
// Getters for roll data
|
||||
get type() {
|
||||
return this.options.type
|
||||
@@ -89,17 +98,40 @@ export default class PrismRPGRoll extends Roll {
|
||||
switch (options.rollType) {
|
||||
case "characteristic":
|
||||
options.rollName = options.rollTarget.name
|
||||
// Value already set in actor.mjs
|
||||
// Calculate D&D 5e modifier from characteristic value
|
||||
options.rollTarget.value = this.getAbilityModifier(options.rollTarget.value)
|
||||
break
|
||||
|
||||
case "sub-attribute":
|
||||
options.rollName = options.rollTarget.name
|
||||
// Sub-attribute value is already a modifier (calculated in prepareDerivedData)
|
||||
break
|
||||
|
||||
case "challenge":
|
||||
case "save":
|
||||
options.rollName = game.i18n.localize(`PRISMRPG.Label.${options.rollTarget.rollKey}`)
|
||||
break
|
||||
|
||||
case "save":
|
||||
options.rollName = `${game.i18n.localize(`PRISMRPG.Label.${options.rollTarget.rollKey}`)} Save`
|
||||
// Calculate D&D 5e saving throw: ability modifier + proficiency bonus
|
||||
// Get the characteristic value from rollTarget
|
||||
const charValue = options.rollTarget.characteristicValue
|
||||
const abilityMod = this.getAbilityModifier(charValue)
|
||||
const saveBonus = options.rollTarget.saveBonus || 0
|
||||
// Store separate values for display
|
||||
options.rollTarget.abilityModifier = abilityMod
|
||||
options.rollTarget.saveProficiency = saveBonus
|
||||
// Add the save bonus (proficiency) stored in saves
|
||||
options.rollTarget.value = abilityMod + saveBonus
|
||||
break
|
||||
|
||||
case "skill":
|
||||
options.rollName = options.rollTarget.name
|
||||
options.rollTarget.value = Math.floor(options.rollTarget.system.skillTotal / 10)
|
||||
// D&D 5e style: ability modifier + proficiency bonus
|
||||
const skillCharValue = options.rollTarget.characteristicValue
|
||||
const skillAbilityMod = this.getAbilityModifier(skillCharValue)
|
||||
const proficiency = options.rollTarget.proficiencyBonus || 0
|
||||
options.rollTarget.value = skillAbilityMod + proficiency
|
||||
break
|
||||
|
||||
case "weapon-attack":
|
||||
|
||||
@@ -144,23 +144,6 @@ export default class PrismRPGCharacter extends foundry.abstract.TypeDataModel {
|
||||
}, {}),
|
||||
)
|
||||
|
||||
// Core Skill system (Prism RPG)
|
||||
schema.coreSkill = new fields.SchemaField({
|
||||
skill: new fields.StringField({
|
||||
required: false,
|
||||
nullable: true,
|
||||
initial: null,
|
||||
choices: SYSTEM.CORE_SKILLS_CHOICES,
|
||||
label: "Selected Core Skill"
|
||||
}),
|
||||
attributeChoice: new fields.StringField({
|
||||
required: false,
|
||||
nullable: true,
|
||||
initial: null,
|
||||
label: "Attribute Choice for +2 Bonus"
|
||||
})
|
||||
})
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,13 @@ export default class PrismRPGSkill extends foundry.abstract.TypeDataModel {
|
||||
label: "Is Core Skill"
|
||||
})
|
||||
|
||||
// Primary attribute for this skill (str, dex, con, int, wis, cha)
|
||||
schema.primaryAttribute = new fields.StringField({
|
||||
required: true,
|
||||
initial: "dex",
|
||||
label: "Primary Attribute"
|
||||
})
|
||||
|
||||
// If Core Skill, which attribute receives the +2 bonus?
|
||||
schema.attributeBonus = new fields.StringField({
|
||||
required: true,
|
||||
@@ -107,9 +114,9 @@ export default class PrismRPGSkill extends foundry.abstract.TypeDataModel {
|
||||
prepareDerivedData() {
|
||||
super.prepareDerivedData()
|
||||
|
||||
// If this is the character's Core Skill, apply bonuses
|
||||
// D&D 5e style: Core Skill gives +2 proficiency bonus
|
||||
if (this.isCoreSkill) {
|
||||
this.modifier = CORE_SKILL_BONUS?.basic || 5
|
||||
this.modifier = 2
|
||||
this.canAdvancedCheck = true
|
||||
} else {
|
||||
this.modifier = 0
|
||||
|
||||
Reference in New Issue
Block a user