First adaptation pass
This commit is contained in:
+41
-1
@@ -1,5 +1,45 @@
|
||||
export const TYPE = Object.freeze({
|
||||
light: { id: "light", label: "PRISMRPG.Armor.Category.light" },
|
||||
medium: { id: "medium", label: "PRISMRPG.Armor.Category.medium" },
|
||||
heavy: { id: "medium", label: "PRISMRPG.Armor.Category.heavy" }
|
||||
heavy: { id: "heavy", label: "PRISMRPG.Armor.Category.heavy" }
|
||||
})
|
||||
|
||||
// Base AC values for armor proficiency levels
|
||||
export const BASE_AC = Object.freeze({
|
||||
light: 12, // +Prowess, Competence, or Grace
|
||||
medium: 14, // +Authority, Cunning, or Resilience
|
||||
heavy: 16 // +Presence, Tenacity, or Willpower
|
||||
})
|
||||
|
||||
// AC bonus sub-attributes for each armor type
|
||||
export const AC_BONUS_ATTRIBUTES = Object.freeze({
|
||||
light: ["prowess", "competence", "grace"],
|
||||
medium: ["authority", "cunning", "resilience"],
|
||||
heavy: ["presence", "tenacity", "willpower"]
|
||||
})
|
||||
|
||||
// Withstand action APC cost for each armor type
|
||||
export const WITHSTAND_APC = Object.freeze({
|
||||
light: 1,
|
||||
medium: 2,
|
||||
heavy: 3
|
||||
})
|
||||
|
||||
// Armor set composition requirements
|
||||
export const SET_REQUIREMENTS = Object.freeze({
|
||||
light: {
|
||||
light: 2,
|
||||
medium: 0,
|
||||
heavy: 0
|
||||
},
|
||||
medium: {
|
||||
light: 3,
|
||||
medium: 1,
|
||||
heavy: 0
|
||||
},
|
||||
heavy: {
|
||||
light: 3,
|
||||
medium: 2,
|
||||
heavy: 1
|
||||
}
|
||||
})
|
||||
|
||||
+101
-15
@@ -1,15 +1,7 @@
|
||||
export const CHARACTERISTICS = Object.freeze({
|
||||
str: {
|
||||
id: "str",
|
||||
label: "PRISMRPG.Label.str"
|
||||
},
|
||||
int: {
|
||||
id: "int",
|
||||
label: "PRISMRPG.Character.int.label"
|
||||
},
|
||||
wis: {
|
||||
id: "wis",
|
||||
label: "PRISMRPG.Character.wis.label"
|
||||
label: "PRISMRPG.Character.str.label"
|
||||
},
|
||||
dex: {
|
||||
id: "dex",
|
||||
@@ -19,18 +11,112 @@ export const CHARACTERISTICS = Object.freeze({
|
||||
id: "con",
|
||||
label: "PRISMRPG.Character.con.label"
|
||||
},
|
||||
int: {
|
||||
id: "int",
|
||||
label: "PRISMRPG.Character.int.label"
|
||||
},
|
||||
wis: {
|
||||
id: "wis",
|
||||
label: "PRISMRPG.Character.wis.label"
|
||||
},
|
||||
cha: {
|
||||
id: "cha",
|
||||
label: "PRISMRPG.Character.cha.label"
|
||||
}
|
||||
})
|
||||
|
||||
// Sub-Attributes derived from combinations of two main attributes
|
||||
export const SUB_ATTRIBUTES = Object.freeze({
|
||||
prowess: {
|
||||
id: "prowess",
|
||||
label: "PRISMRPG.Character.prowess.label",
|
||||
parents: ["str", "dex"],
|
||||
description: "PRISMRPG.Character.prowess.description"
|
||||
},
|
||||
luc: {
|
||||
id: "luc",
|
||||
label: "PRISMRPG.Character.luc.label"
|
||||
vigor: {
|
||||
id: "vigor",
|
||||
label: "PRISMRPG.Character.vigor.label",
|
||||
parents: ["str", "con"],
|
||||
description: "PRISMRPG.Character.vigor.description"
|
||||
},
|
||||
app: {
|
||||
id: "app",
|
||||
label: "PRISMRPG.Character.app.label"
|
||||
competence: {
|
||||
id: "competence",
|
||||
label: "PRISMRPG.Character.competence.label",
|
||||
parents: ["str", "int"],
|
||||
description: "PRISMRPG.Character.competence.description"
|
||||
},
|
||||
authority: {
|
||||
id: "authority",
|
||||
label: "PRISMRPG.Character.authority.label",
|
||||
parents: ["str", "wis"],
|
||||
description: "PRISMRPG.Character.authority.description"
|
||||
},
|
||||
presence: {
|
||||
id: "presence",
|
||||
label: "PRISMRPG.Character.presence.label",
|
||||
parents: ["str", "cha"],
|
||||
description: "PRISMRPG.Character.presence.description"
|
||||
},
|
||||
stamina: {
|
||||
id: "stamina",
|
||||
label: "PRISMRPG.Character.stamina.label",
|
||||
parents: ["dex", "con"],
|
||||
description: "PRISMRPG.Character.stamina.description"
|
||||
},
|
||||
initiative: {
|
||||
id: "initiative",
|
||||
label: "PRISMRPG.Character.initiative.label",
|
||||
parents: ["dex", "int"],
|
||||
description: "PRISMRPG.Character.initiative.description"
|
||||
},
|
||||
wit: {
|
||||
id: "wit",
|
||||
label: "PRISMRPG.Character.wit.label",
|
||||
parents: ["dex", "wis"],
|
||||
description: "PRISMRPG.Character.wit.description"
|
||||
},
|
||||
grace: {
|
||||
id: "grace",
|
||||
label: "PRISMRPG.Character.grace.label",
|
||||
parents: ["dex", "cha"],
|
||||
description: "PRISMRPG.Character.grace.description"
|
||||
},
|
||||
tenacity: {
|
||||
id: "tenacity",
|
||||
label: "PRISMRPG.Character.tenacity.label",
|
||||
parents: ["con", "int"],
|
||||
description: "PRISMRPG.Character.tenacity.description"
|
||||
},
|
||||
willpower: {
|
||||
id: "willpower",
|
||||
label: "PRISMRPG.Character.willpower.label",
|
||||
parents: ["con", "wis"],
|
||||
description: "PRISMRPG.Character.willpower.description"
|
||||
},
|
||||
resilience: {
|
||||
id: "resilience",
|
||||
label: "PRISMRPG.Character.resilience.label",
|
||||
parents: ["con", "cha"],
|
||||
description: "PRISMRPG.Character.resilience.description"
|
||||
},
|
||||
cunning: {
|
||||
id: "cunning",
|
||||
label: "PRISMRPG.Character.cunning.label",
|
||||
parents: ["int", "wis"],
|
||||
description: "PRISMRPG.Character.cunning.description"
|
||||
},
|
||||
guile: {
|
||||
id: "guile",
|
||||
label: "PRISMRPG.Character.guile.label",
|
||||
parents: ["int", "cha"],
|
||||
description: "PRISMRPG.Character.guile.description"
|
||||
},
|
||||
sovereignty: {
|
||||
id: "sovereignty",
|
||||
label: "PRISMRPG.Character.sovereignty.label",
|
||||
parents: ["wis", "cha"],
|
||||
description: "PRISMRPG.Character.sovereignty.description"
|
||||
}
|
||||
})
|
||||
|
||||
export const CHALLENGES = Object.freeze({
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Shield types based on Prism RPG rules
|
||||
* Shields prevent damage equal to their Shield Rating (SR)
|
||||
* Each shield has a Block APC and a Block Augment passive ability
|
||||
*/
|
||||
export const TYPE = Object.freeze({
|
||||
buckler: {
|
||||
id: "buckler",
|
||||
label: "PRISMRPG.Shield.Type.buckler",
|
||||
apc: 1,
|
||||
sr: "1d4",
|
||||
blockAugment: "PRISMRPG.Shield.BlockAugment.buckler",
|
||||
blockAugmentDescription: "PRISMRPG.Shield.BlockAugmentDescription.buckler"
|
||||
},
|
||||
light: {
|
||||
id: "light",
|
||||
label: "PRISMRPG.Shield.Type.light",
|
||||
apc: 2,
|
||||
sr: "1d8",
|
||||
blockAugment: "PRISMRPG.Shield.BlockAugment.light",
|
||||
blockAugmentDescription: "PRISMRPG.Shield.BlockAugmentDescription.light"
|
||||
},
|
||||
heavy: {
|
||||
id: "heavy",
|
||||
label: "PRISMRPG.Shield.Type.heavy",
|
||||
apc: 3,
|
||||
sr: "1d12",
|
||||
blockAugment: "PRISMRPG.Shield.BlockAugment.heavy",
|
||||
blockAugmentDescription: "PRISMRPG.Shield.BlockAugmentDescription.heavy"
|
||||
},
|
||||
tower: {
|
||||
id: "tower",
|
||||
label: "PRISMRPG.Shield.Type.tower",
|
||||
apc: 4,
|
||||
sr: "3d6",
|
||||
blockAugment: "PRISMRPG.Shield.BlockAugment.tower",
|
||||
blockAugmentDescription: "PRISMRPG.Shield.BlockAugmentDescription.tower"
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Block augment descriptions for reference
|
||||
* These are activated when using the Block action with the shield
|
||||
*/
|
||||
export const BLOCK_AUGMENTS = Object.freeze({
|
||||
buckler: "If the character should successfully block damage with this shield, the character reduces the cost of the next Parry action by an amount equal to their Prowess.",
|
||||
light: "If the character would successfully block damage with this shield, the character may move an amount equal to their movement rating.",
|
||||
heavy: "If the character would successfully block damage with this shield, they reduce the APC of the next attack they make by an amount equal to their Vigor or Prowess.",
|
||||
tower: "If the character would successfully block damage with this shield, for 1 round they are considered cover for themselves and allies that are adjacent to them."
|
||||
});
|
||||
@@ -1,3 +1,115 @@
|
||||
/**
|
||||
* Core Skills in Prism RPG
|
||||
* Characters choose 1 Core Skill which gives:
|
||||
* - +5 bonus to basic skill checks
|
||||
* - Access to advanced skill checks
|
||||
* - Access to a Core Skill Class (based on archetype)
|
||||
* - +2 to one of 3 associated attributes
|
||||
*/
|
||||
export const CORE_SKILLS = Object.freeze({
|
||||
acrobatics: {
|
||||
id: "acrobatics",
|
||||
label: "PRISMRPG.Skill.CoreSkill.acrobatics",
|
||||
attributeChoices: ["dex", "wis", "con"]
|
||||
},
|
||||
animalHandling: {
|
||||
id: "animalHandling",
|
||||
label: "PRISMRPG.Skill.CoreSkill.animalHandling",
|
||||
attributeChoices: ["str", "con", "dex"]
|
||||
},
|
||||
arcana: {
|
||||
id: "arcana",
|
||||
label: "PRISMRPG.Skill.CoreSkill.arcana",
|
||||
attributeChoices: ["str", "int", "wis"]
|
||||
},
|
||||
athletics: {
|
||||
id: "athletics",
|
||||
label: "PRISMRPG.Skill.CoreSkill.athletics",
|
||||
attributeChoices: ["str", "dex", "con"]
|
||||
},
|
||||
deception: {
|
||||
id: "deception",
|
||||
label: "PRISMRPG.Skill.CoreSkill.deception",
|
||||
attributeChoices: ["int", "wis", "cha"]
|
||||
},
|
||||
history: {
|
||||
id: "history",
|
||||
label: "PRISMRPG.Skill.CoreSkill.history",
|
||||
attributeChoices: ["str", "wis", "con"]
|
||||
},
|
||||
insight: {
|
||||
id: "insight",
|
||||
label: "PRISMRPG.Skill.CoreSkill.insight",
|
||||
attributeChoices: ["int", "cha", "wis"]
|
||||
},
|
||||
intimidate: {
|
||||
id: "intimidate",
|
||||
label: "PRISMRPG.Skill.CoreSkill.intimidate",
|
||||
attributeChoices: ["str", "cha", "wis"]
|
||||
},
|
||||
investigation: {
|
||||
id: "investigation",
|
||||
label: "PRISMRPG.Skill.CoreSkill.investigation",
|
||||
attributeChoices: ["int", "wis", "con"]
|
||||
},
|
||||
medicine: {
|
||||
id: "medicine",
|
||||
label: "PRISMRPG.Skill.CoreSkill.medicine",
|
||||
attributeChoices: ["con", "wis", "int"]
|
||||
},
|
||||
nature: {
|
||||
id: "nature",
|
||||
label: "PRISMRPG.Skill.CoreSkill.nature",
|
||||
attributeChoices: ["str", "wis", "int"]
|
||||
},
|
||||
perception: {
|
||||
id: "perception",
|
||||
label: "PRISMRPG.Skill.CoreSkill.perception",
|
||||
attributeChoices: ["dex", "wis", "cha"]
|
||||
},
|
||||
performance: {
|
||||
id: "performance",
|
||||
label: "PRISMRPG.Skill.CoreSkill.performance",
|
||||
attributeChoices: ["str", "cha", "wis"]
|
||||
},
|
||||
persuasion: {
|
||||
id: "persuasion",
|
||||
label: "PRISMRPG.Skill.CoreSkill.persuasion",
|
||||
attributeChoices: ["cha", "dex", "int"]
|
||||
},
|
||||
religion: {
|
||||
id: "religion",
|
||||
label: "PRISMRPG.Skill.CoreSkill.religion",
|
||||
attributeChoices: ["str", "wis", "cha"]
|
||||
},
|
||||
sleightOfHand: {
|
||||
id: "sleightOfHand",
|
||||
label: "PRISMRPG.Skill.CoreSkill.sleightOfHand",
|
||||
attributeChoices: ["dex", "wis", "int"]
|
||||
},
|
||||
stealth: {
|
||||
id: "stealth",
|
||||
label: "PRISMRPG.Skill.CoreSkill.stealth",
|
||||
attributeChoices: ["int", "dex", "cha"]
|
||||
},
|
||||
survival: {
|
||||
id: "survival",
|
||||
label: "PRISMRPG.Skill.CoreSkill.survival",
|
||||
attributeChoices: ["int", "con", "cha"]
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Core Skill bonus values
|
||||
*/
|
||||
export const CORE_SKILL_BONUS = Object.freeze({
|
||||
basic: 5, // +5 to basic skill checks
|
||||
attributeBonus: 2 // +2 to chosen attribute
|
||||
});
|
||||
|
||||
/**
|
||||
* Legacy skill categories (may be deprecated)
|
||||
*/
|
||||
export const CATEGORY = Object.freeze({
|
||||
layperson: {
|
||||
id: "layperson",
|
||||
|
||||
@@ -1,3 +1,48 @@
|
||||
/**
|
||||
* Spell colors from the Prism
|
||||
* Each color gives a different effect to spells
|
||||
*/
|
||||
export const COLORS = Object.freeze({
|
||||
indigo: {
|
||||
id: "indigo",
|
||||
label: "PRISMRPG.Spell.Color.indigo",
|
||||
description: "PRISMRPG.Spell.ColorEffect.indigo"
|
||||
},
|
||||
blue: {
|
||||
id: "blue",
|
||||
label: "PRISMRPG.Spell.Color.blue",
|
||||
description: "PRISMRPG.Spell.ColorEffect.blue"
|
||||
},
|
||||
green: {
|
||||
id: "green",
|
||||
label: "PRISMRPG.Spell.Color.green",
|
||||
description: "PRISMRPG.Spell.ColorEffect.green"
|
||||
},
|
||||
yellow: {
|
||||
id: "yellow",
|
||||
label: "PRISMRPG.Spell.Color.yellow",
|
||||
description: "PRISMRPG.Spell.ColorEffect.yellow"
|
||||
},
|
||||
orange: {
|
||||
id: "orange",
|
||||
label: "PRISMRPG.Spell.Color.orange",
|
||||
description: "PRISMRPG.Spell.ColorEffect.orange"
|
||||
},
|
||||
red: {
|
||||
id: "red",
|
||||
label: "PRISMRPG.Spell.Color.red",
|
||||
description: "PRISMRPG.Spell.ColorEffect.red"
|
||||
},
|
||||
violet: {
|
||||
id: "violet",
|
||||
label: "PRISMRPG.Spell.Color.violet",
|
||||
description: "PRISMRPG.Spell.ColorEffect.violet"
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Spell ranges (legacy - to be replaced with Prism system)
|
||||
*/
|
||||
export const RANGE = Object.freeze({
|
||||
na: {
|
||||
id: "na",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as CHARACTER from "./character.mjs"
|
||||
import * as WEAPON from "./weapon.mjs"
|
||||
import * as ARMOR from "./armor.mjs"
|
||||
import * as SHIELD from "./shield.mjs"
|
||||
import * as SPELL from "./spell.mjs"
|
||||
import * as SKILL from "./skill.mjs"
|
||||
import * as EQUIPMENT from "./equipment.mjs"
|
||||
@@ -285,6 +286,7 @@ export const ASCII = `
|
||||
export const SYSTEM = {
|
||||
id: SYSTEM_ID,
|
||||
CHARACTERISTICS: CHARACTER.CHARACTERISTICS,
|
||||
SUB_ATTRIBUTES: CHARACTER.SUB_ATTRIBUTES,
|
||||
CHARACTERISTICS_TABLES: CHARACTERISTICS.TABLES,
|
||||
CHARACTERISTICS_MAJOR: CHARACTERISTICS.MAJOR,
|
||||
MONSTER_CHARACTERISTICS: MONSTER.MONSTER_CHARACTERISTICS,
|
||||
@@ -293,10 +295,21 @@ export const SYSTEM = {
|
||||
SAVES: CHARACTER.SAVES,
|
||||
CHALLENGES: CHARACTER.CHALLENGES,
|
||||
SKILL_CATEGORY: SKILL.CATEGORY,
|
||||
CORE_SKILLS: SKILL.CORE_SKILLS,
|
||||
CORE_SKILL_BONUS: SKILL.CORE_SKILL_BONUS,
|
||||
ARMOR_TYPE: ARMOR.TYPE,
|
||||
ARMOR_BASE_AC: ARMOR.BASE_AC,
|
||||
ARMOR_AC_BONUS_ATTRIBUTES: ARMOR.AC_BONUS_ATTRIBUTES,
|
||||
ARMOR_WITHSTAND_APC: ARMOR.WITHSTAND_APC,
|
||||
ARMOR_SET_REQUIREMENTS: ARMOR.SET_REQUIREMENTS,
|
||||
SHIELD_TYPE: SHIELD.TYPE,
|
||||
SHIELD_BLOCK_AUGMENTS: SHIELD.BLOCK_AUGMENTS,
|
||||
EQUIPMENT_CATEGORY: EQUIPMENT.CATEGORY,
|
||||
SPELL_RANGE: SPELL.RANGE,
|
||||
WEAPON_TYPE: WEAPON.WEAPON_TYPE,
|
||||
SPELL_COLORS: SPELL.COLORS,
|
||||
WEAPON_TYPE: WEAPON.TYPE,
|
||||
WEAPON_GROUP: WEAPON.WEAPON_GROUP,
|
||||
WEAPON_DAMAGE_TYPE: WEAPON.DAMAGE_TYPE,
|
||||
WEAPON_CLASS: WEAPON.WEAPON_CLASS,
|
||||
COMBAT_PROGRESSION_DICE: DICE_VALUES,
|
||||
SHIELD_DEFENSE_DICE: DEFENSE_DICE_VALUES,
|
||||
|
||||
+102
-2
@@ -1,4 +1,105 @@
|
||||
/**
|
||||
* Weapon types based on Prism RPG rules
|
||||
* APC determines weapon class: Light (1 APC), One-Handed (2 APC), Heavy (3 APC)
|
||||
*/
|
||||
export const TYPE = Object.freeze({
|
||||
light: {
|
||||
id: "light",
|
||||
label: "PRISMRPG.Weapon.Type.light",
|
||||
apc: 1,
|
||||
hands: 1
|
||||
},
|
||||
oneHanded: {
|
||||
id: "oneHanded",
|
||||
label: "PRISMRPG.Weapon.Type.oneHanded",
|
||||
apc: 2,
|
||||
hands: 1
|
||||
},
|
||||
heavy: {
|
||||
id: "heavy",
|
||||
label: "PRISMRPG.Weapon.Type.heavy",
|
||||
apc: 3,
|
||||
hands: 2
|
||||
},
|
||||
projectile: {
|
||||
id: "projectile",
|
||||
label: "PRISMRPG.Weapon.Type.projectile",
|
||||
apc: 0, // Variable based on specific weapon
|
||||
hands: 2
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Weapon groups and their associated passives
|
||||
* Each weapon belongs to a group and possesses its passive while wielded
|
||||
*/
|
||||
export const WEAPON_GROUP = Object.freeze({
|
||||
longsword: {
|
||||
id: "longsword",
|
||||
label: "PRISMRPG.Weapon.WeaponGroup.longsword",
|
||||
passive: "turningEdge",
|
||||
passiveLabel: "PRISMRPG.Weapon.Passive.turningEdge",
|
||||
passiveDescription: "PRISMRPG.Weapon.PassiveDescription.turningEdge"
|
||||
},
|
||||
warhammer: {
|
||||
id: "warhammer",
|
||||
label: "PRISMRPG.Weapon.WeaponGroup.warhammer",
|
||||
passive: "puncturingBlows",
|
||||
passiveLabel: "PRISMRPG.Weapon.Passive.puncturingBlows",
|
||||
passiveDescription: "PRISMRPG.Weapon.PassiveDescription.puncturingBlows"
|
||||
},
|
||||
battleaxe: {
|
||||
id: "battleaxe",
|
||||
label: "PRISMRPG.Weapon.WeaponGroup.battleaxe",
|
||||
passive: "shieldEater",
|
||||
passiveLabel: "PRISMRPG.Weapon.Passive.shieldEater",
|
||||
passiveDescription: "PRISMRPG.Weapon.PassiveDescription.shieldEater"
|
||||
},
|
||||
dagger: {
|
||||
id: "dagger",
|
||||
label: "PRISMRPG.Weapon.WeaponGroup.dagger",
|
||||
passive: "balancingStance",
|
||||
passiveLabel: "PRISMRPG.Weapon.Passive.balancingStance",
|
||||
passiveDescription: "PRISMRPG.Weapon.PassiveDescription.balancingStance"
|
||||
},
|
||||
crossbow: {
|
||||
id: "crossbow",
|
||||
label: "PRISMRPG.Weapon.WeaponGroup.crossbow",
|
||||
passive: "boltlock",
|
||||
passiveLabel: "PRISMRPG.Weapon.Passive.boltlock",
|
||||
passiveDescription: "PRISMRPG.Weapon.PassiveDescription.boltlock"
|
||||
},
|
||||
longbow: {
|
||||
id: "longbow",
|
||||
label: "PRISMRPG.Weapon.WeaponGroup.longbow",
|
||||
passive: "volleyFire",
|
||||
passiveLabel: "PRISMRPG.Weapon.Passive.volleyFire",
|
||||
passiveDescription: "PRISMRPG.Weapon.PassiveDescription.volleyFire"
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Damage types for weapons
|
||||
*/
|
||||
export const DAMAGE_TYPE = Object.freeze({
|
||||
piercing: {
|
||||
id: "piercing",
|
||||
label: "PRISMRPG.Weapon.DamageType.piercing",
|
||||
abbreviation: "P"
|
||||
},
|
||||
bludgeoning: {
|
||||
id: "bludgeoning",
|
||||
label: "PRISMRPG.Weapon.DamageType.bludgeoning",
|
||||
abbreviation: "B"
|
||||
},
|
||||
slashing: {
|
||||
id: "slashing",
|
||||
label: "PRISMRPG.Weapon.DamageType.slashing",
|
||||
abbreviation: "S"
|
||||
}
|
||||
});
|
||||
|
||||
// Legacy exports for backward compatibility (to be removed later)
|
||||
export const WEAPON_TYPE = {
|
||||
"melee": "PRISMRPG.Weapon.WeaponType.melee",
|
||||
"ranged": "PRISMRPG.Weapon.WeaponType.ranged"
|
||||
@@ -16,7 +117,7 @@ export const WEAPON_CLASS = {
|
||||
"sling": "PRISMRPG.Weapon.WeaponClass.sling",
|
||||
"thrown": "PRISMRPG.Weapon.WeaponClass.thrown",
|
||||
"polearm": "PRISMRPG.Weapon.WeaponClass.polearm",
|
||||
"unarmed" : "PRISMRPG.Weapon.WeaponClass.unarmed"
|
||||
"unarmed": "PRISMRPG.Weapon.WeaponClass.unarmed"
|
||||
}
|
||||
|
||||
export const WEAPON_CATEGORIES = {
|
||||
@@ -32,4 +133,3 @@ export const WEAPON_CATEGORIES = {
|
||||
"thrown": ["axe", "hammer", "mace", "flail", "bow", "sling", "polearm"],
|
||||
"polearm": ["axe", "hammer", "mace", "flail", "bow", "sling", "thrown"]
|
||||
}
|
||||
|
||||
|
||||
+15
-2
@@ -7,8 +7,21 @@ export default class PrismRPGArmor extends foundry.abstract.TypeDataModel {
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.armorType = new fields.StringField({ required: true, initial: "light", choices: SYSTEM.ARMOR_TYPE })
|
||||
|
||||
// MRR - Movement Rating Reduction (reduced by Vigor sub-attribute)
|
||||
schema.mrr = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0, label: "Movement Rating Reduction" })
|
||||
|
||||
// Armor Passive - the passive ability of this armor piece
|
||||
schema.passive = new fields.StringField({ required: false, initial: "", label: "Armor Passive" })
|
||||
schema.passiveDescription = new fields.HTMLField({ required: false, textSearch: true, label: "Passive Description" })
|
||||
|
||||
// Armor Augment - the Withstand action effect (requires augment from class feature)
|
||||
schema.augment = new fields.StringField({ required: false, initial: "", label: "Armor Augment" })
|
||||
schema.augmentDescription = new fields.HTMLField({ required: false, textSearch: true, label: "Augment Description" })
|
||||
|
||||
// Legacy fields for compatibility
|
||||
schema.defense = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: -50 })
|
||||
schema.maximumMovement = new fields.StringField({ ...requiredInteger, required: true, initial: "" })
|
||||
schema.maximumMovement = new fields.StringField({ required: false, initial: "" })
|
||||
schema.hp = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
schema.damageReduction = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
|
||||
@@ -18,7 +31,7 @@ export default class PrismRPGArmor extends foundry.abstract.TypeDataModel {
|
||||
|
||||
schema.cost = new fields.NumberField({ required: true, initial: 0, min: 0 })
|
||||
schema.money = new fields.StringField({ required: true, initial: "tinbit", choices: SYSTEM.MONEY })
|
||||
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
|
||||
@@ -168,6 +168,21 @@ export default class PrismRPGCharacter extends foundry.abstract.TypeDataModel {
|
||||
}, {}),
|
||||
)
|
||||
|
||||
// Core Skill system (Prism RPG)
|
||||
schema.coreSkill = new fields.SchemaField({
|
||||
skill: new fields.StringField({
|
||||
required: true,
|
||||
initial: "",
|
||||
choices: Object.keys(SYSTEM.CORE_SKILLS || {}),
|
||||
label: "Selected Core Skill"
|
||||
}),
|
||||
attributeChoice: new fields.StringField({
|
||||
required: true,
|
||||
initial: "",
|
||||
label: "Attribute Choice for +2 Bonus"
|
||||
})
|
||||
})
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
|
||||
+108
-17
@@ -1,4 +1,5 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class PrismRPGMiracle extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
@@ -11,30 +12,120 @@ export default class PrismRPGMiracle extends foundry.abstract.TypeDataModel {
|
||||
initial: "",
|
||||
textSearch: true,
|
||||
})
|
||||
|
||||
// Miracle level (1-7+)
|
||||
schema.level = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
initial: 1,
|
||||
min: 1,
|
||||
max: 25,
|
||||
})
|
||||
schema.components = new fields.SchemaField({
|
||||
verbal: new fields.BooleanField(),
|
||||
somatic: new fields.BooleanField(),
|
||||
material: new fields.BooleanField(),
|
||||
catalyst: new fields.BooleanField(),
|
||||
religious: new fields.BooleanField()
|
||||
})
|
||||
schema.prayerTime = new fields.StringField({ required: true, initial: "" })
|
||||
schema.miracleRange = new fields.StringField({ required: true, initial: "" })
|
||||
schema.areaAffected = new fields.StringField({ required: true, initial: "" })
|
||||
schema.duration = new fields.StringField({ required: true, initial: "" })
|
||||
schema.savingThrow = new fields.StringField({ required: true, initial: "" })
|
||||
schema.materialComponent = new fields.StringField({ required: true, initial: "" })
|
||||
schema.catalyst = new fields.StringField({ required: true, initial: "" })
|
||||
schema.miracleType = new fields.StringField({ required: true, initial: "combat", choices: SYSTEM.MIRACLE_TYPES })
|
||||
|
||||
schema.attackRoll = new fields.StringField({ required: true, initial: "" })
|
||||
schema.powerRoll = new fields.StringField({ required: true, initial: "" })
|
||||
// Miracle type
|
||||
schema.miracleType = new fields.StringField({
|
||||
required: true,
|
||||
initial: "combat",
|
||||
choices: SYSTEM.MIRACLE_TYPES
|
||||
})
|
||||
|
||||
// APC to pray
|
||||
schema.apc = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
required: true,
|
||||
initial: 1,
|
||||
min: 0,
|
||||
label: "Action Point Cost"
|
||||
})
|
||||
|
||||
// Faith cost (if applicable in Prism RPG)
|
||||
schema.faithCost = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
required: true,
|
||||
initial: 0,
|
||||
min: 0,
|
||||
label: "Faith Cost"
|
||||
})
|
||||
|
||||
// Divine favor required
|
||||
schema.divineFavor = new fields.StringField({
|
||||
required: true,
|
||||
initial: "",
|
||||
label: "Divine Favor"
|
||||
})
|
||||
|
||||
// Components (Miracles have 'religious' component)
|
||||
schema.components = new fields.SchemaField({
|
||||
verbal: new fields.BooleanField({ initial: false }),
|
||||
somatic: new fields.BooleanField({ initial: false }),
|
||||
material: new fields.BooleanField({ initial: false }),
|
||||
catalyst: new fields.BooleanField({ initial: false }),
|
||||
religious: new fields.BooleanField({ initial: true })
|
||||
})
|
||||
|
||||
schema.materialComponent = new fields.StringField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
schema.catalyst = new fields.StringField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
// Prayer parameters
|
||||
schema.prayerTime = new fields.StringField({
|
||||
required: true,
|
||||
initial: "1 action"
|
||||
})
|
||||
|
||||
schema.miracleRange = new fields.StringField({
|
||||
required: true,
|
||||
initial: "Touch"
|
||||
})
|
||||
|
||||
schema.areaAffected = new fields.StringField({
|
||||
required: true,
|
||||
initial: "Single target"
|
||||
})
|
||||
|
||||
schema.duration = new fields.StringField({
|
||||
required: true,
|
||||
initial: "Instantaneous"
|
||||
})
|
||||
|
||||
schema.savingThrow = new fields.StringField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
// Attack and power
|
||||
schema.attackRoll = new fields.StringField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
schema.powerRoll = new fields.StringField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
// Keywords
|
||||
schema.keywords = new fields.ArrayField(
|
||||
new fields.StringField()
|
||||
)
|
||||
|
||||
// Miracle augment (if applicable)
|
||||
schema.augment = new fields.StringField({
|
||||
required: true,
|
||||
initial: "",
|
||||
label: "Miracle Augment"
|
||||
})
|
||||
|
||||
schema.augmentDescription = new fields.HTMLField({
|
||||
required: true,
|
||||
initial: "",
|
||||
label: "Augment Description"
|
||||
})
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class PrismRPGShield extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
@@ -6,14 +7,81 @@ export default class PrismRPGShield extends foundry.abstract.TypeDataModel {
|
||||
const requiredInteger = { required: true, nullable: false, integer: true }
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.defense = new fields.StringField({required: true, initial: "d4", choices: SYSTEM.SHIELD_DEFENSE_DICE})
|
||||
schema.movementreduction = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
schema.hascover = new fields.BooleanField({ required: true, initial: false })
|
||||
|
||||
// Prism RPG shield properties
|
||||
schema.shieldType = new fields.StringField({
|
||||
required: true,
|
||||
initial: "buckler",
|
||||
choices: Object.keys(SYSTEM.SHIELD_TYPE || {})
|
||||
})
|
||||
|
||||
// APC (Action Point Cost) for Block action
|
||||
schema.apc = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
required: true,
|
||||
initial: 1,
|
||||
min: 1,
|
||||
max: 4,
|
||||
label: "Block APC"
|
||||
})
|
||||
|
||||
// Shield Rating (SR) - damage prevention dice (e.g., "1d4", "1d8", "1d12", "3d6")
|
||||
schema.sr = new fields.StringField({
|
||||
required: true,
|
||||
initial: "1d4",
|
||||
label: "Shield Rating (SR)"
|
||||
})
|
||||
|
||||
// Block Augment - passive ability when using Block action
|
||||
schema.blockAugment = new fields.StringField({
|
||||
required: true,
|
||||
initial: "",
|
||||
label: "Block Augment"
|
||||
})
|
||||
|
||||
schema.blockAugmentDescription = new fields.HTMLField({
|
||||
required: true,
|
||||
initial: "",
|
||||
label: "Block Augment Description"
|
||||
})
|
||||
|
||||
// Augment effects (for equipment progression)
|
||||
schema.augment = new fields.StringField({
|
||||
required: true,
|
||||
initial: "",
|
||||
label: "Shield Augment"
|
||||
})
|
||||
|
||||
schema.augmentDescription = new fields.HTMLField({
|
||||
required: true,
|
||||
initial: "",
|
||||
label: "Augment Description"
|
||||
})
|
||||
|
||||
// Legacy properties (kept for backward compatibility)
|
||||
schema.defense = new fields.StringField({
|
||||
required: true,
|
||||
initial: "d4",
|
||||
choices: SYSTEM.SHIELD_DEFENSE_DICE
|
||||
})
|
||||
|
||||
schema.movementreduction = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
required: true,
|
||||
initial: 0,
|
||||
min: 0
|
||||
})
|
||||
|
||||
schema.hascover = new fields.BooleanField({
|
||||
required: true,
|
||||
initial: false
|
||||
})
|
||||
|
||||
schema.standing = new fields.SchemaField({
|
||||
min: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
})
|
||||
|
||||
schema.crouching = new fields.SchemaField({
|
||||
min: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
@@ -24,6 +92,7 @@ export default class PrismRPGShield extends foundry.abstract.TypeDataModel {
|
||||
slashing: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
piercing: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
})
|
||||
|
||||
schema.autodestruction = new fields.SchemaField({
|
||||
bashing: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
slashing: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
@@ -40,5 +109,4 @@ export default class PrismRPGShield extends foundry.abstract.TypeDataModel {
|
||||
|
||||
/** @override */
|
||||
static LOCALIZATION_PREFIXES = ["PRISMRPG.Shield"]
|
||||
|
||||
}
|
||||
|
||||
+106
-86
@@ -1,29 +1,75 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
import { CATEGORY } from "../config/skill.mjs"
|
||||
|
||||
/**
|
||||
* Core Skill data model for Prism RPG
|
||||
*
|
||||
* Core Skills are skills in which the character is particularly proficient.
|
||||
* - Basic skill checks: +5 modifier
|
||||
* - Advanced skill checks: Only accessible with Core Skill
|
||||
* - Core Skill Class: Gives access to a class based on archetype
|
||||
* - Attribute Bonus: +2 to one of 3 associated attributes
|
||||
*/
|
||||
export default class PrismRPGSkill extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const schema = {}
|
||||
const requiredInteger = { required: true, nullable: false, integer: true }
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.category = new fields.StringField({ required: true, initial: "layperson", choices: SYSTEM.SKILL_CATEGORY })
|
||||
schema.base = new fields.StringField({ required: true, initial: "WIS" })
|
||||
schema.bonus = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
|
||||
schema.classesCost = new fields.SchemaField(
|
||||
Object.values(SYSTEM.CHAR_CLASSES_DEFINES).reduce((obj, pcClass) => {
|
||||
obj[pcClass.id] = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
return obj
|
||||
}, {}),
|
||||
)
|
||||
schema.cost = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
schema.description = new fields.HTMLField({
|
||||
required: true,
|
||||
textSearch: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
schema.weaponClass = new fields.StringField({ required: true, initial: "shortblade", choices: SYSTEM.WEAPON_CLASS })
|
||||
schema.weaponBonus = new fields.SchemaField({
|
||||
attack: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
defense: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
damage: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
// Core Skill type (from the 18 available Core Skills)
|
||||
schema.coreSkill = new fields.StringField({
|
||||
required: true,
|
||||
initial: "acrobatics",
|
||||
choices: Object.keys(SYSTEM.CORE_SKILLS || {}),
|
||||
label: "Core Skill"
|
||||
})
|
||||
|
||||
// Is this the character's chosen Core Skill?
|
||||
schema.isCoreSkill = new fields.BooleanField({
|
||||
required: true,
|
||||
initial: false,
|
||||
label: "Is Core Skill"
|
||||
})
|
||||
|
||||
// If Core Skill, which attribute receives the +2 bonus?
|
||||
schema.attributeBonus = new fields.StringField({
|
||||
required: true,
|
||||
initial: "",
|
||||
label: "Attribute Bonus"
|
||||
})
|
||||
|
||||
// Skill modifier (includes Core Skill bonus if applicable)
|
||||
schema.modifier = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
required: true,
|
||||
initial: 0,
|
||||
label: "Skill Modifier"
|
||||
})
|
||||
|
||||
// Can perform advanced checks
|
||||
schema.canAdvancedCheck = new fields.BooleanField({
|
||||
required: true,
|
||||
initial: false,
|
||||
label: "Can Perform Advanced Checks"
|
||||
})
|
||||
|
||||
// Associated Core Skill Class (if any)
|
||||
schema.coreSkillClass = new fields.StringField({
|
||||
required: true,
|
||||
initial: "",
|
||||
label: "Core Skill Class"
|
||||
})
|
||||
|
||||
// Notes/Custom description
|
||||
schema.notes = new fields.HTMLField({
|
||||
required: true,
|
||||
initial: "",
|
||||
label: "Notes"
|
||||
})
|
||||
|
||||
return schema
|
||||
@@ -32,83 +78,57 @@ export default class PrismRPGSkill extends foundry.abstract.TypeDataModel {
|
||||
/** @override */
|
||||
static LOCALIZATION_PREFIXES = ["PRISMRPG.Skill"]
|
||||
|
||||
get skillCategory() {
|
||||
return game.i18n.localize(CATEGORY[this.category].label)
|
||||
/**
|
||||
* Get the Core Skill definition from SYSTEM
|
||||
*/
|
||||
get coreSkillDefinition() {
|
||||
return SYSTEM.CORE_SKILLS?.[this.coreSkill] || null
|
||||
}
|
||||
|
||||
validate(options) {
|
||||
let isError = super.validate(options)
|
||||
let bonus = this._source.weaponBonus.attack + this._source.weaponBonus.defense + this._source.weaponBonus.damage
|
||||
if (bonus > Math.floor(this._source.skillTotal / 10)) {
|
||||
ui.notifications.error(game.i18n.localize("PRISMRPG.Skill.error.weaponBonus"))
|
||||
isError = true
|
||||
}
|
||||
return isError
|
||||
/**
|
||||
* Get the localized Core Skill name
|
||||
*/
|
||||
get coreSkillLabel() {
|
||||
const definition = this.coreSkillDefinition
|
||||
return definition ? game.i18n.localize(definition.label) : this.coreSkill
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the available attribute choices for this Core Skill
|
||||
*/
|
||||
get attributeChoices() {
|
||||
const definition = this.coreSkillDefinition
|
||||
return definition?.attributeChoices || []
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare derived data
|
||||
*/
|
||||
prepareDerivedData() {
|
||||
super.prepareDerivedData();
|
||||
this.skillTotal = this.computeBase();
|
||||
if (this.category === "weapon") {
|
||||
this.totalBonus = this.weaponBonus.attack + this.weaponBonus.defense + this.weaponBonus.damage;
|
||||
if (Number(this.skillTotal)) {
|
||||
this.availableBonus = Math.max(Math.floor(this.skillTotal / 10) - 1, 0)
|
||||
} else {
|
||||
this.availableBonus = "N/A"
|
||||
}
|
||||
super.prepareDerivedData()
|
||||
|
||||
// If this is the character's Core Skill, apply bonuses
|
||||
if (this.isCoreSkill) {
|
||||
this.modifier = SYSTEM.CORE_SKILL_BONUS?.basic || 5
|
||||
this.canAdvancedCheck = true
|
||||
} else {
|
||||
this.modifier = 0
|
||||
this.canAdvancedCheck = false
|
||||
}
|
||||
}
|
||||
|
||||
computeBase() {
|
||||
let actor = this.parent?.actor;
|
||||
if (!actor) {
|
||||
return `${this.base} + ${String(this.bonus)}`;
|
||||
}
|
||||
/**
|
||||
* Calculate skill check bonus
|
||||
* @param {string} attributeKey The attribute to use (str, dex, con, int, wis, cha)
|
||||
* @returns {number} Total skill check bonus
|
||||
*/
|
||||
getSkillCheckBonus(attributeKey) {
|
||||
let actor = this.parent?.actor
|
||||
if (!actor) return this.modifier
|
||||
|
||||
if (this.base === "N/A" || this.base === "None") {
|
||||
return this.bonus
|
||||
}
|
||||
const attribute = actor.system.characteristics?.[attributeKey]
|
||||
const attributeMod = attribute?.mod || 0
|
||||
|
||||
// Split the base value per stat : WIS,DEX,STR,INT,CHA (example)
|
||||
let base = this.base;
|
||||
// Fix errors in the base value
|
||||
base.replace("CHARISMA", "CHA");
|
||||
|
||||
if (base.match(/OR/)) {
|
||||
let baseSplit = base.split("OR");
|
||||
let baseSplitLength = baseSplit.length;
|
||||
if (baseSplitLength > 0) {
|
||||
// Select the max stat value from the parent actor
|
||||
let maxStat = 0;
|
||||
for (let i = 0; i < baseSplitLength; i++) {
|
||||
const stat = baseSplit[i].trim();
|
||||
const statValue = actor.system.characteristics[stat.toLowerCase()]?.value || 0;
|
||||
if (statValue > maxStat) {
|
||||
maxStat = statValue;
|
||||
}
|
||||
}
|
||||
return maxStat + this.bonus
|
||||
}
|
||||
} else {
|
||||
if (base.match(/\+/)) {
|
||||
// Split with + calculate the total
|
||||
let baseSplit = base.split("+");
|
||||
let baseSplitLength = baseSplit.length;
|
||||
if (baseSplitLength > 0) {
|
||||
let total = 0;
|
||||
for (let i = 0; i < baseSplitLength; i++) {
|
||||
const stat = baseSplit[i].trim();
|
||||
const statValue = actor.system.characteristics[stat.toLowerCase()]?.value || 0;
|
||||
total += statValue;
|
||||
}
|
||||
return total + this.bonus
|
||||
}
|
||||
} else {
|
||||
// Single stat
|
||||
const statValue = actor.system.characteristics[base.trim().toLowerCase()]?.value || 0;
|
||||
return statValue + this.bonus
|
||||
}
|
||||
}
|
||||
return `${this.base} + ${String(this.bonus)}`;
|
||||
return attributeMod + this.modifier
|
||||
}
|
||||
}
|
||||
|
||||
+141
-20
@@ -1,4 +1,5 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class PrismRPGSpell extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
@@ -11,6 +12,8 @@ export default class PrismRPGSpell extends foundry.abstract.TypeDataModel {
|
||||
initial: "",
|
||||
textSearch: true,
|
||||
})
|
||||
|
||||
// Spell level (1-7+)
|
||||
schema.level = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
initial: 1,
|
||||
@@ -18,28 +21,146 @@ export default class PrismRPGSpell extends foundry.abstract.TypeDataModel {
|
||||
max: 25,
|
||||
})
|
||||
|
||||
schema.cost = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
schema.memorized = new fields.BooleanField({ required: true, initial: false })
|
||||
|
||||
schema.components = new fields.SchemaField({
|
||||
verbal: new fields.BooleanField(),
|
||||
somatic: new fields.BooleanField(),
|
||||
catalyst: new fields.BooleanField(),
|
||||
material: new fields.BooleanField(),
|
||||
// Mana cost - base cost of the spell
|
||||
schema.manaCost = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
required: true,
|
||||
initial: 1,
|
||||
min: 0,
|
||||
label: "Mana Cost"
|
||||
})
|
||||
|
||||
// Mana upkeep cost (for sustained spells)
|
||||
schema.manaUpkeep = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
required: true,
|
||||
initial: 0,
|
||||
min: 0,
|
||||
label: "Mana Upkeep"
|
||||
})
|
||||
|
||||
// APC to cast
|
||||
schema.apc = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
required: true,
|
||||
initial: 1,
|
||||
min: 0,
|
||||
label: "Action Point Cost"
|
||||
})
|
||||
|
||||
// Color/Hue of the spell (from the Prism)
|
||||
schema.color = new fields.StringField({
|
||||
required: true,
|
||||
initial: "violet",
|
||||
choices: Object.keys(SYSTEM.SPELL_COLORS || {}),
|
||||
label: "Spell Color"
|
||||
})
|
||||
|
||||
// Color effect description
|
||||
schema.colorEffect = new fields.HTMLField({
|
||||
required: true,
|
||||
initial: "",
|
||||
label: "Color Effect"
|
||||
})
|
||||
|
||||
// Spell Ascension - can be upcast
|
||||
schema.canAscend = new fields.BooleanField({
|
||||
required: true,
|
||||
initial: true,
|
||||
label: "Can Ascend"
|
||||
})
|
||||
|
||||
schema.ascensionEffect = new fields.HTMLField({
|
||||
required: true,
|
||||
initial: "",
|
||||
label: "Ascension Effect"
|
||||
})
|
||||
|
||||
// Memorized (prepared)
|
||||
schema.memorized = new fields.BooleanField({
|
||||
required: true,
|
||||
initial: false
|
||||
})
|
||||
|
||||
// Components
|
||||
schema.components = new fields.SchemaField({
|
||||
verbal: new fields.BooleanField({ initial: false }),
|
||||
somatic: new fields.BooleanField({ initial: false }),
|
||||
catalyst: new fields.BooleanField({ initial: false }),
|
||||
material: new fields.BooleanField({ initial: false }),
|
||||
})
|
||||
|
||||
schema.materialComponent = new fields.StringField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
schema.catalyst = new fields.StringField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
// Casting parameters
|
||||
schema.castingTime = new fields.StringField({
|
||||
required: true,
|
||||
initial: "1 action"
|
||||
})
|
||||
|
||||
schema.spellRange = new fields.StringField({
|
||||
required: true,
|
||||
initial: "30ft"
|
||||
})
|
||||
|
||||
schema.areaAffected = new fields.StringField({
|
||||
required: true,
|
||||
initial: "Single target"
|
||||
})
|
||||
|
||||
schema.duration = new fields.StringField({
|
||||
required: true,
|
||||
initial: "Instantaneous"
|
||||
})
|
||||
|
||||
schema.savingThrow = new fields.StringField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
// Attack and damage
|
||||
schema.attackRoll = new fields.StringField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
schema.powerRoll = new fields.StringField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
// Keywords
|
||||
schema.keywords = new fields.ArrayField(
|
||||
new fields.StringField()
|
||||
)
|
||||
|
||||
// Legacy fields
|
||||
schema.cost = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
required: true,
|
||||
initial: 0,
|
||||
min: 0
|
||||
})
|
||||
|
||||
schema.extraAetherPoints = new fields.StringField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
schema.criticalType = new fields.StringField({
|
||||
required: true,
|
||||
initial: "electric",
|
||||
choices: SYSTEM.SPELL_CRITICAL
|
||||
})
|
||||
schema.castingTime = new fields.StringField({ required: true, initial: "" })
|
||||
schema.spellRange = new fields.StringField({ required: true, initial: "" })
|
||||
schema.areaAffected = new fields.StringField({ required: true, initial: "" })
|
||||
schema.duration = new fields.StringField({ required: true, initial: "" })
|
||||
schema.savingThrow = new fields.StringField({ required: true, initial: "" })
|
||||
schema.extraAetherPoints = new fields.StringField({ required: true, initial: "" })
|
||||
schema.materialComponent = new fields.StringField({ required: true, initial: "" })
|
||||
schema.catalyst = new fields.StringField({ required: true, initial: "" })
|
||||
schema.criticalType = new fields.StringField({ required: true, initial: "electric", choices : SYSTEM.SPELL_CRITICAL })
|
||||
|
||||
schema.attackRoll = new fields.StringField({ required: true, initial: "" })
|
||||
schema.powerRoll = new fields.StringField({ required: true, initial: "" })
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
|
||||
+124
-37
@@ -1,47 +1,139 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class PrismRPGSkill extends foundry.abstract.TypeDataModel {
|
||||
export default class PrismRPGWeapon extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const schema = {}
|
||||
const requiredInteger = { required: true, nullable: false, integer: true }
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.weaponType = new fields.StringField({ required: true, initial: "melee", choices: SYSTEM.WEAPON_TYPE })
|
||||
schema.weaponClass = new fields.StringField({ required: true, initial: "shortblade", choices: SYSTEM.WEAPON_CLASS })
|
||||
|
||||
// Prism RPG weapon properties
|
||||
schema.weaponType = new fields.StringField({
|
||||
required: true,
|
||||
initial: "light",
|
||||
choices: Object.keys(SYSTEM.WEAPON_TYPE || {})
|
||||
})
|
||||
|
||||
schema.weaponGroup = new fields.StringField({
|
||||
required: true,
|
||||
initial: "longsword",
|
||||
choices: Object.keys(SYSTEM.WEAPON_GROUP || {})
|
||||
})
|
||||
|
||||
// APC (Action Point Cost) - determined by weapon type
|
||||
schema.apc = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
required: true,
|
||||
initial: 1,
|
||||
min: 0,
|
||||
max: 3
|
||||
})
|
||||
|
||||
// Damage dice (e.g., "1d8", "2d6", "1d12")
|
||||
schema.damage = new fields.StringField({
|
||||
required: true,
|
||||
initial: "1d8"
|
||||
})
|
||||
|
||||
// Damage type(s)
|
||||
schema.damageType = new fields.SchemaField({
|
||||
typeP: new fields.BooleanField(),
|
||||
typeB: new fields.BooleanField(),
|
||||
typeS: new fields.BooleanField()
|
||||
})
|
||||
schema.damage = new fields.SchemaField({
|
||||
damageS: new fields.StringField({required: true, initial: ""}),
|
||||
damageM: new fields.StringField({required: true, initial: ""})
|
||||
})
|
||||
schema.applyStrengthDamageBonus = new fields.BooleanField({ required: true, initial: true })
|
||||
|
||||
schema.hands = new fields.StringField({ required: true, initial: "1", choices: {"1": "1", "2": "2"} })
|
||||
schema.isAgile = new fields.BooleanField({ required: true, initial: false })
|
||||
|
||||
schema.defenseMax = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
schema.secondsToAttack = new fields.StringField({required: true, initial: ""})
|
||||
schema.combatProgressionDice = new fields.StringField({required: true, initial: "d4", choices: SYSTEM.COMBAT_PROGRESSION_DICE})
|
||||
|
||||
schema.speed = new fields.SchemaField({
|
||||
simpleAim: new fields.StringField({required: true, initial: ""}),
|
||||
carefulAim: new fields.StringField({required: true, initial: ""}),
|
||||
focusedAim: new fields.StringField({required: true, initial: ""})
|
||||
piercing: new fields.BooleanField({ initial: false }),
|
||||
bludgeoning: new fields.BooleanField({ initial: false }),
|
||||
slashing: new fields.BooleanField({ initial: false })
|
||||
})
|
||||
|
||||
schema.defense = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
schema.weaponRange = new fields.SchemaField({
|
||||
pointBlank: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
short: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
medium: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
long: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
extreme: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
outOfSkill: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
// Group passive (inherited from weapon group)
|
||||
schema.groupPassive = new fields.StringField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
schema.groupPassiveDescription = new fields.HTMLField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
// Weapon-specific passive ability
|
||||
schema.passive = new fields.StringField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
schema.passiveDescription = new fields.HTMLField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
// Maneuver(s) available with this weapon
|
||||
schema.maneuver = new fields.StringField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
schema.maneuverDescription = new fields.HTMLField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
// Augment effects (for equipment progression)
|
||||
schema.augment = new fields.StringField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
schema.augmentDescription = new fields.HTMLField({
|
||||
required: true,
|
||||
initial: ""
|
||||
})
|
||||
|
||||
// Projectile-specific properties
|
||||
schema.isProjectile = new fields.BooleanField({
|
||||
required: true,
|
||||
initial: false
|
||||
})
|
||||
|
||||
schema.range = new fields.SchemaField({
|
||||
short: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
medium: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
long: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
})
|
||||
|
||||
schema.reloadAPC = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
initial: 0,
|
||||
min: 0
|
||||
})
|
||||
|
||||
// Legacy properties (kept for backward compatibility)
|
||||
schema.hands = new fields.StringField({
|
||||
required: true,
|
||||
initial: "1",
|
||||
choices: { "1": "1", "2": "2" }
|
||||
})
|
||||
|
||||
schema.isAgile = new fields.BooleanField({
|
||||
required: true,
|
||||
initial: false
|
||||
})
|
||||
|
||||
schema.applyStrengthDamageBonus = new fields.BooleanField({
|
||||
required: true,
|
||||
initial: true
|
||||
})
|
||||
|
||||
schema.defenseMax = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
required: true,
|
||||
initial: 0,
|
||||
min: 0
|
||||
})
|
||||
|
||||
schema.defense = new fields.NumberField({
|
||||
...requiredInteger,
|
||||
required: true,
|
||||
initial: 0,
|
||||
min: 0
|
||||
})
|
||||
|
||||
schema.bonuses = new fields.SchemaField({
|
||||
@@ -60,9 +152,4 @@ export default class PrismRPGSkill extends foundry.abstract.TypeDataModel {
|
||||
|
||||
/** @override */
|
||||
static LOCALIZATION_PREFIXES = ["PRISMRPG.Weapon"]
|
||||
|
||||
get weaponCategory() {
|
||||
return game.i18n.localize(CATEGORY[this.weaponType].label)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user